I am trying to use struct.unpack()
to take apart a data record that ends with an ASCII string.
The record (it happens to be a TomTom ov2 record) has this format (stored little-endian):
- 1 byte
- 4 byte int for total record size (including this field)
- 4 byte int
- 4 byte int
- variable-length string, null-terminated
unpack()
requires that the string's length be included in the format you pass it. I can use the second field and the known size of the rest of the record -- 13 bytes -- to get the string length:
str_len = struct.unpack("<xi", record[:5])[0] - 13
fmt = "<biii{0}s".format(str_len)
then proceed with the full unpacking, but since the string is null-terminated, I really wish unpack()
would do it for me. It'd also be nice to have this should I run across a struct that doesn't include its own size.
How can I make that happen?
I made two new functions that should be useable as drop-in replacements for the standard pack and unpack functions. They both support the 'z' character to pack/unpack an ASCIIZ string. There are no restrictions to the location or number of occurrences of the 'z' character in the format string:
Here's an example of how to use them:
The size-less record is fairly easy to handle, actually, since
struct.calcsize()
will tell you the length it expects. You can use that and the actual length of the data to construct a new format string forunpack()
that includes the correct string length.This function is just a wrapper for
unpack()
, allowing a new format character in the last position that will drop the terminal NUL: