Author: Antonio Cuni <[email protected]>
Branch: faster-rstruct
Changeset: r80670:9972a7f270d5
Date: 2015-11-13 19:01 +0100
http://bitbucket.org/pypy/pypy/changeset/9972a7f270d5/
Log: use the fast raw_storage unpacking also for integer types, when
possible
diff --git a/rpython/rlib/rstruct/nativefmttable.py
b/rpython/rlib/rstruct/nativefmttable.py
--- a/rpython/rlib/rstruct/nativefmttable.py
+++ b/rpython/rlib/rstruct/nativefmttable.py
@@ -8,6 +8,7 @@
from rpython.rlib.objectmodel import specialize
from rpython.rlib.rarithmetic import r_singlefloat, widen
from rpython.rlib.rstruct import standardfmttable as std
+from rpython.rlib.rstruct.standardfmttable import native_is_bigendian
from rpython.rlib.rstruct.error import StructError
from rpython.rlib.unroll import unrolling_iterable
from rpython.rlib.rawstorage import str_storage_getitem
@@ -16,8 +17,6 @@
from rpython.translator.tool.cbuild import ExternalCompilationInfo
-native_is_bigendian = struct.pack("=i", 1) == struct.pack(">i", 1)
-
native_fmttable = {
'x': std.standard_fmttable['x'],
'c': std.standard_fmttable['c'],
diff --git a/rpython/rlib/rstruct/standardfmttable.py
b/rpython/rlib/rstruct/standardfmttable.py
--- a/rpython/rlib/rstruct/standardfmttable.py
+++ b/rpython/rlib/rstruct/standardfmttable.py
@@ -12,7 +12,11 @@
from rpython.rlib.rstruct import ieee
from rpython.rlib.rstruct.error import StructError, StructOverflowError
from rpython.rlib.unroll import unrolling_iterable
+from rpython.rlib.rawstorage import str_storage_getitem
+from rpython.rlib import rarithmetic
+from rpython.rtyper.lltypesystem import rffi
+native_is_bigendian = struct.pack("=i", 1) == struct.pack(">i", 1)
def pack_pad(fmtiter, count):
fmtiter.result.append_multiple_char('\x00', count)
@@ -162,6 +166,15 @@
# ____________________________________________________________
+def get_rffi_int_type(size, signed):
+ for TYPE in rffi.platform.numbertype_to_rclass:
+ if (rffi.sizeof(TYPE) == size and
+ rarithmetic.is_signed_integer_type(TYPE) == signed):
+ return TYPE
+ raise KeyError("Cannot find an int type size=%d, signed=%d" % (size,
signed))
+
+UNPACK_ALLOW_RAW_STORAGE = True
+
def make_int_unpacker(size, signed, _memo={}):
try:
return _memo[size, signed]
@@ -180,13 +193,20 @@
else:
inttype = r_ulonglong
unroll_range_size = unrolling_iterable(range(size))
+ TYPE = get_rffi_int_type(size, signed)
@specialize.argtype(0)
def unpack_int(fmtiter):
intvalue = inttype(0)
s = fmtiter.read(size)
idx = 0
- if fmtiter.bigendian:
+ if UNPACK_ALLOW_RAW_STORAGE and fmtiter.bigendian ==
native_is_bigendian:
+ # fast path, using the native raw_storage
+ intvalue = str_storage_getitem(TYPE, s, 0)
+ if not signed and size < native_int_size:
+ intvalue = rarithmetic.intmask(intvalue)
+ intvalue = inttype(intvalue)
+ elif fmtiter.bigendian:
for i in unroll_range_size:
x = ord(s[idx])
if signed and i == 0 and x >= 128:
diff --git a/rpython/rlib/rstruct/test/test_runpack.py
b/rpython/rlib/rstruct/test/test_runpack.py
--- a/rpython/rlib/rstruct/test/test_runpack.py
+++ b/rpython/rlib/rstruct/test/test_runpack.py
@@ -1,5 +1,6 @@
from rpython.rtyper.test.tool import BaseRtypingTest
from rpython.rlib.rstruct.runpack import runpack
+from rpython.rlib.rstruct import standardfmttable
from rpython.rlib.rarithmetic import LONG_BIT
import struct
@@ -55,3 +56,37 @@
assert d == 12.34 # no precision lost
assert f != 12.34 # precision lost
assert abs(f - 12.34) < 1E-6
+
+ def test_unpack_standard_little(self):
+ def unpack(fmt, data):
+ def fn():
+ return runpack(fmt, data)
+ return self.interpret(fn, [])
+ #
+ assert unpack("<i", 'DCBA') == 0x41424344
+ assert unpack("<i", '\xfd\xff\xff\xff') == -3
+ assert unpack("<i", '\x00\x00\x00\x80') == -2147483648
+ assert unpack("<I", 'DCB\x81') == 0x81424344
+ assert unpack("<q", 'HGFEDCBA') == 0x4142434445464748
+ assert unpack("<q", 'HHIJKLM\xbe') == -0x41B2B3B4B5B6B7B8
+ assert unpack("<Q", 'HGFEDCB\x81') == 0x8142434445464748
+
+ def test_unpack_standard_big(self):
+ def unpack(fmt, data):
+ def fn():
+ return runpack(fmt, data)
+ return self.interpret(fn, [])
+ #
+ assert unpack(">i", 'ABCD') == 0x41424344
+ assert unpack(">i", '\xff\xff\xff\xfd') == -3
+ assert unpack(">i", '\x80\x00\x00\x00') == -2147483648
+ assert unpack(">I", '\x81BCD') == 0x81424344
+ assert unpack(">q", 'ABCDEFGH') == 0x4142434445464748
+ assert unpack(">q", '\xbeMLKJIHH') == -0x41B2B3B4B5B6B7B8
+ assert unpack(">Q", '\x81BCDEFGH') == 0x8142434445464748
+
+ def test_unpack_standard_no_raw_storage(self, monkeypatch):
+ monkeypatch.setattr(standardfmttable, 'UNPACK_ALLOW_RAW_STORAGE',
False)
+ self.test_unpack_standard_little()
+ self.test_unpack_standard_big()
+
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit