Author: Amaury Forgeot d'Arc <amaur...@gmail.com>
Branch: py3k
Changeset: r48034:6d32eeb3fc38
Date: 2011-10-13 22:38 +0200
http://bitbucket.org/pypy/pypy/changeset/6d32eeb3fc38/

Log:    Implement a basic version of long.from_bytes, it's enough for the
        random module. Also attach it to 'int', until these types are
        unified...

diff --git a/pypy/objspace/std/inttype.py b/pypy/objspace/std/inttype.py
--- a/pypy/objspace/std/inttype.py
+++ b/pypy/objspace/std/inttype.py
@@ -33,6 +33,10 @@
         val >>= 1
     return space.wrap(bits)
 
+@gateway.unwrap_spec(s='bufferstr', byteorder=str)
+def descr_from_bytes(space, w_cls, s, byteorder):
+    from pypy.objspace.std.longtype import descr_from_bytes
+    return descr_from_bytes(space, space.w_long, s)
 
 def wrapint(space, x):
     if space.config.objspace.std.withsmallint:
@@ -205,5 +209,6 @@
     denominator = typedef.GetSetProperty(descr_get_denominator),
     real = typedef.GetSetProperty(descr_get_real),
     imag = typedef.GetSetProperty(descr_get_imag),
+    from_bytes = gateway.interp2app(descr_from_bytes, as_classmethod=True),
 )
 int_typedef.registermethods(globals())
diff --git a/pypy/objspace/std/longtype.py b/pypy/objspace/std/longtype.py
--- a/pypy/objspace/std/longtype.py
+++ b/pypy/objspace/std/longtype.py
@@ -113,6 +113,15 @@
         raise OperationError(space.w_OverflowError,
                              space.wrap("too many digits in integer"))
 
+@gateway.unwrap_spec(s='bufferstr', byteorder=str)
+def descr_from_bytes(space, w_cls, s, byteorder):
+    from pypy.rlib.rbigint import rbigint
+    bigint = rbigint.frombytes(s)
+    from pypy.objspace.std.longobject import W_LongObject
+    w_obj = space.allocate_instance(W_LongObject, w_cls)
+    W_LongObject.__init__(w_obj, bigint)
+    return w_obj
+
 # ____________________________________________________________
 
 long_typedef = StdTypeDef("long",
@@ -130,5 +139,6 @@
     real = typedef.GetSetProperty(descr_get_real),
     imag = typedef.GetSetProperty(descr_get_imag),
     bit_length = gateway.interp2app(bit_length),
+    from_bytes = gateway.interp2app(descr_from_bytes, as_classmethod=True),
 )
 long_typedef.registermethods(globals())
diff --git a/pypy/objspace/std/test/test_longobject.py 
b/pypy/objspace/std/test/test_longobject.py
--- a/pypy/objspace/std/test/test_longobject.py
+++ b/pypy/objspace/std/test/test_longobject.py
@@ -310,6 +310,9 @@
         assert (-1<<40).bit_length() == 41
         assert ((2**31)-1).bit_length() == 31
 
+    def test_from_bytes(self):
+        assert long.from_bytes(b'c', 'little') == 99
+        assert long.from_bytes(b'\x01\x01', 'little') == 257
 
     def test_negative_zero(self):
         x = eval("-0L")
diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -215,6 +215,24 @@
         # then modify the result.
         return _decimalstr_to_bigint(s)
 
+    @staticmethod
+    def frombytes(s):
+        accum = 0
+        accumbits = 0
+        digits = []
+        for ch in s:
+            c = ord(ch)
+            accum <<= 8
+            accum |= c
+            accumbits += 8
+            if accumbits >= SHIFT:
+                digits.append(_store_digit(accum & MASK))
+                accum >>= SHIFT
+                accumbits -= SHIFT
+        if accumbits:
+            digits.append(_store_digit(accum))
+        return rbigint(digits, 1)
+
     @jit.elidable
     def toint(self):
         """
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to