示例#1
0
 def test_from_bytearray(self):
     self.assert_length_value(8, b'\x00',
                              BitString.from_bytearray(b'\x00'))
     self.assert_length_value(16, b'ab',
                              BitString.from_bytearray(b'ab'))
     self.assert_length_value(
         16, b'ab', BitString.from_bytearray(bytearray(b'ab')))
示例#2
0
 def test_from_sequence(self):
     self.assert_length_value(
         8, b'\x01', BitString.from_sequence([1], BitString.from_byte))
     self.assert_error(
         lambda: BitString.from_sequence([256], BitString.from_byte))
     self.assert_length_value(
         16, b'\x01\x02',
         BitString.from_sequence([1, 2], BitString.from_byte))
示例#3
0
 def dispatch_table(big_endian=True, encoding=None, errors=STRICT):
     '''
     Convert types appropriately.
     '''
     # pylint: disable-msg=W0108
     # consistency
     return {int: lambda n: BitString.from_int(n, ordered=big_endian),
             str: lambda s: BitString.from_str(s, encoding, errors),
             bytes: lambda b: BitString.from_bytearray(b),
             bytearray: lambda b: BitString.from_bytearray(b),
             BitString: lambda x: x}
示例#4
0
 def test_add(self):
     acc = BitString()
     for i in range(8):
         acc += BitString.from_int('0o' + str(i))
     # >>> hex(0o76543210)
     # '0xfac688'
     self.assert_length_value(24, b'\x88\xc6\xfa', acc)
     acc = BitString()
     for i in range(7):
         acc += BitString.from_int('0o' + str(i))
     self.assert_length_value(21, b'\x88\xc6\x1a', acc)
示例#5
0
 def test_add(self):
     acc = BitString()
     for i in range(8):
         acc += BitString.from_int('0o' + str(i))
     # >>> hex(0o76543210)
     # '0xfac688'
     self.assert_length_value(24, b'\x88\xc6\xfa', acc)
     acc = BitString()
     for i in range(7):
         acc += BitString.from_int('0o' + str(i))
     self.assert_length_value(21, b'\x88\xc6\x1a', acc)
示例#6
0
 def dispatch_table(big_endian=True, encoding=None, errors=STRICT):
     '''
     Convert types appropriately.
     '''
     # pylint: disable-msg=W0108
     # consistency
     return {
         int: lambda n: BitString.from_int(n, ordered=big_endian),
         str: lambda s: BitString.from_str(s, encoding, errors),
         bytes: lambda b: BitString.from_bytearray(b),
         bytearray: lambda b: BitString.from_bytearray(b),
         BitString: lambda x: x
     }
示例#7
0
 def assert_round_trip(self, start, stop=None, length=None):
     if stop is None:
         stop = start
     result = BitString.from_int(start, length=length).to_int()
     assert result == stop, (result, stop)
     if length is not None:
         assert len(result) == length, (result, length)
示例#8
0
 def assert_round_trip(self, start, stop=None, length=None):
     if stop is None:
         stop = start
     result = BitString.from_int(start, length=length).to_int()
     assert result == stop, (result, stop)
     if length is not None:
         assert len(result) == length, (result, length)
示例#9
0
 def matcher(value=None):
     """
     Generate the matcher, given a value.
     """
     if value is None:
         return LEnd(length)
     else:
         return _Constant(BitString.from_int(value, length=length, big_endian=False))
示例#10
0
 def Byte(value=None):
     '''
     Match or read a byte (if a value is given, it must match).
     '''
     if value is None:
         return BEnd(8)
     else:
         return _Constant(BitString.from_byte(value))
示例#11
0
 def String(value, encoding=None, errors=STRICT):
     """
     Match or read a string (to read a value, give the number of bytes).
     """
     if isinstance(value, int):
         return _String(value, encoding=encoding, errors=errors)
     else:
         return _Constant(BitString.from_str(value, encoding=encoding, errors=errors))
示例#12
0
 def Byte(value=None):
     '''
     Match or read a byte (if a value is given, it must match).
     '''
     if value is None:
         return BEnd(8)
     else:
         return _Constant(BitString.from_byte(value))
示例#13
0
 def ByteArray(value):
     '''
     Match or read an array of bytes (to read a value, give the number 
     of bytes).
     '''
     if isinstance(value, int):
         return _ByteArray(value)
     else:
         return _Constant(BitString.from_bytearray(value))
示例#14
0
 def matcher(value=None):
     '''
     Generate the matcher, given a value.
     '''
     if value is None:
         return LEnd(length)
     else:
         return _Constant(
             BitString.from_int(value, length=length, big_endian=False))
示例#15
0
 def String(value, encoding=None, errors=STRICT):
     '''
     Match or read a string (to read a value, give the number of bytes).
     '''
     if isinstance(value, int):
         return _String(value, encoding=encoding, errors=errors)
     else:
         return _Constant(
             BitString.from_str(value, encoding=encoding, errors=errors))
示例#16
0
 def matcher(value=None):
     '''
     Generate the matcher, given a value.
     '''
     if value is None:
         return BEnd(length)
     else:
         return _Constant(BitString.from_int(value, length=length, 
                                             big_endian=True))
示例#17
0
 def ByteArray(value):
     '''
     Match or read an array of bytes (to read a value, give the number 
     of bytes).
     '''
     if isinstance(value, int):
         return _ByteArray(value)
     else:
         return _Constant(BitString.from_bytearray(value))
示例#18
0
 def test_get_item(self):
     a = BitString.from_int('01001100011100001111b0')
     b = a[:]
     assert a == b, (a, b)
     b = a[0:]
     assert a == b, (a, b)
     b = a[-1::-1]
     assert BitString.from_int('11110000111000110010b0') == b, b
     b = a[0]
     assert BitString.from_int('0b0') == b, (b, str(b), BitString.from_int('0b0'))
     b = a[1]
     assert BitString.from_int('1b0') == b, b
     b = a[0:2]
     assert BitString.from_int('01b0') == b, b
     b = a[0:2]
     assert BitString.from_int('0b10') == b, b
     b = a[-5:]
     assert BitString.from_int('01111b0') == b, b
     b = a[-1:-6:-1]
     assert BitString.from_int('11110b0') == b, b
     b = a[1:-1]
     assert BitString.from_int('100110001110000111b0') == b, b
示例#19
0
        def test_encode(self):
            mac = parse('''
    Frame(
      Header(
        preamble  = 0b10101010*7,
        start     = 0b10101011,
        destn     = 010203040506x0,
        source    = 0708090a0b0cx0,
        ethertype = 0800x0
      ),
      Data(1/8,2/8,3/8,4/8),
      CRC(234d0/4.)
    )
    ''')

            serial = simple_serialiser(mac, dispatch_table())
            bs = serial.bytes()
            for _index in range(7):
                b = next(bs)
                assert b == BitString.from_int('0b10101010').to_int(), b
            b = next(bs)
            assert b == BitString.from_int('0b10101011').to_int(), b
示例#20
0
 def test_get_item(self):
     a = BitString.from_int('01001100011100001111b0')
     b = a[:]
     assert a == b, (a, b)
     b = a[0:]
     assert a == b, (a, b)
     b = a[-1::-1]
     assert BitString.from_int('11110000111000110010b0') == b, b
     b = a[0]
     assert BitString.from_int('0b0') == b, (b, str(b),
                                             BitString.from_int('0b0'))
     b = a[1]
     assert BitString.from_int('1b0') == b, b
     b = a[0:2]
     assert BitString.from_int('01b0') == b, b
     b = a[0:2]
     assert BitString.from_int('0b10') == b, b
     b = a[-5:]
     assert BitString.from_int('01111b0') == b, b
     b = a[-1:-6:-1]
     assert BitString.from_int('11110b0') == b, b
     b = a[1:-1]
     assert BitString.from_int('100110001110000111b0') == b, b
示例#21
0
 def test_invert(self):
     #basicConfig(level=DEBUG)
     self.assert_length_value(12, b'\x00\x0c',
                              ~BitString.from_int('0x3ff'))
示例#22
0
 def test_str(self):
     b = BitString.from_int32(0xabcd1234)
     assert str(b) == '00101100 01001000 10110011 11010101b0/32', str(b)
     b = BitString.from_int('0b110')
     assert str(b) == '011b0/3', str(b)
示例#23
0
 def test_from_int_with_length(self):
     self.assert_error(lambda: BitString.from_int(1, 0))
     self.assert_error(lambda: BitString.from_int(0, 1))
     self.assert_error(lambda: BitString.from_int(0, 7))
     self.assert_length_value(8, b'\x00', BitString.from_int(0, 8))
     self.assert_error(lambda: BitString.from_int(0, 0.1))
     self.assert_length_value(8, b'\x00', BitString.from_int(0, 1.))
     self.assert_length_value(1, b'\x00', BitString.from_int('0x0', 1))
     self.assert_length_value(7, b'\x00', BitString.from_int('0x0', 7))
     self.assert_length_value(8, b'\x00', BitString.from_int('0x0', 8))
     self.assert_length_value(1, b'\x00',
                              BitString.from_int('0x0', 0.1))
     self.assert_length_value(8, b'\x00', BitString.from_int('0x0', 1.))
     self.assert_length_value(16, b'\x34\x12',
                              BitString.from_int(0x1234, 16))
     self.assert_length_value(16, b'\x34\x12',
                              BitString.from_int('0x1234', 16))
     self.assert_length_value(16, b'\x12\x34',
                              BitString.from_int('1234x0', 16))
     self.assert_length_value(16, b'\x34\x12',
                              BitString.from_int('4660', 16))
     self.assert_length_value(16, b'\x34\x12',
                              BitString.from_int('0d4660', 16))
     self.assert_length_value(16, b'\x12\x34',
                              BitString.from_int('4660d0', 16))
示例#24
0
 def bassert(self, value, expected, length=None):
     x = BitString.from_int(expected, length)
     assert value == x, (value, x)
示例#25
0
    def make_binary_parser():
        '''
        Create a parser for binary data.
        '''
        
        # avoid import loops
        from lepl import Word, Letter, Digit, UnsignedInteger, \
            Regexp, DfaRegexp, Drop, Separator, Delayed, Optional, Any, First, \
            args, Trace, TraceVariables
        from lepl.bin.bits import BitString
        from lepl.support.node import Node

        classes = {}
        
        def named_class(name, *args):
            '''
            Given a name and some args, create a sub-class of Binary and 
            create an instance with the given content.
            '''
            if name not in classes:
                classes[name] = type(name, (Node,), {})
            return classes[name](*args)
        
        with TraceVariables(False):

            mult    = lambda l, n: BitString.from_sequence([l] * int(n, 0)) 
                
            # an attribute or class name
            name    = Word(Letter(), Letter() | Digit() | '_')
        
            # lengths can be integers (bits) or floats (bytes.bits)
            # but if we have a float, we do not want to parse as an int
            # (or we will get a conversion error due to too small length)
            length  = First(UnsignedInteger() + '.' + Optional(UnsignedInteger()),
                            UnsignedInteger())
        
            # a literal decimal
            decimal = UnsignedInteger()
        
            # a binary number (without pre/postfix)
            binary  = Any('01')[1:]
        
            # an octal number (without pre/postfix)
            octal   = Any('01234567')[1:]
        
            # a hex number (without pre/postfix)
            hex_     = Regexp('[a-fA-F0-9]')[1:]
            
            # the letters used for binary, octal and hex values 
            #(eg the 'x' in 0xffee)
            # pylint: disable-msg=C0103
            b, o, x, d = Any('bB'), Any('oO'), Any('xX'), Any('dD')
        
            # a decimal with optional pre/postfix
            dec     = '0' + d + decimal | decimal + d + '0' | decimal
        
            # little-endian literals have normal prefix syntax (eg 0xffee) 
            little  = decimal | '0' + (b + binary | o + octal | x + hex_)
        
            # big-endian literals have postfix (eg ffeex0)
            big     = (binary + b | octal + o | hex_ + x) + '0'
        
            # optional spaces - will be ignored 
            # (use DFA here because it's multi-line, so \n will match ok)
            spaces  = Drop(DfaRegexp('[ \t\n\r]*'))
            
            with Separator(spaces):
                
                # the grammar is recursive - expressions can contain expressions - 
                # so we use a delayed matcher here as a placeholder, so that we can 
                # use them before they are defined.
                expr = Delayed()
                
                # an implicit length value can be big or little-endian
                ivalue = big | little                 > args(BitString.from_int)
                
                # a value with a length can also be decimal
                lvalue = (big | little | dec) & Drop('/') & length  \
                                                      > args(BitString.from_int)
                
                value = lvalue | ivalue
                
                repeat = value & Drop('*') & little   > args(mult)
                
                # a named value is also a tuple
                named = name & Drop('=') & (expr | value | repeat)  > tuple
                
                # an entry in the expression could be any of these
                entry = named | value | repeat | expr
                
                # and an expression itself consists of a comma-separated list of
                # one or more entries, surrounded by paremtheses
                entries = Drop('(') & entry[1:, Drop(',')] & Drop(')')
                
                # the Binary node may be explicit or implicit and takes the list of
                # entries as an argument list
                node = Optional(Drop('Node')) & entries             > Node
                
                # alternatively, we can give a name and create a named sub-class
                other = name & entries                > args(named_class)
                
                # and finally, we "tie the knot" by giving a definition for the
                # delayed matcher we introduced earlier, which is either a binary
                # node or a subclass
                expr += spaces & (node | other) & spaces
        
        #expr = Trace(expr)
        # this changes order, making 0800x0 parse as binary
        expr.config.no_compile_to_regexp()
        # use sequence to force regexp over multiple lines
        return expr.get_parse_sequence()
示例#26
0
 def _assert(self, repr_, value):
     try:
         b = BitString.from_int(repr_)
         assert str(b) == value + 'b0/' + str(len(b)), str(b)
     except ValueError:
         assert value is None
示例#27
0
 def test_str(self):
     b = BitString.from_int32(0xabcd1234)
     assert str(b) == '00101100 01001000 10110011 11010101b0/32', str(b)
     b = BitString.from_int('0b110')
     assert str(b) == '011b0/3', str(b)
示例#28
0
 def __init__(self, value, length=None):
     if not isinstance(value, BitString):
         value = BitString.from_int(value, length)
     super(Const, self).__init__(value)
示例#29
0
 def __init__(self, value, length=None):
     if not isinstance(value, BitString):
         value = BitString.from_int(value, length)
     super(Const, self).__init__(value)
示例#30
0
 def test_from_int(self):
     self.assert_length_value(3, b'\x00', BitString.from_int('0o0'))
     self.assert_error(lambda: BitString.from_int('1o0'))
     self.assert_error(lambda: BitString.from_int('00o0'))
     self.assert_error(lambda: BitString.from_int('100o0'))
     self.assert_error(lambda: BitString.from_int('777o0'))
     self.assert_length_value(9, b'\x40\x00', BitString.from_int('0o100'))
     self.assert_length_value(9, b'\xfe\x01', BitString.from_int('0o776'))
     self.assert_length_value(12, b'\xff\x03', BitString.from_int('0x3ff'))
     self.assert_length_value(12, b'\xff\x03', BitString.from_int('0o1777'))
     self.assert_length_value(16, b'\x03\xff', BitString.from_int('03ffx0'))
     self.assert_length_value(3, b'\x04', BitString.from_int('0b100'))
     self.assert_length_value(1, b'\x01', BitString.from_int('1b0'))
     self.assert_length_value(2, b'\x02', BitString.from_int('01b0'))
     self.assert_length_value(9, b'\x00\x01', BitString.from_int('000000001b0'))
     self.assert_length_value(9, b'\x01\x01', BitString.from_int('100000001b0'))
     self.assert_length_value(16, b'\x0f\x33', BitString.from_int('1111000011001100b0'))
示例#31
0
 def test_from_sequence(self):
     self.assert_length_value(8, b'\x01', BitString.from_sequence([1], BitString.from_byte))
     self.assert_error(lambda: BitString.from_sequence([256], BitString.from_byte))
     self.assert_length_value(16, b'\x01\x02', BitString.from_sequence([1,2], BitString.from_byte))
示例#32
0
 def test_from_int_with_length(self):
     self.assert_error(lambda: BitString.from_int(1, 0))
     self.assert_error(lambda: BitString.from_int(0, 1))
     self.assert_error(lambda: BitString.from_int(0, 7))
     self.assert_length_value(8, b'\x00', BitString.from_int(0, 8))
     self.assert_error(lambda: BitString.from_int(0, 0.1))
     self.assert_length_value(8, b'\x00', BitString.from_int(0, 1.))
     self.assert_length_value(1, b'\x00', BitString.from_int('0x0', 1))
     self.assert_length_value(7, b'\x00', BitString.from_int('0x0', 7))
     self.assert_length_value(8, b'\x00', BitString.from_int('0x0', 8))
     self.assert_length_value(1, b'\x00', BitString.from_int('0x0', 0.1))
     self.assert_length_value(8, b'\x00', BitString.from_int('0x0', 1.))
     self.assert_length_value(16, b'\x34\x12', BitString.from_int(0x1234, 16))
     self.assert_length_value(16, b'\x34\x12', BitString.from_int('0x1234', 16))
     self.assert_length_value(16, b'\x12\x34', BitString.from_int('1234x0', 16))
     self.assert_length_value(16, b'\x34\x12', BitString.from_int('4660', 16))
     self.assert_length_value(16, b'\x34\x12', BitString.from_int('0d4660', 16))
     self.assert_length_value(16, b'\x12\x34', BitString.from_int('4660d0', 16))
示例#33
0
 def test_from_bytearray(self):
     self.assert_length_value(8, b'\x00', BitString.from_bytearray(b'\x00'))
     self.assert_length_value(16, b'ab', BitString.from_bytearray(b'ab'))
     self.assert_length_value(16, b'ab', BitString.from_bytearray(bytearray(b'ab')))
示例#34
0
 def _assert(self, repr_, value):
     try:
         b = BitString.from_int(repr_)
         assert str(b) == value + 'b0/' + str(len(b)), str(b)
     except ValueError:
         assert value is None
示例#35
0
    def make_binary_parser():
        '''
        Create a parser for binary data.
        '''

        # avoid import loops
        from lepl import Word, Letter, Digit, UnsignedInteger, \
            Regexp, DfaRegexp, Drop, Separator, Delayed, Optional, Any, First, \
            args, Trace, TraceVariables
        from lepl.bin.bits import BitString
        from lepl.support.node import Node

        classes = {}

        def named_class(name, *args):
            '''
            Given a name and some args, create a sub-class of Binary and 
            create an instance with the given content.
            '''
            if name not in classes:
                classes[name] = type(name, (Node, ), {})
            return classes[name](*args)

        with TraceVariables(False):

            mult = lambda l, n: BitString.from_sequence([l] * int(n, 0))

            # an attribute or class name
            name = Word(Letter(), Letter() | Digit() | '_')

            # lengths can be integers (bits) or floats (bytes.bits)
            # but if we have a float, we do not want to parse as an int
            # (or we will get a conversion error due to too small length)
            length = First(
                UnsignedInteger() + '.' + Optional(UnsignedInteger()),
                UnsignedInteger())

            # a literal decimal
            decimal = UnsignedInteger()

            # a binary number (without pre/postfix)
            binary = Any('01')[1:]

            # an octal number (without pre/postfix)
            octal = Any('01234567')[1:]

            # a hex number (without pre/postfix)
            hex_ = Regexp('[a-fA-F0-9]')[1:]

            # the letters used for binary, octal and hex values
            #(eg the 'x' in 0xffee)
            # pylint: disable-msg=C0103
            b, o, x, d = Any('bB'), Any('oO'), Any('xX'), Any('dD')

            # a decimal with optional pre/postfix
            dec = '0' + d + decimal | decimal + d + '0' | decimal

            # little-endian literals have normal prefix syntax (eg 0xffee)
            little = decimal | '0' + (b + binary | o + octal | x + hex_)

            # big-endian literals have postfix (eg ffeex0)
            big = (binary + b | octal + o | hex_ + x) + '0'

            # optional spaces - will be ignored
            # (use DFA here because it's multi-line, so \n will match ok)
            spaces = Drop(DfaRegexp('[ \t\n\r]*'))

            with Separator(spaces):

                # the grammar is recursive - expressions can contain expressions -
                # so we use a delayed matcher here as a placeholder, so that we can
                # use them before they are defined.
                expr = Delayed()

                # an implicit length value can be big or little-endian
                ivalue = big | little > args(BitString.from_int)

                # a value with a length can also be decimal
                lvalue = (big | little | dec) & Drop('/') & length  \
                                                      > args(BitString.from_int)

                value = lvalue | ivalue

                repeat = value & Drop('*') & little > args(mult)

                # a named value is also a tuple
                named = name & Drop('=') & (expr | value | repeat) > tuple

                # an entry in the expression could be any of these
                entry = named | value | repeat | expr

                # and an expression itself consists of a comma-separated list of
                # one or more entries, surrounded by paremtheses
                entries = Drop('(') & entry[1:, Drop(',')] & Drop(')')

                # the Binary node may be explicit or implicit and takes the list of
                # entries as an argument list
                node = Optional(Drop('Node')) & entries > Node

                # alternatively, we can give a name and create a named sub-class
                other = name & entries > args(named_class)

                # and finally, we "tie the knot" by giving a definition for the
                # delayed matcher we introduced earlier, which is either a binary
                # node or a subclass
                expr += spaces & (node | other) & spaces

        #expr = Trace(expr)
        # this changes order, making 0800x0 parse as binary
        expr.config.no_compile_to_regexp()
        # use sequence to force regexp over multiple lines
        return expr.get_parse_sequence()
示例#36
0
 def test_invert(self):
     #basicConfig(level=DEBUG)
     self.assert_length_value(12, b'\x00\x0c', ~BitString.from_int('0x3ff'))
示例#37
0
 def test_from_byte(self):
     self.assert_error(lambda: BitString.from_byte(-1))
     self.assert_length_value(8, b'\x00', BitString.from_byte(0))
     self.assert_length_value(8, b'\x01', BitString.from_byte(1))
     self.assert_length_value(8, b'\xff', BitString.from_byte(255))
     self.assert_error(lambda: BitString.from_byte(256))
示例#38
0
 def test_from_byte(self):
     self.assert_error(lambda: BitString.from_byte(-1))
     self.assert_length_value(8, b'\x00', BitString.from_byte(0))
     self.assert_length_value(8, b'\x01', BitString.from_byte(1))
     self.assert_length_value(8, b'\xff', BitString.from_byte(255))
     self.assert_error(lambda: BitString.from_byte(256))
示例#39
0
 def test_from_int(self):
     self.assert_length_value(3, b'\x00', BitString.from_int('0o0'))
     self.assert_error(lambda: BitString.from_int('1o0'))
     self.assert_error(lambda: BitString.from_int('00o0'))
     self.assert_error(lambda: BitString.from_int('100o0'))
     self.assert_error(lambda: BitString.from_int('777o0'))
     self.assert_length_value(9, b'\x40\x00',
                              BitString.from_int('0o100'))
     self.assert_length_value(9, b'\xfe\x01',
                              BitString.from_int('0o776'))
     self.assert_length_value(12, b'\xff\x03',
                              BitString.from_int('0x3ff'))
     self.assert_length_value(12, b'\xff\x03',
                              BitString.from_int('0o1777'))
     self.assert_length_value(16, b'\x03\xff',
                              BitString.from_int('03ffx0'))
     self.assert_length_value(3, b'\x04', BitString.from_int('0b100'))
     self.assert_length_value(1, b'\x01', BitString.from_int('1b0'))
     self.assert_length_value(2, b'\x02', BitString.from_int('01b0'))
     self.assert_length_value(9, b'\x00\x01',
                              BitString.from_int('000000001b0'))
     self.assert_length_value(9, b'\x01\x01',
                              BitString.from_int('100000001b0'))
     self.assert_length_value(16, b'\x0f\x33',
                              BitString.from_int('1111000011001100b0'))
示例#40
0
 def bassert(self, value, expected, length=None):
     x = BitString.from_int(expected, length)
     assert value == x, (value, x)