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