Fixed length string with CString embedded

56 views
Skip to first unread message

Lou King

unread,
Aug 11, 2015, 7:03:36 AM8/11/15
to Construct
I just discovered construct yesterday. Wow, great package!

I am parsing a binary file which has fixed length strings that are null terminated. Some of these seem to have garbage after the null termination.

I think the way to handle this is to make a Union of Padding, CString, or maybe Peek(CString), then Padding. Or maybe another way.

Is there a "best" way to handle this?

Also is there example of how to create new macro to encapsulate such things? I see http://construct.readthedocs.org/en/latest/extending.html but this talks about creating an Adapter, not the macro which uses that adapter. I started looking at the code, but I think many here have the construct experience I am lacking and could quickly supply a code snippet.

Thanks in advance.

Frank Carney

unread,
Aug 11, 2015, 1:11:06 PM8/11/15
to Construct
Yes, a union would work great.  You can also define it separately:
special_union = embed(struct("na"
 
union(
    cstring
(),
   
char(length),
 
)
))

I don't know if I have the syntax right, but you get the idea.  There might be a way to call a function that returns the construct object you want with the length of the space you want.  I show the way above because then you can use the special_union in your code later inside other construct statements.

Lou King

unread,
Aug 11, 2015, 3:16:23 PM8/11/15
to Construct
Thanks. With your hints I was able to get this code to work

#------------------------------------------------------------------------------------------
def FixedCString(name, length, terminators=six.b("\x00"), encoding=None):
#------------------------------------------------------------------------------------------

    fixedcstring = Embedded( Struct (None, 
            Peek (CString (name, terminators=terminators, encoding=encoding)),
            Padding (length), 
        )
    )

    return fixedcstring

to wit

>>> teststruct = Struct('all', FixedCString('cstring',20), String('string',4))
>>> testcstring = 'Pale Malt(2-row)\x00(2-row)\x00ow)'
>>> 
testcstring[0:20]
'Pale Malt(2-row)\x00(2-'
>>> test = teststruct.parse(testcstring)
>>> print test
Container:
    cstring = 'Pale Malt(2-row)'
    string = 'row)'

Arek Bulski

unread,
Sep 26, 2016, 10:49:51 AM9/26/16
to Construct
No idea what all these contraptions are for. String() is fixed sized and has a padchar/paddir arguments that allow for stripping it during parsing.

Basil Peace

unread,
Oct 31, 2016, 5:56:32 PM10/31/16
to Construct
String()'s padchar doesn't help if there is garbage after the null termination.
Reply all
Reply to author
Forward
0 new messages