Author: Alex Gaynor <[email protected]>
Branch:
Changeset: r46032:7cc899d8de19
Date: 2011-07-27 18:14 -0700
http://bitbucket.org/pypy/pypy/changeset/7cc899d8de19/
Log: Introduce StringBuilder.append_charpsize, which takes a char* and a
size and adds that to the builder, then use this in a few plcaes.
diff --git a/pypy/rlib/rstring.py b/pypy/rlib/rstring.py
--- a/pypy/rlib/rstring.py
+++ b/pypy/rlib/rstring.py
@@ -1,8 +1,8 @@
""" String builder interface and string functions
"""
-from pypy.annotation.model import SomeObject, SomeString, s_None,\
- SomeChar, SomeInteger, SomeUnicodeCodePoint, SomeUnicodeString
+from pypy.annotation.model import (SomeObject, SomeString, s_None, SomeChar,
+ SomeInteger, SomeUnicodeCodePoint, SomeUnicodeString, SomePtr)
from pypy.rpython.extregistry import ExtRegistryEntry
@@ -65,6 +65,12 @@
assert isinstance(c, self.tp)
self.l.append(c * times)
+ def append_charpsize(self, s, size):
+ l = []
+ for i in xrange(size):
+ l.append(s[i])
+ self.l.append(self.tp("").join(l))
+
def build(self):
return self.tp("").join(self.l)
@@ -100,6 +106,11 @@
assert isinstance(s_times, SomeInteger)
return s_None
+ def method_append_charpsize(self, s_ptr, s_size):
+ assert isinstance(s_ptr, SomePtr)
+ assert isinstance(s_size, SomeInteger)
+ return s_None
+
def method_getlength(self):
return SomeInteger(nonneg=True)
@@ -127,6 +138,11 @@
assert isinstance(s_times, SomeInteger)
return s_None
+ def method_append_charpsize(self, s_ptr, s_size):
+ assert isinstance(s_ptr, SomePtr)
+ assert isinstance(s_size, SomeInteger)
+ return s_None
+
def method_getlength(self):
return SomeInteger(nonneg=True)
diff --git a/pypy/rlib/rzlib.py b/pypy/rlib/rzlib.py
--- a/pypy/rlib/rzlib.py
+++ b/pypy/rlib/rzlib.py
@@ -1,8 +1,11 @@
import sys
+
+from pypy.rlib.rstring import StringBuilder
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.rpython.tool import rffi_platform
+from pypy.translator.platform import platform as compiler, CompilationError
from pypy.translator.tool.cbuild import ExternalCompilationInfo
-from pypy.translator.platform import platform as compiler, CompilationError
+
if compiler.name == "msvc":
libname = 'zlib'
@@ -353,7 +356,7 @@
# of characters 'result'. We don't need to gradually
# increase the output buffer size because there is no
# quadratic factor.
- result = []
+ result = StringBuilder()
while True:
stream.c_next_out = rffi.cast(Bytefp, outbuf)
@@ -369,8 +372,7 @@
if err == Z_OK or err == Z_STREAM_END:
# accumulate data into 'result'
avail_out = rffi.cast(lltype.Signed, stream.c_avail_out)
- for i in xrange(bufsize - avail_out):
- result.append(outbuf[i])
+ result.append_charpsize(outbuf, bufsize - avail_out)
# if the output buffer is full, there might be more data
# so we need to try again. Otherwise, we're done.
if avail_out > 0:
@@ -401,6 +403,6 @@
# When decompressing, if the compressed stream of data was truncated,
# then the zlib simply returns Z_OK and waits for more. If it is
# complete it returns Z_STREAM_END.
- return (''.join(result),
+ return (result.build(),
err,
rffi.cast(lltype.Signed, stream.c_avail_in))
diff --git a/pypy/rpython/lltypesystem/rbuilder.py
b/pypy/rpython/lltypesystem/rbuilder.py
--- a/pypy/rpython/lltypesystem/rbuilder.py
+++ b/pypy/rpython/lltypesystem/rbuilder.py
@@ -1,13 +1,13 @@
-
+from pypy.rlib import rgc
+from pypy.rlib.objectmodel import enforceargs
+from pypy.rlib.rarithmetic import ovfcheck
+from pypy.rpython.annlowlevel import llstr
+from pypy.rpython.rptr import PtrRepr
+from pypy.rpython.lltypesystem import lltype, rstr
+from pypy.rpython.lltypesystem.lltype import staticAdtMethod
+from pypy.rpython.lltypesystem.rstr import (STR, UNICODE, char_repr,
+ string_repr, unichar_repr, unicode_repr)
from pypy.rpython.rbuilder import AbstractStringBuilderRepr
-from pypy.rpython.lltypesystem import lltype, rstr
-from pypy.rpython.lltypesystem.rstr import STR, UNICODE, char_repr,\
- string_repr, unichar_repr, unicode_repr
-from pypy.rpython.annlowlevel import llstr
-from pypy.rlib import rgc
-from pypy.rlib.rarithmetic import ovfcheck
-from pypy.rlib.objectmodel import enforceargs
-from pypy.rpython.lltypesystem.lltype import staticAdtMethod
from pypy.tool.sourcetools import func_with_new_name
# Think about heuristics below, maybe we can come up with something
@@ -73,7 +73,7 @@
ll_builder.grow(ll_builder, lgt)
ll_str.copy_contents(ll_str, ll_builder.buf, 0, used, lgt)
ll_builder.used = needed
-
+
@staticmethod
def ll_append_char(ll_builder, char):
if ll_builder.used == ll_builder.allocated:
@@ -102,6 +102,16 @@
ll_builder.used = used
@staticmethod
+ def ll_append_charpsize(ll_builder, charp, size):
+ used = ll_builder.used
+ if used + size > ll_builder.allocated:
+ ll_builder.grow(ll_builder, size)
+ for i in xrange(size):
+ ll_builder.buf.chars[used] = charp[i]
+ used += 1
+ ll_builder.used = used
+
+ @staticmethod
def ll_getlength(ll_builder):
return ll_builder.used
@@ -119,6 +129,9 @@
mallocfn = staticmethod(rstr.mallocstr)
string_repr = string_repr
char_repr = char_repr
+ raw_ptr_repr = PtrRepr(
+ lltype.Ptr(lltype.Array(lltype.Char, hints={'nolength': True}))
+ )
class UnicodeBuilderRepr(BaseStringBuilderRepr):
lowleveltype = lltype.Ptr(UNICODEBUILDER)
@@ -126,6 +139,9 @@
mallocfn = staticmethod(rstr.mallocunicode)
string_repr = unicode_repr
char_repr = unichar_repr
+ raw_ptr_repr = PtrRepr(
+ lltype.Ptr(lltype.Array(lltype.UniChar, hints={'nolength': True}))
+ )
unicodebuilder_repr = UnicodeBuilderRepr()
stringbuilder_repr = StringBuilderRepr()
diff --git a/pypy/rpython/lltypesystem/rffi.py
b/pypy/rpython/lltypesystem/rffi.py
--- a/pypy/rpython/lltypesystem/rffi.py
+++ b/pypy/rpython/lltypesystem/rffi.py
@@ -789,8 +789,7 @@
# char* and size -> str (which can contain null bytes)
def charpsize2str(cp, size):
b = builder_class(size)
- for i in xrange(size):
- b.append(cp[i])
+ b.append_charpsize(cp, size)
return b.build()
charpsize2str._annenforceargs_ = [None, int]
diff --git a/pypy/rpython/rbuilder.py b/pypy/rpython/rbuilder.py
--- a/pypy/rpython/rbuilder.py
+++ b/pypy/rpython/rbuilder.py
@@ -36,6 +36,11 @@
hop.exception_cannot_occur()
return hop.gendirectcall(self.ll_append_multiple_char, *vlist)
+ def rtype_method_append_charpsize(self, hop):
+ vlist = hop.inputargs(self, self.raw_ptr_repr, lltype.Signed)
+ hop.exception_cannot_occur()
+ return hop.gendirectcall(self.ll_append_charpsize, *vlist)
+
def rtype_method_getlength(self, hop):
vlist = hop.inputargs(self)
hop.exception_cannot_occur()
diff --git a/pypy/rpython/rptr.py b/pypy/rpython/rptr.py
--- a/pypy/rpython/rptr.py
+++ b/pypy/rpython/rptr.py
@@ -22,7 +22,7 @@
class __extend__(annmodel.SomeInteriorPtr):
def rtyper_makerepr(self, rtyper):
return InteriorPtrRepr(self.ll_ptrtype)
-
+
class PtrRepr(Repr):
@@ -91,7 +91,7 @@
vlist = hop.inputargs(*hop.args_r)
nexpected = len(self.lowleveltype.TO.ARGS)
nactual = len(vlist)-1
- if nactual != nexpected:
+ if nactual != nexpected:
raise TyperError("argcount mismatch: expected %d got %d" %
(nexpected, nactual))
if isinstance(vlist[0], flowmodel.Constant):
@@ -111,7 +111,12 @@
hop.swap_fst_snd_args()
hop.r_s_popfirstarg()
return self.rtype_simple_call(hop)
-
+
+class __extend__(pairtype(PtrRepr, PtrRepr)):
+ def convert_from_to((r_ptr1, r_ptr2), v, llop):
+ assert r_ptr1.lowleveltype == r_ptr2.lowleveltype
+ return v
+
class __extend__(pairtype(PtrRepr, IntegerRepr)):
@@ -205,7 +210,7 @@
self.lowleveltype = adtmeth.ll_ptrtype
self.ll_ptrtype = adtmeth.ll_ptrtype
self.lowleveltype =
rtyper.getrepr(annmodel.lltype_to_annotation(adtmeth.ll_ptrtype)).lowleveltype
-
+
def rtype_simple_call(self, hop):
hop2 = hop.copy()
func = self.func
@@ -242,7 +247,7 @@
if numitemoffsets > 0:
self.lowleveltype =
lltype.Ptr(self.parentptrtype._interior_ptr_type_with_index(self.resulttype.TO))
else:
- self.lowleveltype = self.parentptrtype
+ self.lowleveltype = self.parentptrtype
def getinteriorfieldargs(self, hop, v_self):
vlist = []
@@ -305,7 +310,7 @@
class __extend__(pairtype(InteriorPtrRepr, IntegerRepr)):
- def rtype_getitem((r_ptr, r_item), hop):
+ def rtype_getitem((r_ptr, r_item), hop):
ARRAY = r_ptr.resulttype.TO
ITEM_TYPE = ARRAY.OF
if isinstance(ITEM_TYPE, lltype.ContainerType):
@@ -325,7 +330,7 @@
vlist = r_ptr.getinteriorfieldargs(hop, v_self) + [v_index]
return hop.genop('getinteriorfield', vlist,
resulttype=ITEM_TYPE)
-
+
def rtype_setitem((r_ptr, r_index), hop):
ARRAY = r_ptr.resulttype.TO
ITEM_TYPE = ARRAY.OF
@@ -333,11 +338,11 @@
v_self, v_index, v_value = hop.inputargs(r_ptr, lltype.Signed,
hop.args_r[2])
vlist = r_ptr.getinteriorfieldargs(hop, v_self) + [v_index, v_value]
hop.genop('setinteriorfield', vlist)
-
+
class __extend__(pairtype(InteriorPtrRepr, LLADTMethRepr)):
def convert_from_to((r_from, r_to), v, llops):
if r_from.lowleveltype == r_to.lowleveltype:
return v
return NotImplemented
-
+
diff --git a/pypy/rpython/test/test_rbuilder.py
b/pypy/rpython/test/test_rbuilder.py
--- a/pypy/rpython/test/test_rbuilder.py
+++ b/pypy/rpython/test/test_rbuilder.py
@@ -1,8 +1,10 @@
import py
+
+from pypy.rlib.rstring import StringBuilder, UnicodeBuilder
+from pypy.rpython.annlowlevel import llstr, hlstr
+from pypy.rpython.lltypesystem import rffi
+from pypy.rpython.lltypesystem.rbuilder import *
from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
-from pypy.rpython.lltypesystem.rbuilder import *
-from pypy.rpython.annlowlevel import llstr, hlstr
-from pypy.rlib.rstring import StringBuilder, UnicodeBuilder
class TestStringBuilderDirect(object):
@@ -73,6 +75,15 @@
res = self.interpret(func, [])
assert res == 4
+ def test_append_charpsize(self):
+ def func(l):
+ s = StringBuilder()
+ with rffi.scoped_str2charp("hello world") as x:
+ s.append_charpsize(x, l)
+ return s.build()
+ res = self.ll_to_string(self.interpret(func, [5]))
+ assert res == "hello"
+
class TestLLtype(BaseTestStringBuilder, LLRtypeMixin):
pass
@@ -81,3 +92,5 @@
py.test.skip("getlength(): not implemented on ootype")
def test_unicode_getlength(self):
py.test.skip("getlength(): not implemented on ootype")
+ def test_append_charpsize(self):
+ py.test.skip("append_charpsize(): not implemented on ootype")
\ No newline at end of file
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit