[pypy-commit] pypy default: switch struct to use StringBuilder internally
alex_gaynor
noreply at buildbot.pypy.org
Mon Mar 5 19:22:15 CET 2012
Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch:
Changeset: r53239:73cc3b2ca760
Date: 2012-03-05 13:21 -0500
http://bitbucket.org/pypy/pypy/changeset/73cc3b2ca760/
Log: switch struct to use StringBuilder internally
diff --git a/pypy/interpreter/buffer.py b/pypy/interpreter/buffer.py
--- a/pypy/interpreter/buffer.py
+++ b/pypy/interpreter/buffer.py
@@ -20,6 +20,7 @@
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.error import OperationError
from pypy.rlib.objectmodel import compute_hash
+from pypy.rlib.rstring import StringBuilder
class Buffer(Wrappable):
@@ -152,12 +153,13 @@
if space.isinstance_w(w_object, space.w_unicode):
# unicode objects support the old buffer interface
# but not the new buffer interface (change in python 2.7)
- from pypy.rlib.rstruct.unichar import pack_unichar
- charlist = []
- for unich in space.unicode_w(w_object):
- pack_unichar(unich, charlist)
+ from pypy.rlib.rstruct.unichar import pack_unichar, UNICODE_SIZE
+ unistr = space.unicode_w(w_object)
+ builder = StringBuilder(len(unistr) * UNICODE_SIZE)
+ for unich in unistr:
+ pack_unichar(unich, builder)
from pypy.interpreter.buffer import StringBuffer
- w_buffer = space.wrap(StringBuffer(''.join(charlist)))
+ w_buffer = space.wrap(StringBuffer(builder.build()))
else:
w_buffer = space.buffer(w_object)
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,5 +1,6 @@
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
@@ -8,11 +9,11 @@
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,28 +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')
diff --git a/pypy/module/struct/test/test_ztranslation.py b/pypy/module/struct/test/test_ztranslation.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/struct/test/test_ztranslation.py
@@ -0,0 +1,6 @@
+from pypy.objspace.fake.checkmodule import checkmodule
+
+
+def test_checkmodule():
+ checkmodule('struct')
+
diff --git a/pypy/objspace/std/marshal_impl.py b/pypy/objspace/std/marshal_impl.py
--- a/pypy/objspace/std/marshal_impl.py
+++ b/pypy/objspace/std/marshal_impl.py
@@ -16,6 +16,7 @@
from pypy.interpreter.pycode import PyCode
from pypy.interpreter import gateway, unicodehelper
from pypy.rlib.rstruct import ieee
+from pypy.rlib.rstring import StringBuilder
from pypy.objspace.std.boolobject import W_BoolObject
from pypy.objspace.std.complexobject import W_ComplexObject
@@ -153,9 +154,9 @@
register(TYPE_INT64, unmarshal_Int64)
def pack_float(f):
- result = []
+ result = StringBuilder(8)
ieee.pack_float(result, f, 8, False)
- return ''.join(result)
+ return result.build()
def unpack_float(s):
return ieee.unpack_float(s, False)
diff --git a/pypy/objspace/std/ropeunicodeobject.py b/pypy/objspace/std/ropeunicodeobject.py
--- a/pypy/objspace/std/ropeunicodeobject.py
+++ b/pypy/objspace/std/ropeunicodeobject.py
@@ -8,6 +8,7 @@
from pypy.objspace.std.ropeobject import W_RopeObject
from pypy.objspace.std.noneobject import W_NoneObject
from pypy.rlib import rope
+from pypy.rlib.rstring import StringBuilder
from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
from pypy.objspace.std import unicodeobject, slicetype, iterobject
from pypy.objspace.std.tupleobject import W_TupleObject
@@ -946,15 +947,16 @@
return mod_format(space, w_format, w_values, do_unicode=True)
def buffer__RopeUnicode(space, w_unicode):
- from pypy.rlib.rstruct.unichar import pack_unichar
- charlist = []
+ from pypy.rlib.rstruct.unichar import pack_unichar, UNICODE_SIZE
node = w_unicode._node
iter = rope.ItemIterator(node)
- for idx in range(node.length()):
+ length = node.length()
+ builder = StringBuilder(length * UNICODE_SIZE)
+ for idx in range(length):
unich = unichr(iter.nextint())
- pack_unichar(unich, charlist)
+ pack_unichar(unich, builder)
from pypy.interpreter.buffer import StringBuffer
- return space.wrap(StringBuffer(''.join(charlist)))
+ return space.wrap(StringBuffer(builder.build()))
# methods of the iterator
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
@@ -136,13 +136,13 @@
def pack_float(result, x, size, be):
- l = [] if be else result
+ l = []
unsigned = float_pack(x, size)
for i in range(size):
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/nativefmttable.py b/pypy/rlib/rstruct/nativefmttable.py
--- a/pypy/rlib/rstruct/nativefmttable.py
+++ b/pypy/rlib/rstruct/nativefmttable.py
@@ -29,8 +29,7 @@
doubleval = fmtiter.accept_float_arg()
double_buf[0] = doubleval
p = rffi.cast(rffi.CCHARP, double_buf)
- for i in range(sizeof_double):
- fmtiter.result.append(p[i])
+ fmtiter.result.append_charpsize(p, rffi.sizeof(rffi.DOUBLE))
@specialize.argtype(0)
def unpack_double(fmtiter):
@@ -46,8 +45,7 @@
floatval = r_singlefloat(doubleval)
float_buf[0] = floatval
p = rffi.cast(rffi.CCHARP, float_buf)
- for i in range(sizeof_float):
- fmtiter.result.append(p[i])
+ fmtiter.result.append_charpsize(p, rffi.sizeof(rffi.FLOAT))
@specialize.argtype(0)
def unpack_float(fmtiter):
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
@@ -21,8 +21,7 @@
# ____________________________________________________________
def pack_pad(fmtiter, count):
- for i in range(count):
- fmtiter.result.append('\x00')
+ fmtiter.result.append_multiple_char('\x00', count)
def pack_char(fmtiter):
string = fmtiter.accept_str_arg()
@@ -38,11 +37,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 +54,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):
More information about the pypy-commit
mailing list