Core Function Pack

From Sputnik Wiki
(Difference between revisions)
Jump to: navigation, search
(Data Encoding)
Line 1: Line 1:
 
<pre>
 
<pre>
Pack( <expression>, <expressions> )
+
Pack( <format>, <args> )
 
</pre>
 
</pre>
  
 
=== Description ===
 
=== Description ===
  
Pack data into a binary array
+
Pack data into a binary array.
  
==== expression ====
+
Pack given arguments into a binary string according to format.
  
The format string to use.
+
=== Parameters ===
  
==== expressions ====
+
==== format ====
  
One or more expressions to convert.
+
The format string consists of format codes followed by an optional repeater argument. The repeater argument can be either an integer value or * for repeating to the end of the input data.
  
=== Return Value ===
+
For a, A, b, B, h, H the repeat count specifies how many characters of one data argument are taken, for @ it is the absolute position where to put the next data, for everything else the repeat count specifies how many data arguments are consumed and packed into the resulting binary string.
  
Success: Returns a binary variable which contains the array of bytes.
+
Currently implemented formats are:
  
Failure: Returns null.
+
<pre>
 +
Code Description
 +
a NUL-padded string
 +
A SPACE-padded string
 +
b A bit string (ascending bit order inside each byte, like the Vec() function)
 +
B A bit string (descending bit order inside each byte)
 +
h Hex string, low nibble first
 +
H Hex string, high nibble first
 +
c signed ASCII char
 +
C unsigned ASCII char
 +
w signed UNICODE char
 +
W unsigned UNICODE char
 +
s signed short (always 16 bit, machine byte order)
 +
S unsigned short (always 16 bit, machine byte order)
 +
n unsigned short (always 16 bit, big endian byte order)
 +
v unsigned short (always 16 bit, little endian byte order)
 +
i signed integer (machine dependent size and byte order)
 +
I unsigned integer (machine dependent size and byte order)
 +
l signed long (always 32 bit, machine byte order)
 +
L unsigned long (always 32 bit, machine byte order)
 +
q signed quad (64-bit) value (always 64 bit, machine byte order)
 +
Q unsigned quad (64-bit) value (always 64 bit, machine byte order)
 +
N unsigned long (always 32 bit, big endian byte order)
 +
V unsigned long (always 32 bit, little endian byte order)
 +
f float (machine dependent size and representation)
 +
d double (machine dependent size and representation)
 +
x NUL byte
 +
X Back up one byte
 +
@ NUL-fill to absolute position
 +
</pre>
  
=== Remarks ===
+
==== args ====
  
To access the binary data in the variable you will need to either request elements from index id, cycle through all elements in a loop or use the Unpack function to convert the binary array into something useful.
+
One or more variables to be used in the packing.
  
Its worth noting you can cycle through a Binary variable like this :
+
=== Return Value ===
<syntaxhighlight lang="sputnik">
+
$binary = Pack("z0", "Hello World!");
+
Foreach ($binary as $i)
+
{
+
println( "Byte: " . $i . " | Hex: " . Hex($i) . " | Char: " . Chr($i) );
+
}
+
</syntaxhighlight>
+
  
Or like this :
+
Success: Returns the new binary variable.
<syntaxhighlight lang="sputnik">
+
$binary = Pack("z0", "Hello World!");
+
println( "Byte: $i Hex: {Hex('$i')} Char: {Chr('$i')}" ) Foreach ($binary as $i);
+
</syntaxhighlight>
+
  
==== Control Specifiers ====
+
Failure: Returns null.
  
<pre>
+
=== Remarks ===
Character Description
+
^ Switch to big endian encoding
+
_ Switch to little endian encoding
+
% Switch to host (native) encoding
+
! Aligns the next data type to its natural
+
boundary, for example for a double that
+
would be 8 bytes, for a 32-bit int, that
+
would be 4 bytes. For strings this is set to 4.
+
N A number between 1 and 9, indicates a repeat count
+
(process N items with the following datatype
+
[N] For numbers larger than 9, use brackets, for example [20]
+
* Repeat the next data type until the arguments are exhausted
+
The * on Unpack() with certain formats will cause it to extract
+
                        all remaining bytes to that format for example *H will cause
+
                        Unpack() to extract all remaining bytes and return them as a single hex string
+
(key) For Unpack() ONLY this allows you to set a key for this argument to be placed
+
                        into in the return array so (cat)i will cause the argument to be viewed as an Int32
+
                        and placed into the array as $array['cat'] if the repeat counter is higher than 1
+
                        it may get placed into the array like $array['cat1'] or $array['cat2'] etc
+
</pre>
+
  
==== Data Encoding ====
+
Note that Sputnik stores variables as signed/unsigned as needed which can be confusing if you are a PHP user using this Pack function basically when the format says Unsigned it is literal and the variable will be unsigned/signed as specified both the packing and unpacking.
  
Warning - The pack for $variables is designed to create the bytes of the arrays elements such as array of ints however it does not unpack to a $variable instead you must unpack it as the base type you packed it to such as Int32.
+
This also means if the original value as an Int64 and you packed it with "i" then unpack it with "i" the new value will be an Int32 and not an Int64 since Sputnik sees no need to magically unpack everything to highest data type so "f" will actually give you a Float and not a Double and so on of course that doesn't mean you can't cast it to a double when getting from the return array.
  
<pre>
+
Be aware that if you do not name an element, an empty string is used. If you do not name more than one element, this means that some data is overwritten as the keys are the same
Character Description
+
b A bit string (ascending bit order inside each byte, like the Vec() function)
+
B A bit string (descending bit order inside each byte)
+
h Hex string, low nibble first
+
H Hex string, high nibble first
+
s Int16
+
S UInt16
+
i Int32
+
I UInt32
+
l Int64
+
L UInt64
+
f Float
+
d Double
+
c 1-byte signed character
+
C 1-byte unsigned character
+
vb Binary representation of a Signed character
+
vB Binary representation of a Unsigned character
+
vs Binary representation of a Int16
+
vi Binary representation of a Int32
+
vl Binary representation of a Int64
+
vS Binary representation of a UInt16
+
vI Binary representation of a UInt32
+
vL Binary representation of a UInt64
+
vf Binary representation of a Float
+
vd Binary representation of a Double
+
z8 string encoded as UTF8 with 1-byte null terminator
+
z6 string encoded as UTF16 with 2-byte null terminator
+
z7 string encoded as UTF7 with 1-byte null terminator
+
zb string encoded as BigEndianUnicode with 2-byte null terminator
+
z3 string encoded as UTF32 with 4-byte null terminator
+
z4 string encoded as UTF32 big endian with 4-byte null terminator
+
z1 string encoded as ASCII with 1-byte null terminator
+
z0 string encoded as ASCII without a null terminator
+
x null byte
+
X Back up one byte
+
  
FOR PACK ONLY BELOW
+
=== Example ===
$ac A $variable containing an array of Signed character values
+
$aC A $variable containing an array of Unsigned character values
+
$as A $variable containing an array of Int16 values
+
$aS A $variable containing an array of UInt16 values
+
$ai A $variable containing an array of Int32 values
+
$aI A $variable containing an array of UInt32 values
+
$al A $variable containing an array of Int64 values
+
$aL A $variable containing an array of UInt64 values
+
$af A $variable containing an array of Float values
+
$ad A $variable containing an array of Double values
+
</pre>
+
  
Note - All Sputnik strings are UTF8 by default.
+
<syntaxhighlight lang="sputnik">
 +
$bin = pack("S", 65535);
 +
$ray = unpack("S", $bin);
 +
echo "UNSIGNED SHORT VAL = ", $ray[1], "\n";
  
=== Example ===
+
$bin = pack("S", 65536);
 +
$ray = unpack("S", $bin);
 +
echo "OVERFLOW USHORT VAL = ", $ray[1], "\n";
 +
 
 +
$bin = pack("V", 65536);
 +
$ray = unpack("V", $bin);
 +
echo "SAME AS ABOVE BUT WITH ULONG VAL = ", $ray[1], "\n";
 +
</syntaxhighlight>
  
Converting an array of Ints into bytes then back into an array of ints again:
 
  
 
<syntaxhighlight lang="sputnik">
 
<syntaxhighlight lang="sputnik">
$oldArray = array(100, 200, 300, 400); // Create an array
+
$binarydata = "\x04\x00\xa0\x00";
// Pack the array into bytes with each element converted to Int32
+
$array = Unpack("cchars/nint", $binarydata);
$binary = Pack('$ai', $oldArray); // NOTICE '' was used instead of ""? This is vital when packing variables or else it will fail
+
// The resulting array will contain the entries
Foreach ($binary as $i)
+
// "chars" with value 4 and "int" with 160.  
{
+
printr $array;
println( "Byte: " . $i ); // Prints the bytes just for looksee
+
// Prints:
}
+
// ARRAY
$newArray = Unpack('*i', $binary); // Unpack All the Int32s into an array
+
// {
println("Old Array : " . $oldArray);
+
//        [chars] => 4
println("New Array : " . $newArray);
+
//         [int] => 194
 +
// }
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Same as above but this time packing a float and a double as well :
 
  
 
<syntaxhighlight lang="sputnik">
 
<syntaxhighlight lang="sputnik">
$oldArray = array(100, 200, 300, 400); // Create an array
+
$binarydata = "\x04\x00\xa0\x00";
// Pack the array into bytes with each element converted to Int32
+
$array = Unpack("c2chars/nint", $binarydata);
$binary = Pack('$aifd', $oldArray, (float)777, (double)1337.42); // NOTICE '' was used instead of ""? This is vital when packing variables or else it will fail
+
// The resulting array will contain the entries
Foreach ($binary as $i)
+
// "chars1", "chars2" and "int".  
{
+
printr $array;
println( "Byte: " . $i ); // Prints the bytes just for looksee
+
// Prints:
}
+
// ARRAY
$newArray = Unpack('4ifd', $binary); // Unpack 4 Int32s, 1 float and 1 double into an array
+
// {
println("Old Array : " . $oldArray);
+
//        [chars1] => 4
println("New Array : " . $newArray);
+
//        [chars2] => 0
foreach ($newArray as $i)
+
//        [int] => 49824
{
+
// }
println("Value: " . $i );
+
}
+
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Of course we could set how many Ints to decode dynamically example:
 
  
 
<syntaxhighlight lang="sputnik">
 
<syntaxhighlight lang="sputnik">
$oldArray = array(100, 200, 300, 400); // Create an array
+
$binarydata = Pack("nvc*", 0x1234, 0x5678, 65, 66);
// Pack the array into bytes with each element converted to Int32
+
// The resulting binary string will be 6 bytes long
$binary = Pack('$aifd', $oldArray, (float)777, (double)1337.42); // NOTICE '' was used instead of ""? This is vital when packing variables or else it will fail
+
// and contain the byte sequence 0x12, 0x34, 0x78, 0x56, 0x41, 0x42.  
Foreach ($binary as $i)
+
printr $binarydata;
{
+
// Prints:
println( "Byte: " . $i ); // Prints the bytes just for looksee
+
// {BINARY:6}
}
+
// {
$newArray = Unpack(UBound($oldArray) . 'ifd', $binary); // Unpack 4 Int32s, 1 float and 1 double into an array
+
//         [0] => 18
println("Old Array : " . $oldArray);
+
//         [1] => 52
println("New Array : " . $newArray);
+
//        [2] => 120
foreach ($newArray as $i)
+
//        [3] => 86
{
+
//        [4] => 65
println("Value: " . $i );
+
//        [5] => 66
}
+
// }
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Convert a string into a binary array and back again:
+
Using * to pack all the remaining objects with the same specifier
 
+
 
<syntaxhighlight lang="sputnik">
 
<syntaxhighlight lang="sputnik">
$arr = Pack("z0", "Hello World!");
+
printr pack("C*",80,72,80);
foreach ($arr as $i)
+
{
+
println($i);
+
}
+
$str = Unpack("z0", $arr, true);
+
println($str);
+
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Convert a dobule into a binary array and back again:
+
String to Hex and back again
 
<syntaxhighlight lang="sputnik">
 
<syntaxhighlight lang="sputnik">
$arr = Pack("d", 777.42);
+
function H2Str( $hex )  
foreach ($arr as $i)
+
 
{
 
{
println($i);
+
return pack('H*', $hex);
 
}
 
}
$str = Unpack("d", $arr);
 
println($str);
 
</syntaxhighlight>
 
  
Convert a int into a binary array and back again:
+
function Str2H( $str )
<syntaxhighlight lang="sputnik">
+
$arr = Pack("d", (int)777);
+
foreach ($arr as $i)
+
 
{
 
{
println($i);
+
return unpack('H*', $str, true);
 
}
 
}
$str = Unpack("d", $arr);
+
$txt = 'This is test';
println($str);
+
$hex = Str2H( $txt );
 +
$str = H2Str( $hex );
 +
echo "${txt} => ${hex} => ${str}\n";
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Convert a string into a hex and back again:
+
Display the ASCII character codes for an entire string
 
<syntaxhighlight lang="sputnik">
 
<syntaxhighlight lang="sputnik">
$str = "Hello World!";
+
echo join (unpack('C*', 'abcdef'), ' ');
println("Original String: " . $str);
+
// 97 98 99 100 101 102
$hex = Unpack("*H", $str, true);
+
println("Hex String: " . $hex);
+
$strf = Pack("*H", $hex);
+
println("Normal String: " . $strf);
+
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Convert a string into a hex and back again (alternative using ONLY regex this time):
+
Display the UNICODE character codes for an entire string
 
<syntaxhighlight lang="sputnik">
 
<syntaxhighlight lang="sputnik">
$str = "Hello World!";
+
echo join (unpack('W*', 'こんにちは'), ' ');
println("Orig String: " . $str);
+
// 33251 58259 37762 33251 58283 41345 33251
$str =~ s/(.)/Hex(AscW($1), 2)/ego;
+
println("Hex String: " . $str);
+
$str =~ s/([\dA-Fa-f][\dA-Fa-f])/ChrW(Dec($1))/ego;
+
println("Normal String: " . $str);
+
</syntaxhighlight>
+
 
+
To pack two integers in big endian format, you would use this:
+
<syntaxhighlight lang="sputnik">
+
$bytes = Pack ("^ii", 1234, 4542);
+
</syntaxhighlight>
+
 
+
More Examples:
+
<syntaxhighlight lang="sputnik">
+
; The following means:
+
; Little endian encoding of a Int16, followed by an aligned
+
; int32 value.
+
$r = Pack("_s!i", 0x7b, 0x12345678);
+
foreach ($r as $i)
+
{
+
print(Hex($i) . " ");
+
}
+
// Prints 7B 0 0 0 80 56 34 12
+
 
+
$bytes = Pack("CCCC", 65, 66, 67, 68);
+
foreach ($bytes as $i)
+
{
+
print(Chr($i) . " ");
+
} // Prints 4-byte sequence for "ABCD"
+
 
+
$bytes = Pack("4C", 65, 66, 67, 68);
+
foreach ($bytes as $i)
+
{
+
print(Chr($i) . " ");
+
} // Prints 4-byte sequence for "ABCD"
+
 
+
$bytes = Pack("*C", 65, 66, 67, 68);
+
foreach ($bytes as $i)
+
{
+
print(Chr($i) . " ");
+
} // Prints 4-byte sequence for "ABCD"
+
 
+
$bytes = Pack("^ii", 0x1234abcd, 0x7fadb007);
+
foreach ($bytes as $i)
+
{
+
print(Hex($i) . " ");
+
}
+
println(""); // Result: 12 34 ab cd 7f ad b0 07
+
 
+
// Encode 3 integers as big-endian, but only provides two as arguments,
+
// this defaults to zero for the last value.
+
$bytes = Pack("^iii", 0x1234abcd, 0x7fadb007);
+
foreach ($bytes as $i)
+
{
+
print(Hex($i) . " ");
+
}
+
println(""); // Result: 12 34 ab cd 7f ad b0 07 00 00 00 00
+
 
+
// Encode as little endian, pack 1 short, align, 1 int
+
$bytes = Pack("_s!i", 0x7b, 0x12345678);
+
foreach ($bytes as $i)
+
{
+
print(Hex($i) . " ");
+
}
+
println(""); // Result: 7b 00 00 00 78 56 34 12
+
+
// Encode a string in utf-8 with a null terminator
+
$bytes = Pack("z8", "hello");
+
foreach ($bytes as $i)
+
{
+
print(Hex($i) . " ");
+
}
+
println(""); // Result: 68 65 6c 6c 6f 00 00 00 00
+
+
// Little endian encoding, for Int16, followed by an aligned
+
// Int32
+
$bytes = Pack("_s!i", 0x7b, 0x12345678);
+
foreach ($bytes as $i)
+
{
+
print(Hex($i) . " ");
+
}
+
println(""); // Result: 7b 00 00 00 78 56 34 12
+
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
[[Category:Core Function]]
 
[[Category:Core Function]]

Revision as of 14:02, 26 September 2013

Pack( <format>, <args> )

Contents

Description

Pack data into a binary array.

Pack given arguments into a binary string according to format.

Parameters

format

The format string consists of format codes followed by an optional repeater argument. The repeater argument can be either an integer value or * for repeating to the end of the input data.

For a, A, b, B, h, H the repeat count specifies how many characters of one data argument are taken, for @ it is the absolute position where to put the next data, for everything else the repeat count specifies how many data arguments are consumed and packed into the resulting binary string.

Currently implemented formats are:

Code 	Description
a 	NUL-padded string
A 	SPACE-padded string
b 	A bit string (ascending bit order inside each byte, like the Vec() function)
B 	A bit string (descending bit order inside each byte)
h 	Hex string, low nibble first
H 	Hex string, high nibble first
c	signed ASCII char
C 	unsigned ASCII char
w	signed UNICODE char
W 	unsigned UNICODE char
s 	signed short (always 16 bit, machine byte order)
S 	unsigned short (always 16 bit, machine byte order)
n 	unsigned short (always 16 bit, big endian byte order)
v 	unsigned short (always 16 bit, little endian byte order)
i 	signed integer (machine dependent size and byte order)
I 	unsigned integer (machine dependent size and byte order)
l 	signed long (always 32 bit, machine byte order)
L 	unsigned long (always 32 bit, machine byte order)
q 	signed quad (64-bit) value (always 64 bit, machine byte order)
Q 	unsigned quad (64-bit) value (always 64 bit, machine byte order)
N 	unsigned long (always 32 bit, big endian byte order)
V 	unsigned long (always 32 bit, little endian byte order)
f 	float (machine dependent size and representation)
d 	double (machine dependent size and representation)
x 	NUL byte
X 	Back up one byte
@ 	NUL-fill to absolute position

args

One or more variables to be used in the packing.

Return Value

Success: Returns the new binary variable.

Failure: Returns null.

Remarks

Note that Sputnik stores variables as signed/unsigned as needed which can be confusing if you are a PHP user using this Pack function basically when the format says Unsigned it is literal and the variable will be unsigned/signed as specified both the packing and unpacking.

This also means if the original value as an Int64 and you packed it with "i" then unpack it with "i" the new value will be an Int32 and not an Int64 since Sputnik sees no need to magically unpack everything to highest data type so "f" will actually give you a Float and not a Double and so on of course that doesn't mean you can't cast it to a double when getting from the return array.

Be aware that if you do not name an element, an empty string is used. If you do not name more than one element, this means that some data is overwritten as the keys are the same

Example

$bin = pack("S", 65535);
$ray = unpack("S", $bin);
echo "UNSIGNED SHORT VAL = ", $ray[1], "\n";
 
$bin = pack("S", 65536);
$ray = unpack("S", $bin);
echo "OVERFLOW USHORT VAL = ", $ray[1], "\n";
 
$bin = pack("V", 65536);
$ray = unpack("V", $bin);
echo "SAME AS ABOVE BUT WITH ULONG VAL = ", $ray[1], "\n";


$binarydata = "\x04\x00\xa0\x00";
$array = Unpack("cchars/nint", $binarydata);
// The resulting array will contain the entries
// "chars" with value 4 and "int" with 160. 
printr $array;
// Prints:
// ARRAY
// {
//         [chars] => 4
//         [int] => 194
// }


$binarydata = "\x04\x00\xa0\x00";
$array = Unpack("c2chars/nint", $binarydata);
// The resulting array will contain the entries
// "chars1", "chars2" and "int". 
printr $array;
// Prints:
// ARRAY
// {
//         [chars1] => 4
//         [chars2] => 0
//         [int] => 49824
// }


$binarydata = Pack("nvc*", 0x1234, 0x5678, 65, 66);
// The resulting binary string will be 6 bytes long
// and contain the byte sequence 0x12, 0x34, 0x78, 0x56, 0x41, 0x42. 
printr $binarydata;
// Prints:
// {BINARY:6}
// {
//         [0] => 18
//         [1] => 52
//         [2] => 120
//         [3] => 86
//         [4] => 65
//         [5] => 66
// }

Using * to pack all the remaining objects with the same specifier

printr pack("C*",80,72,80);

String to Hex and back again

function H2Str( $hex ) 
{
	return pack('H*', $hex);
}
 
function Str2H( $str )
{
	return unpack('H*', $str, true);
}
$txt = 'This is test';
$hex = Str2H( $txt );
$str = H2Str( $hex );
echo "${txt} => ${hex} => ${str}\n";

Display the ASCII character codes for an entire string

echo join (unpack('C*', 'abcdef'), ' ');
// 97 98 99 100 101 102

Display the UNICODE character codes for an entire string

echo join (unpack('W*', 'こんにちは'), ' ');
// 33251 58259 37762 33251 58283 41345 33251
Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox