From Serious Documentation
Jump to: navigation, search
Function Returns Introduced Description
bytesToString String v5.0.207 Builds a string from the ASCII bytes of an Integer, Short, or Byte until a 0x00 byte is encountered or the number of bytes of the size of the object are consumed. Optionally, non-printable characters can be replaced as-encountered. All byte orderings are supported.

See Also:


String bytesToString(Float/Integer/Short/Byte number, Byte nBytes);

String bytesToString(Float/Integer/Short/Byte number, Byte nBytes, ByteOrder byteOrder);

String bytesToString(Float/Integer/Short/Byte number, Byte nBytes, ByteOrder byteOrder, Codepoint replacement );

Parameters/Return Value

Parameter Data Type Description
number Float
Number to convert.
The size of the source type drives the maximum number of bytes to convert; constants are assumed to have the least number of representation bytes.
nBytes Byte Maximum number of bytes to process in the object. All values are promoted to signed Integer at runtime, but on a maximum of nBytes are processed in the byteOrder specified (or BYTEORDER.BIG_ENDIAN if unspecified).
byteOrder ByteOrder Byte order to analyze the source number with; default is BYTEORDER.BIG_ENDIAN (optional)
replacement Codepoint If a non-printable character (0x01-0x1F) is encountered, this UTF8 Codepoint is inserted into the string instead. 0x00 is permitted here and terminates the string upon encountering a non-printable byte. Any Unicode Codepoint is permitted.
Return String Character string

Detailed Description

The bytesToString() function returns the character string representing the 8, 16, or 32-bit ASCII byte sequence held in the number specified.

For example, the 32-bit integer 0x53484950 is a big endian order representation of "SHIP".

The most common use of this function is when receiving Modbus or other communications variables from a remote system that are encoding strings or character sequences. For example, the remote end may pass Short variables with 2-letter codes describing the state of a machine; say 0x444F or "DO" for Door Open. You may want to display these codes in your GUI, and so converting them to a String is desirable. One option in this example is

String = codepointToString((x>>8)&0x0FF) + codepointToString(x&0x0FF);

But this technique gets cumbersome with Integer variables. Further, what if the encoding in the number has non-printable characters you wish to replace, and/or you may encounter a string-ending 0x00 byte in the sequence? The method above does not handle these cases.

The bytesToString() function makes parsing these objects much simpler.

Size of Source Object

Numeric operands in SHIP are always promoted to 32-bit signed numbers during mathematical manipulation and assignment. Since all number types in SHIP are signed, all 32-bit values used in math are signed Integer values. When a smaller variable or const objects (i.e. (Byte or Short) are supplied in expressions, they will be sign extended to the full 32-bits. For example, a const such as 0x99 will always be sign extended to 0xFFFFFF99 during use.

With the bytesToString function, this can cause some interesting side effects. Consider bytesToString(0x81) which would, ideally, should return "™". However, because of sign extension and 32-bit promotion, the 0x99 will be promoted to 0xFFFFFF99 and the full return from the bytesToString(0x99) would be "ÿÿÿ™". This is rarely the desirable outcome.

Therefore there is an additional mandatory parameter, nBytes, which helps address this issue. Note the byte ordering (see below) is performed in advance of the characters being processed.

You still need to take care that you're processing the bytes you truly desire. For example, if a single byte is desired to be processed from the lowest byte position of a 32-bit value, using bytesToString(0x99,1) will not generate the expected "™" because the default byte ordering is big Endian, and the first byte processed (of the 1 allowed by the nBytes parameter) is a sign-extended 0xFF. To get the correct result, one should specify in this case bytesToString(0x99,1,BYTEORDER.LITTLE_ENDIAN);.

Byte Ordering

Often the bytes in the number object are not in the same order. Often communications Integer values come in big Endian, but other times you may have all sorts of needs for the 4 different byte orderings of a 32-bit value (or 2 for a 16-bit value).

The optional parameter allows you to manipulate the byte ordering that the object is processed in. The ByteOrder value is similar to that supported in linkset nodes to convert incoming data, and a typical value might be BYTEORDER.SWAP8 to swap pairs of 8-bit values in a 16- or 32-bit number.


Example Result Notes
bytesToString(0x53,1); "" The bytes are sign extended to 0x00000053, and processed by default in big Endian order, so the first byte encountered is a 0x00 which ends the string.
bytesToString(0x53,1,BYTEORDER.LITTLE_ENDIAN); "S"
bytesToString(0x53484950,4); "SHIP"
bytesToString(0x53484900,4); "SHI"
bytesToString(0x53480050,4); "SH" Early terminated when 0x00 encountered in 3rd byte.
bytesToString(0x53484950,4,BYTEORDER.LITTLE_ENDIAN); "PIHS" All 4 bytes endian flipped.
bytesToString(0x53484950,4,BYTEORDER.BIG_ENDIAN,0x3F); "SHIP" All bytes are printable, so the replacement character 3F ('?') is unused.
bytesToString(0x53480350,4,BYTEORDER.BIG_ENDIAN,0x3F); "SH?P" The third byte, 0x03 is unprintable, so it is replaced with the replacement character 3F ('?').
bytesToString(0x53480350,4,BYTEORDER.BIG_ENDIAN,0x2573); "SH╳P" The third byte, 0x03 is unprintable, so it is replaced with the extended UTF8 replacement character 0x2573, the diagonal cross ('╳'). Note for this to be visible in your GUI this character must be present in your font.