[pypy-commit] pypy faster-rstruct-2: migrate pack_float to the new buffer-based interface

antocuni pypy.commits at gmail.com
Wed May 10 19:05:33 EDT 2017


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: faster-rstruct-2
Changeset: r91229:f3fc7a2efd43
Date: 2017-05-10 17:44 +0200
http://bitbucket.org/pypy/pypy/changeset/f3fc7a2efd43/

Log:	migrate pack_float to the new buffer-based interface

diff --git a/rpython/rlib/mutbuffer.py b/rpython/rlib/mutbuffer.py
--- a/rpython/rlib/mutbuffer.py
+++ b/rpython/rlib/mutbuffer.py
@@ -16,7 +16,7 @@
 
     You can call finish() only once.
     """
-    _attrs_ = ['readonly', 'll_val']
+    _attrs_ = ['readonly', 'll_val', 'size']
     _immutable_ = True
 
     def __init__(self, size):
diff --git a/rpython/rlib/rstruct/ieee.py b/rpython/rlib/rstruct/ieee.py
--- a/rpython/rlib/rstruct/ieee.py
+++ b/rpython/rlib/rstruct/ieee.py
@@ -265,14 +265,17 @@
     return (mant, (sign << BITS - MANT_DIG - 1) | exp)
 
 @jit.unroll_safe
-def pack_float(result, x, size, be):
-    l = []
+def pack_float(result, pos, x, size, be):
     unsigned = float_pack(x, size)
-    for i in range(size):
-        l.append(chr((unsigned >> (i * 8)) & 0xFF))
     if be:
-        l.reverse()
-    result.append("".join(l))
+        # write in reversed order
+        for i in range(size):
+            c = chr((unsigned >> (i * 8)) & 0xFF)
+            result.setitem(pos + size - i - 1, c)
+    else:
+        for i in range(size):
+            c = chr((unsigned >> (i * 8)) & 0xFF)
+            result.setitem(pos+i, c)
 
 @jit.unroll_safe
 def pack_float80(result, x, size, be):
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
@@ -62,10 +62,14 @@
     def packer(fmtiter):
         fl = fmtiter.accept_float_arg()
         try:
-            return ieee.pack_float(fmtiter.result, fl, size, fmtiter.bigendian)
+            result = ieee.pack_float(fmtiter.result, fmtiter.pos,
+                                     fl, size, fmtiter.bigendian)
         except OverflowError:
             assert size == 4
             raise StructOverflowError("float too large for format 'f'")
+        else:
+            fmtiter.advance(size)
+            return result
     return packer
 
 # ____________________________________________________________
diff --git a/rpython/rlib/rstruct/test/test_ieee.py b/rpython/rlib/rstruct/test/test_ieee.py
--- a/rpython/rlib/rstruct/test/test_ieee.py
+++ b/rpython/rlib/rstruct/test/test_ieee.py
@@ -3,6 +3,7 @@
 import random
 import struct
 
+from rpython.rlib.mutbuffer import MutableStringBuffer
 from rpython.rlib.rstruct import ieee
 from rpython.rlib.rfloat import isnan, NAN, INFINITY
 from rpython.translator.c.test.test_genc import compile
@@ -73,9 +74,9 @@
                 assert repr(x) == repr(y), '%r != %r, Q=%r' % (x, y, Q)
 
         for be in [False, True]:
-            Q = []
-            ieee.pack_float(Q, x, 8, be)
-            Q = Q[0]
+            buf = MutableStringBuffer(8)
+            ieee.pack_float(buf, 0, x, 8, be)
+            Q = buf.finish()
             y = ieee.unpack_float(Q, be)
             assert repr(x) == repr(y), '%r != %r, Q=%r' % (x, y, Q)
 
@@ -197,12 +198,11 @@
 class TestCompiled:
     def test_pack_float(self):
         def pack(x, size):
-            result = []
-            ieee.pack_float(result, x, size, False)
+            buf = MutableStringBuffer(size)
+            ieee.pack_float(buf, 0, x, size, False)
             l = []
-            for x in result:
-                for c in x:
-                    l.append(str(ord(c)))
+            for c in buf.finish():
+                l.append(str(ord(c)))
             return ','.join(l)
         c_pack = compile(pack, [float, int])
 
diff --git a/rpython/rlib/rstruct/test/test_pack.py b/rpython/rlib/rstruct/test/test_pack.py
--- a/rpython/rlib/rstruct/test/test_pack.py
+++ b/rpython/rlib/rstruct/test/test_pack.py
@@ -15,6 +15,11 @@
     def advance(self, count):
         self.pos += count
 
+    def finish(self):
+        # check that we called advance() the right number of times
+        assert self.pos == self.result.getlength()
+        return self.result.finish()
+
     def _accept_arg(self):
         return self.value
 
@@ -41,7 +46,7 @@
         attrs = self.fmttable[fmt]
         pack = attrs['pack']
         pack(fake_fmtiter)
-        return fake_fmtiter.result.finish()
+        return fake_fmtiter.finish()
 
     def check(self, fmt, value):
         expected = struct.pack(self.endianess+fmt, value)


More information about the pypy-commit mailing list