[pypy-svn] r65706 - in pypy/trunk/pypy: annotation annotation/test objspace/std rpython rpython/lltypesystem rpython/ootypesystem rpython/test

benjamin at codespeak.net benjamin at codespeak.net
Wed Jun 10 02:09:33 CEST 2009


Author: benjamin
Date: Wed Jun 10 02:09:32 2009
New Revision: 65706

Modified:
   pypy/trunk/pypy/annotation/test/test_annrpython.py
   pypy/trunk/pypy/annotation/unaryop.py
   pypy/trunk/pypy/objspace/std/stringobject.py
   pypy/trunk/pypy/rpython/lltypesystem/rstr.py
   pypy/trunk/pypy/rpython/ootypesystem/ootype.py
   pypy/trunk/pypy/rpython/ootypesystem/rstr.py
   pypy/trunk/pypy/rpython/rstr.py
   pypy/trunk/pypy/rpython/test/test_rstr.py
Log:
implement str.splitlines() for rpython

Modified: pypy/trunk/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/trunk/pypy/annotation/test/test_annrpython.py	(original)
+++ pypy/trunk/pypy/annotation/test/test_annrpython.py	Wed Jun 10 02:09:32 2009
@@ -425,6 +425,14 @@
             s_meth = s_example.getattr(iv(methname))
             assert isinstance(s_constmeth, annmodel.SomeBuiltin)
 
+    def test_str_splitlines(self):
+        a = self.RPythonAnnotator()
+        def f(a_str):
+            return a_str.splitlines()
+        s = a.build_types(f, [str])
+        assert isinstance(s, annmodel.SomeList)
+        assert s.listdef.listitem.resized
+
     def test_simple_slicing(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.simple_slice, [list])
@@ -3068,7 +3076,6 @@
         a = self.RPythonAnnotator()
         a.translator.config.translation.list_comprehension_operations = True
         py.test.raises(TooLateForChange, a.build_types, fn, [int])
-            
 
     def test_listitem_never_resize(self):
         from pypy.rlib.debug import check_annotation

Modified: pypy/trunk/pypy/annotation/unaryop.py
==============================================================================
--- pypy/trunk/pypy/annotation/unaryop.py	(original)
+++ pypy/trunk/pypy/annotation/unaryop.py	Wed Jun 10 02:09:32 2009
@@ -493,6 +493,13 @@
     def hash(str):
         return SomeInteger()
 
+    def method_splitlines(str, s_keep_newlines=None):
+        s_list = getbookkeeper().newlist(str.basestringclass())
+        # Force the list to be resizable because ll_splitlines doesn't
+        # preallocate the list.
+        s_list.listdef.listitem.resize()
+        return s_list
+
     def method_split(str, patt): # XXX
         getbookkeeper().count("str_split", str, patt)
         return getbookkeeper().newlist(str.basestringclass())

Modified: pypy/trunk/pypy/objspace/std/stringobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/stringobject.py	(original)
+++ pypy/trunk/pypy/objspace/std/stringobject.py	Wed Jun 10 02:09:32 2009
@@ -701,29 +701,10 @@
  
  
 def str_splitlines__String_ANY(space, w_self, w_keepends):
-    data = w_self._value
     u_keepends  = space.int_w(w_keepends)  # truth value, but type checked
-    selflen = len(data)
-    
     strs_w = []
-    i = j = 0
-    while i < selflen:
-        # Find a line and append it
-        while i < selflen and data[i] != '\n' and data[i] != '\r':
-            i += 1
-        # Skip the line break reading CRLF as one line break
-        eol = i
-        i += 1
-        if i < selflen and data[i-1] == '\r' and data[i] == '\n':
-            i += 1
-        if u_keepends:
-            eol = i
-        strs_w.append(sliced(space, data, j, eol, w_self))
-        j = i
-
-    if j < selflen:
-        strs_w.append(sliced(space, data, j, len(data), w_self))
-
+    for value in w_self._value.splitlines(u_keepends):
+        strs_w.append(space.wrap(value))
     return space.newlist(strs_w)
 
 def str_zfill__String_ANY(space, w_self, w_width):

Modified: pypy/trunk/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/trunk/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/trunk/pypy/rpython/lltypesystem/rstr.py	Wed Jun 10 02:09:32 2009
@@ -674,6 +674,36 @@
         s1.copy_contents(s1, newstr, 0, 0, newlen)
         return newstr
 
+    def ll_splitlines(LIST, s, keep_newlines):
+        chars = s.chars
+        strlen = len(chars)
+        i = 0
+        j = 0
+        # The annotator makes sure this list is resizable.
+        res = LIST.ll_newlist(0)
+        while j < strlen:
+            while i < strlen and chars[i] != '\n' and chars[i] != '\r':
+                i += 1
+            eol = i
+            if i < strlen:
+                if chars[i] == '\r' and i + 1 < strlen and chars[i + 1] == '\n':
+                    i += 2
+                else:
+                    i += 1
+                if keep_newlines:
+                    eol = i
+            list_length = res.ll_length()
+            res._ll_resize_ge(list_length + 1)
+            item = res.ll_items()[list_length] = s.malloc(eol - j)
+            item.copy_contents(s, item, j, 0, eol - j)
+            j = i
+        if j < strlen:
+            list_length = res.ll_length()
+            res._ll_resize_ge(list_length + 1)
+            item = res.ll_items()[list_length] = s.malloc(strlen - j)
+            item.copy_contents(s, item, j, 0, strlen - j)
+        return res
+
     def ll_split_chr(LIST, s, c):
         chars = s.chars
         strlen = len(chars)

Modified: pypy/trunk/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/trunk/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/trunk/pypy/rpython/ootypesystem/ootype.py	Wed Jun 10 02:09:32 2009
@@ -368,6 +368,7 @@
             "ll_lower": Meth([], self.SELFTYPE_T),
             "ll_substring": Meth([Signed, Signed], self.SELFTYPE_T), # ll_substring(start, count)
             "ll_split_chr": Meth([self.CHAR], Array(self.SELFTYPE_T)),
+            "ll_splitlines": Meth([Bool], Array(self.SELFTYPE_T)),
             "ll_contains": Meth([self.CHAR], Bool),
             "ll_replace_chr_chr": Meth([self.CHAR, self.CHAR], self.SELFTYPE_T),
             })
@@ -1289,6 +1290,12 @@
         # NOT_RPYTHON
         return self.make_string(self._str[start:start+count])
 
+    def ll_splitlines(self, keep_newlines):
+        l = [self.make_string(s) for s in self._str.splitlines(keep_newlines)]
+        res = _array(Array(self._TYPE), len(l))
+        res._array[:] = l
+        return res
+
     def ll_split_chr(self, ch):
         # NOT_RPYTHON
         l = [self.make_string(s) for s in self._str.split(ch)]

Modified: pypy/trunk/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/trunk/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/trunk/pypy/rpython/ootypesystem/rstr.py	Wed Jun 10 02:09:32 2009
@@ -207,6 +207,9 @@
     def ll_stringslice_minusone(s):
         return s.ll_substring(0, s.ll_strlen()-1)
 
+    def ll_splitlines(RESULT, s, keep_newlines):
+        return RESULT.ll_convert_from_array(s.ll_splitlines(keep_newlines))
+
     def ll_split_chr(RESULT, s, c):
         return RESULT.ll_convert_from_array(s.ll_split_chr(c))
 

Modified: pypy/trunk/pypy/rpython/rstr.py
==============================================================================
--- pypy/trunk/pypy/rpython/rstr.py	(original)
+++ pypy/trunk/pypy/rpython/rstr.py	Wed Jun 10 02:09:32 2009
@@ -213,6 +213,20 @@
                 raise TyperError("sep.join() of non-string list: %r" % r_lst)
             return hop.gendirectcall(llfn, v_str, v_length, v_items)
 
+    def rtype_method_splitlines(self, hop):
+        rstr = hop.args_r[0].repr
+        if hop.nb_args == 2:
+            args = hop.inputargs(rstr.repr, Bool)
+        else:
+            args = [hop.inputarg(rstr.repr, 0), hop.inputconst(Bool, False)]
+        try:
+            list_type = hop.r_result.lowleveltype.TO
+        except AttributeError:
+            list_type = hop.r_result.lowleveltype
+        cLIST = hop.inputconst(Void, list_type)
+        hop.exception_cannot_occur()
+        return hop.gendirectcall(self.ll.ll_splitlines, cLIST, *args)
+
     def rtype_method_split(self, hop):
         rstr = hop.args_r[0].repr
         v_str, v_chr = hop.inputargs(rstr.repr, rstr.char_repr)

Modified: pypy/trunk/pypy/rpython/test/test_rstr.py
==============================================================================
--- pypy/trunk/pypy/rpython/test/test_rstr.py	(original)
+++ pypy/trunk/pypy/rpython/test/test_rstr.py	Wed Jun 10 02:09:32 2009
@@ -554,6 +554,17 @@
             res = self.ll_to_string(self.interpret(dummy, []))
             assert res == expected
 
+    def test_splitlines(self):
+        const = self.const
+        def f(i, newlines):
+            s = [const(''), const("\n"), const("\n\n"), const("hi\n"),
+                 const("random data\r\n"), const("\r\n"), const("\rdata")]
+            return len(s[i].splitlines(newlines))
+        for newlines in (True, False):
+            for i in xrange(5):
+                res = self.interpret(f, [i, newlines])
+                assert res == f(i, newlines)
+
     def test_split(self):
         const = self.const
         def fn(i):



More information about the Pypy-commit mailing list