Author: Alex Gaynor <[email protected]>
Branch: struct-double
Changeset: r53217:0ed55d81e633
Date: 2012-03-04 16:51 -0500
http://bitbucket.org/pypy/pypy/changeset/0ed55d81e633/

Log:    change struct.pack to build a StringBuilder, rather than a list

diff --git a/pypy/module/struct/formatiterator.py 
b/pypy/module/struct/formatiterator.py
--- a/pypy/module/struct/formatiterator.py
+++ b/pypy/module/struct/formatiterator.py
@@ -1,18 +1,19 @@
+from pypy.interpreter.error import OperationError
 from pypy.rlib import jit
 from pypy.rlib.objectmodel import specialize
+from pypy.rlib.rstring import StringBuilder
 from pypy.rlib.rstruct.error import StructError
 from pypy.rlib.rstruct.formatiterator import FormatIterator
 from pypy.rlib.rstruct.standardfmttable import PACK_ACCEPTS_BROKEN_INPUT
-from pypy.interpreter.error import OperationError
 
 
 class PackFormatIterator(FormatIterator):
 
-    def __init__(self, space, args_w):
+    def __init__(self, space, args_w, size):
         self.space = space
         self.args_w = args_w
         self.args_index = 0
-        self.result = []      # list of characters
+        self.result = StringBuilder(size)
 
     # This *should* be always unroll safe, the only way to get here is by
     # unroll the interpret function, which means the fmt is const, and thus
@@ -29,9 +30,8 @@
 
     @jit.unroll_safe
     def align(self, mask):
-        pad = (-len(self.result)) & mask
-        for i in range(pad):
-            self.result.append('\x00')
+        pad = (-self.result.getlength()) & mask
+        self.result.append_multiple_char('\x00', pad)
 
     def finished(self):
         if self.args_index != len(self.args_w):
diff --git a/pypy/module/struct/interp_struct.py 
b/pypy/module/struct/interp_struct.py
--- a/pypy/module/struct/interp_struct.py
+++ b/pypy/module/struct/interp_struct.py
@@ -1,29 +1,34 @@
 from pypy.interpreter.gateway import unwrap_spec
 from pypy.module.struct.formatiterator import PackFormatIterator, 
UnpackFormatIterator
+from pypy.rlib import jit
 from pypy.rlib.rstruct.error import StructError
 from pypy.rlib.rstruct.formatiterator import CalcSizeFormatIterator
 
 
 @unwrap_spec(format=str)
 def calcsize(space, format):
+    return space.wrap(_calcsize(space, format))
+
+def _calcsize(space, format):
     fmtiter = CalcSizeFormatIterator()
     try:
         fmtiter.interpret(format)
     except StructError, e:
         raise e.at_applevel(space)
-    return space.wrap(fmtiter.totalsize)
-
+    return fmtiter.totalsize
 
 @unwrap_spec(format=str)
 def pack(space, format, args_w):
-    fmtiter = PackFormatIterator(space, args_w)
+    if jit.isconstant(format):
+        size = _calcsize(space, format)
+    else:
+        size = 8
+    fmtiter = PackFormatIterator(space, args_w, size)
     try:
         fmtiter.interpret(format)
     except StructError, e:
         raise e.at_applevel(space)
-    result = ''.join(fmtiter.result)
-    return space.wrap(result)
-
+    return space.wrap(fmtiter.result.build())
 
 @unwrap_spec(format=str, input='bufferstr')
 def unpack(space, format, input):
diff --git a/pypy/rlib/rstruct/ieee.py b/pypy/rlib/rstruct/ieee.py
--- a/pypy/rlib/rstruct/ieee.py
+++ b/pypy/rlib/rstruct/ieee.py
@@ -142,7 +142,7 @@
         l.append(chr((unsigned >> (i * 8)) & 0xFF))
     if be:
         l.reverse()
-        result.extend(l)
+        result.append("".join(l))
 
 
 def unpack_float(s, be):
diff --git a/pypy/rlib/rstruct/standardfmttable.py 
b/pypy/rlib/rstruct/standardfmttable.py
--- a/pypy/rlib/rstruct/standardfmttable.py
+++ b/pypy/rlib/rstruct/standardfmttable.py
@@ -38,11 +38,10 @@
 def pack_string(fmtiter, count):
     string = fmtiter.accept_str_arg()
     if len(string) < count:
-        fmtiter.result += string
-        for i in range(len(string), count):
-            fmtiter.result.append('\x00')
+        fmtiter.result.append(string)
+        fmtiter.result.append_multiple_char('\x00', count - len(string))
     else:
-        fmtiter.result += string[:count]
+        fmtiter.result.append_slice(string, 0, count)
 
 def pack_pascal(fmtiter, count):
     string = fmtiter.accept_str_arg()
@@ -56,9 +55,8 @@
     else:
         prefixchar = chr(prefix)
     fmtiter.result.append(prefixchar)
-    fmtiter.result += string[:prefix]
-    for i in range(1 + prefix, count):
-        fmtiter.result.append('\x00')
+    fmtiter.result.append_slice(string, 0, prefix)
+    fmtiter.result.append_multiple_char('\x00', count - (1 + prefix))
 
 def make_float_packer(size):
     def packer(fmtiter):
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to