[pypy-commit] pypy default: move an optimization from stringobject.py to rstring.py
cfbolz
noreply at buildbot.pypy.org
Mon Jun 17 14:35:18 CEST 2013
Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch:
Changeset: r64904:70f3823a6ba8
Date: 2013-06-13 22:33 +0200
http://bitbucket.org/pypy/pypy/changeset/70f3823a6ba8/
Log: move an optimization from stringobject.py to rstring.py
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -16,7 +16,7 @@
from rpython.rlib.objectmodel import (
compute_hash, compute_unique_id, specialize)
from rpython.rlib.rarithmetic import ovfcheck
-from rpython.rlib.rstring import StringBuilder, split
+from rpython.rlib.rstring import StringBuilder, split, rsplit
class W_AbstractStringObject(W_Object):
@@ -287,31 +287,12 @@
bylen = len(by)
if bylen == 0:
raise OperationError(space.w_ValueError, space.wrap("empty separator"))
-
- if bylen == 1 and maxsplit < 0:
- res = []
- start = 0
- # fast path: uses str.rfind(character) and str.count(character)
- by = by[0] # annotator hack: string -> char
- count = value.count(by)
- res = [None] * (count + 1)
- end = len(value)
- while count >= 0:
- assert end >= 0
- prev = value.rfind(by, 0, end)
- start = prev + 1
- assert start >= 0
- res[count] = value[start:end]
- count -= 1
- end = prev
- else:
- res = split(value, by, maxsplit)
-
+ res = split(value, by, maxsplit)
return space.newlist_str(res)
def str_rsplit__String_None_ANY(space, w_self, w_none, w_maxsplit=-1):
maxsplit = space.int_w(w_maxsplit)
- res_w = []
+ res = []
value = w_self._value
i = len(value)-1
while True:
@@ -336,20 +317,19 @@
# the word is value[j+1:i+1]
j1 = j + 1
assert j1 >= 0
- res_w.append(sliced(space, value, j1, i+1, w_self))
+ res.append(value[j1:i+1])
# continue to look from the character before the space before the word
i = j - 1
- res_w.reverse()
- return space.newlist(res_w)
+ res.reverse()
+ return space.newlist_str(res)
def make_rsplit_with_delim(funcname, sliced):
from rpython.tool.sourcetools import func_with_new_name
def fn(space, w_self, w_by, w_maxsplit=-1):
maxsplit = space.int_w(w_maxsplit)
- res_w = []
value = w_self._value
end = len(value)
by = w_by._value
@@ -357,6 +337,7 @@
if bylen == 0:
raise OperationError(space.w_ValueError, space.wrap("empty separator"))
+ res_w = []
while maxsplit != 0:
next = value.rfind(by, 0, end)
if next < 0:
@@ -371,8 +352,13 @@
return func_with_new_name(fn, funcname)
-str_rsplit__String_String_ANY = make_rsplit_with_delim('str_rsplit__String_String_ANY',
- sliced)
+def str_rsplit__String_String_ANY(space, w_self, w_by, w_maxsplit=-1):
+ maxsplit = space.int_w(w_maxsplit)
+ value = w_self._value
+ by = w_by._value
+ if not by:
+ raise OperationError(space.w_ValueError, space.wrap("empty separator"))
+ return space.newlist_str(rsplit(value, by, maxsplit))
def str_join__String_ANY(space, w_self, w_list):
l = space.listview_str(w_list)
diff --git a/pypy/objspace/std/test/test_liststrategies.py b/pypy/objspace/std/test/test_liststrategies.py
--- a/pypy/objspace/std/test/test_liststrategies.py
+++ b/pypy/objspace/std/test/test_liststrategies.py
@@ -555,10 +555,14 @@
try:
w_l = space.call_method(w_s, "split")
w_l2 = space.call_method(w_s, "split", space.wrap(" "))
+ w_l3 = space.call_method(w_s, "rsplit")
+ w_l4 = space.call_method(w_s, "rsplit", space.wrap(" "))
finally:
del space.newlist
assert space.listview_str(w_l) == ["a", "b", "c"]
assert space.listview_str(w_l2) == ["a", "b", "c"]
+ assert space.listview_str(w_l3) == ["a", "b", "c"]
+ assert space.listview_str(w_l4) == ["a", "b", "c"]
def test_unicode_uses_newlist_unicode(self):
space = self.space
@@ -567,10 +571,14 @@
try:
w_l = space.call_method(w_u, "split")
w_l2 = space.call_method(w_u, "split", space.wrap(" "))
+ w_l3 = space.call_method(w_u, "rsplit")
+ w_l4 = space.call_method(w_u, "rsplit", space.wrap(" "))
finally:
del space.newlist
assert space.listview_unicode(w_l) == [u"a", u"b", u"c"]
assert space.listview_unicode(w_l2) == [u"a", u"b", u"c"]
+ assert space.listview_unicode(w_l3) == [u"a", u"b", u"c"]
+ assert space.listview_unicode(w_l4) == [u"a", u"b", u"c"]
def test_pop_without_argument_is_fast(self):
space = self.space
diff --git a/rpython/rlib/rstring.py b/rpython/rlib/rstring.py
--- a/rpython/rlib/rstring.py
+++ b/rpython/rlib/rstring.py
@@ -18,11 +18,27 @@
if bylen == 0:
raise ValueError("empty separator")
+ start = 0
+ if bylen == 1:
+ # fast path: uses str.rfind(character) and str.count(character)
+ by = by[0] # annotator hack: string -> char
+ count = value.count(by)
+ if 0 <= maxsplit < count:
+ count = maxsplit
+ res = newlist_hint(count + 1)
+ while count > 0:
+ next = value.find(by, start)
+ res.append(value[start:next])
+ start = next + bylen
+ count -= 1
+ res.append(value[start:len(value)])
+ return res
+
if maxsplit > 0:
res = newlist_hint(min(maxsplit + 1, len(value)))
else:
res = []
- start = 0
+
while maxsplit != 0:
next = value.find(by, start)
if next < 0:
diff --git a/rpython/rlib/test/test_rstring.py b/rpython/rlib/test/test_rstring.py
--- a/rpython/rlib/test/test_rstring.py
+++ b/rpython/rlib/test/test_rstring.py
@@ -10,6 +10,7 @@
assert split('a|b|c|d', '|') == ['a', 'b', 'c', 'd']
assert split('a|b|c|d', '|', 2) == ['a', 'b', 'c|d']
assert split('a//b//c//d', '//') == ['a', 'b', 'c', 'd']
+ assert split('a//b//c//d', '//', 2) == ['a', 'b', 'c//d']
assert split('endcase test', 'test') == ['endcase ', '']
py.test.raises(ValueError, split, 'abc', '')
More information about the pypy-commit
mailing list