[pypy-commit] pypy default: Introduce StringBuilder.append_charpsize, which takes a char* and a size and adds that to the builder, then use this in a few plcaes.

alex_gaynor noreply at buildbot.pypy.org
Thu Jul 28 03:14:53 CEST 2011


Author: Alex Gaynor <alex.gaynor at 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


More information about the pypy-commit mailing list