Author: Alex Gaynor <alex.gay...@gmail.com> 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 pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit