Fixed and cleaned up signed integer reading and encoding. Implemented some value...
authorJoseph Spiros <joseph.spiros@ithinksw.com>
Wed, 13 Apr 2011 04:40:10 +0000 (00:40 -0400)
committerJoseph Spiros <joseph.spiros@ithinksw.com>
Wed, 13 Apr 2011 04:40:10 +0000 (00:40 -0400)
ebml/core.py
ebml/tests/test_core.py

index 24d849f..e076c8b 100644 (file)
@@ -138,13 +138,13 @@ def read_signed_integer(stream, size):
        
        value = 0
        if size > 0:
        
        value = 0
        if size > 0:
-               byte = ord(stream.read(1))
-               if (byte & 0b10000000) == 0b10000000:
-                       value = -1 << 8
-               value |= byte
+               first_byte = ord(stream.read(1))
+               value = first_byte
                for i in xrange(1, size):
                        byte = ord(stream.read(1))
                for i in xrange(1, size):
                        byte = ord(stream.read(1))
-                       value = (value << 1) | byte
+                       value = (value << 8) | byte
+               if (first_byte & 0b10000000) == 0b10000000:
+                       value = -(2**(size*8) - value)
        return value
 
 
        return value
 
 
@@ -391,9 +391,7 @@ def encode_signed_integer(sint, length=None):
                if sint >= 0:
                        uint = sint
                else:
                if sint >= 0:
                        uint = sint
                else:
-                       uint = 0b10000000 << (length - 1)
-                       uint += sint
-                       uint |= 0b10000000 << (length - 1)
+                       uint = 2**(length*8) - abs(sint)
        
        data = bytearray(length)
        for index in reversed(xrange(length)):
        
        data = bytearray(length)
        for index in reversed(xrange(length)):
index 54a46a7..ce72b69 100644 (file)
@@ -59,5 +59,48 @@ class ElementIDTests(unittest.TestCase):
                        self.assert_roundtrip(id_)
 
 
                        self.assert_roundtrip(id_)
 
 
+class ValueTestCase(unittest.TestCase):
+       encoder = None
+       reader = None
+       
+       def assert_roundtrip(self, value):
+               if self.encoder is not None and self.reader is not None:
+                       encoded = self.encoder(value)
+                       encoded_stream = StringIO(encoded)
+                       self.assertEqual(value, self.reader(encoded_stream, len(encoded)))
+               else:
+                       raise NotImplementedError
+
+
+class UnsignedIntegerTests(ValueTestCase):
+       encoder = staticmethod(encode_unsigned_integer)
+       reader = staticmethod(read_unsigned_integer)
+       maximum = 2**64 - 1
+       
+       def test_random(self):
+               for value in (randint(0, self.maximum) for i in xrange(0, 10000)):
+                       self.assert_roundtrip(value)
+       
+       def test_maximum(self):
+               self.assert_roundtrip(self.maximum)
+
+
+class SignedIntegerTests(ValueTestCase):
+       encoder = staticmethod(encode_signed_integer)
+       reader = staticmethod(read_signed_integer)
+       minimum = -(2**63)
+       maximum = (2**63) - 1
+       
+       def test_random(self):
+               for value in (randint(self.minimum, self.maximum) for i in xrange(0, 10000)):
+                       self.assert_roundtrip(value)
+       
+       def test_minimum(self):
+               self.assert_roundtrip(self.minimum)
+       
+       def test_maximum(self):
+               self.assert_roundtrip(self.maximum)
+
+
 if __name__ == '__main__':
        unittest.main()
\ No newline at end of file
 if __name__ == '__main__':
        unittest.main()
\ No newline at end of file