def GreedyString(name, encoding=None, char_field=Field(None, 1)): r""" A configurable, variable-length string field. :param name: name :param encoding: encoding (e.g. "utf8") or None for no encoding :param char_field: construct representing a single character Example:: >>> foo = GreedyString("foo") >>> foo.parse(b"hello\x00") b'hello\x00' >>> foo.build(b"hello\x00") b'hello\x00' >>> foo.parse(b"hello") b'hello' >>> foo.build(b"hello") b'hello' """ return Rename( name, StringAdapter( OptionalGreedyRange(char_field), encoding=encoding, ))
def StringUpto(name, terminators, consume_terminator = False, allow_eof = True): """a string that stretches up to a terminator, or EOF. this is a more flexible version of CString. * name - the name of the field * terminator - the set of terminator characters * consume_terminator - whether to consume the terminator character. the default is False. * allow_eof - whether to allow EOF to terminate the string. the default is True. this option is applicable only if consume_terminator is set. """ con = StringAdapter(OptionalGreedyRange(CharNoneOf(name, terminators))) if not consume_terminator: return con if allow_eof: term = Optional(CharOf(None, terminators)) else: term = CharOf(None, terminators) return IndexingAdapter(Sequence("foo", con, term), index = 0)
def String(name, length, encoding=None, padchar=None, paddir="right", trimdir="right"): r""" A configurable, fixed-length string field. The padding character must be specified for padding and trimming to work. :param name: name :param length: length, in bytes :param encoding: encoding (e.g. "utf8") or None for no encoding :param padchar: optional character to pad out strings :param paddir: direction to pad out strings; one of "right", "left", or "both" :param str trim: direction to trim strings; one of "right", "left" Example:: >>> from construct import String >>> String("foo", 5).parse("hello") 'hello' >>> >>> String("foo", 12, encoding = "utf8").parse("hello joh\xd4\x83n") u'hello joh\u0503n' >>> >>> foo = String("foo", 10, padchar = "X", paddir = "right") >>> foo.parse("helloXXXXX") 'hello' >>> foo.build("hello") 'helloXXXXX' """ con = StringAdapter(Field(name, length), encoding=encoding) if padchar is not None: con = PaddedStringAdapter(con, padchar=padchar, paddir=paddir, trimdir=trimdir) return con
def PascalString(name, length_field=UBInt8("length"), encoding=None): r""" A length-prefixed string. ``PascalString`` is named after the string types of Pascal, which are length-prefixed. Lisp strings also follow this convention. The length field will appear in the same ``Container`` as the ``PascalString``, with the given name. :param name: name :param length_field: a field which will store the length of the string :param encoding: encoding (e.g. "utf8") or None for no encoding Example:: >>> foo = PascalString("foo") >>> foo.parse("\x05hello") 'hello' >>> foo.build("hello world") '\x0bhello world' >>> >>> foo = PascalString("foo", length_field = UBInt16("length")) >>> foo.parse("\x00\x05hello") 'hello' >>> foo.build("hello") '\x00\x05hello' """ return StringAdapter( LengthValueAdapter( Sequence( name, length_field, Field("data", lambda ctx: ctx[length_field.name]), )), encoding=encoding, )
def Word(name): """a sequence of letters""" return StringAdapter(GreedyRange(Alpha(name)))