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