Struct implementation in PHP. It supports decoding binary files.
Creating a new struct
$myStruct_t = new Struct(
"foo", uint32_t, //single uint32_t
"baz", uint8_t, 30 //array of 30 unsigned chars
);
You can specify flags for a members, such as:
$myStruct_t = new Struct(
"beval", uint32_t, 1, ENDIAN_BIG, //big endian value
"leval", uint32_t, 1, ENDIAN_LITTLE, //little endian value
"myString", int8_t, 32, VAR_STRING, //string of 32 characters
"myNumber", uint32_t, 1, VAR_NUMERIC, //explicitly uses the PHP's int type
);
You can use FLAG_STRSZ to indicate that this member will specify the size of an upcoming string
$string_t = new Struct(
"strSz", uint32_t, 1, FLAG_STRSZ, //a string follow, and its length is indicated by this member
"varString", uint8_t, 0, //the size will be replaced at runtime due to FLAG_STRSZ
);
The use of FLAG_STRSZ makes a structure size unpredictable.
You can also use nested structures:
$myStruct_t = new Struct(
"foo", uint32_t, //single uint32_t
"baz", uint8_t, 30 //array of 30 unsigned chars
);
$otherStruct_t = new Struct(
"magic", uint8_t, 4,
"elements", $myStruct_t, 32, //creates an array of 32 structures
);
Structs and files:
// Clone the structure template
$header = clone($header_t);
// Simple check for proper arguments
if($argc < 2 || !file_exists($argv[1])){
fprintf(STDERR, "File not found!\n");
return 1;
}
// Open the specified file in read mode
$f = fopen($argv[1], "rb");
// Get enough data to fill the structure
$d = fread($f, $header->getSize());
// We don't need the file anymore
fclose($f);
// Put the data we read into the structure
$header->apply($d);
Parsing the elements
printf("Struct size: %d\n", $header->getSize());
foreach($header->members as $name => $member){
printf("member '%s', value: 0x%x\n", $name, $member->getValue());
}
And for nested structures?
function printStruct($struct){
foreach($struct->members as $name => $memb){
$value = $memb->getValue();
if(is_array($value)){
if(Struct::isStructArray($value)){
foreach($value as $subStruct){
printStruct($subStruct);
}
} else {
//print array of bytes/elements
printf("%s\n", $name);
var_dump($value);
}
} else {
//print element/value
printf("%s => 0x%x\n", $name, $value);
}
}
}
Getting the binary data of a member/struct
$binaryData = $member->getData();
Setting the binary data of a member (use this to set strings!)
$member->setData($binData);
Getting the decoded value of a member (according to its type).
$value = $member->getValue();
Setting the value of a member (will get encoded according to its type).
NOTE: for strings use setData, or you'll need to pass a char array to this function
$member->setValue($value);