pack
pack(template, …)
This function packs one or more values into a binary data structure, returning a byte string containing the structure. This is very similar to the Perl function of the same name. The template parameter is a sequence of characters that specify the type of each value, as follows:
• a — an ASCII string, null padded
• A — an ASCII string, blank value
• c — a signed character value
• C — an unsigned character value
• d — a double-precision floating point number in native format
• f — a single-precision floating point number in native format
• i — a signed integer (32–bit) value
• I — an unsigned integer (32–bit) value
• l — a signed long value
• L — an unsigned long value
• n — a short integer value in network (big-endian) order
• N — a long (32–bit) value in network (big-endian) order
• p — a pointer to a null terminated string
• s — a signed short (16–bit) value
• S — an unsigned short (16–bit) value
• x — a null byte
• X — back up a byte
• z — a Unicode string in big-endian (network) order, null padded
• Z — a Unicode string in little-endian order, null padded
• @ — null fill to absolute position
Each character may be followed by a number that specifies a repeat count. The character and repeat count comprise a field specifier. Field specifiers may be separated by white space. For all type specifiers except a, A, x, X, and @, the repeat count specifies how many values from the list of arguments are to be used. For example:
pack("s2", 1, 2)
packs values 1 and 2, into a structure of 2 shorts. If the repeat count is *, then all remaining values are used, for example:
pack("i*", 3, 4, 5, 6)
produces a structure of four integers.
The repeat code for z and Z is the number of Unicode characters. Thus, z4 results in 8-bytes written to the packed string. To get a blank-padded Unicode string, use:
pack("z20", ustr . dupl(" ", 20 - length(ustr)))
For specifiers a and A, only a single value is used. The repeat count specifies the size of the output string, padded with nulls if a, or space if A was given. The type specifiers x, X, and @ do not use up any values. The repeat count for x and X specify how much of the output string should be expanded or contracted. @ is similar to x but the repeat count specifies an absolute instead of relative position.
Since Arbortext Editor does not support floating point as a basic type, the values corresponding to the f and d type specifiers must be written as strings. For example:
pack("df", "1.5e-4", "72.27")
The binary representation of real numbers is the native machine format which is not portable.
If an argument specifies an array name, then all the elements of the array from 1 to high_bound( array name ) are used if the template specifies enough fields. For example,
split("1 2 3 4 5", array)
split("1 2 3 4 5", array)
n5 = pack("i*", arry)
generates a structure of 5 integers. Currently, there is a limit of 250 field values.
The following three examples generate a string of four characters (and are equivalent):
pack("cccc", 97, 98, 99, 100)
pack("c4", 97, 98, 99, 100)
pack("a4", "abcdefg")
Note that in the latter case, only the first four characters of the value are used.
The example that follows involves writing a port number in network order to a network channel (possibly connected to a non-Intel based machine):
write(ch, pack("n",portno))
If the other end was a Arbortext Editor client, unpack would be used to convert the port number. For example:
read(ch, buf, 2)
portno = unpack("n", buf)
pack may also be used to preallocate a string to a particular size, for example,
str = pack("x1000");str = ''
creates a string of 1000 bytes and gives it a null initial value. This is useful in cases where a large string is created by appending many small strings using the concatenation assignment operator .= in a loop. Preallocating the string to a size close to the final size reduces the number of times Arbortext Editor has to reallocate the string as characters are appended. This also reduces the execution time needed for the loop.
To pack a Unicode character, use s or n. For example,
pack("s2", ord("a"), chr(0x2665))
The a and A designators convert a Unicode string into a possibly multi-byte string in the system character set. Note, if a field length is specified, for example, a7, this could result in a partial character being stored if the system character set is a multi-byte character set.
If you are converting a Unicode string parameter to an 8-bit string for passing to a dynamic library, it is best to pass the string as a parameter to the dl_call function and let dl_call to the conversion for you. One case in which it is necessary to use pack is if the parameter is an output parameter and one needs to allocate enough space to hold the return value. Then the ACL code will need to use pack with something like "a2000" to allocate a big enough string to hold the result. Note that this assumes that the DLL is an 8-bit DLL and conversion is necessary.
Related Topics