[pypy-commit] pypy default: startswith and endswith implementations
cfbolz
noreply at buildbot.pypy.org
Mon Jun 17 14:35:29 CEST 2013
Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch:
Changeset: r64913:3e0a1d3ed9e0
Date: 2013-06-16 09:50 +0200
http://bitbucket.org/pypy/pypy/changeset/3e0a1d3ed9e0/
Log: startswith and endswith implementations
diff --git a/rpython/rlib/rstring.py b/rpython/rlib/rstring.py
--- a/rpython/rlib/rstring.py
+++ b/rpython/rlib/rstring.py
@@ -1,5 +1,6 @@
""" String builder interface and string functions
"""
+import sys
from rpython.annotator.model import (SomeObject, SomeString, s_None, SomeChar,
SomeInteger, SomeUnicodeCodePoint, SomeUnicodeString, SomePtr, SomePBC)
@@ -7,6 +8,7 @@
from rpython.rlib.rarithmetic import ovfcheck
from rpython.rtyper.extregistry import ExtRegistryEntry
from rpython.tool.pairtype import pairtype
+from rpython.rlib import jit
# -------------- public API for string functions -----------------------
@@ -145,6 +147,45 @@
return builder.build()
+def _normalize_start_end(length, start, end):
+ if start < 0:
+ start += length
+ if start < 0:
+ start = 0
+ if end < 0:
+ end += length
+ if end < 0:
+ end = 0
+ elif end > length:
+ end = length
+ return start, end
+
+ at specialize.argtype(0)
+ at jit.elidable
+def startswith(u_self, prefix, start=0, end=sys.maxint):
+ length = len(u_self)
+ start, end = _normalize_start_end(length, start, end)
+ stop = start + len(prefix)
+ if stop > end:
+ return False
+ for i in range(len(prefix)):
+ if u_self[start+i] != prefix[i]:
+ return False
+ return True
+
+ at specialize.argtype(0)
+ at jit.elidable
+def endswith(u_self, suffix, start=0, end=sys.maxint):
+ length = len(u_self)
+ start, end = _normalize_start_end(length, start, end)
+ begin = end - len(suffix)
+ if begin < start:
+ return False
+ for i in range(len(suffix)):
+ if u_self[begin+i] != suffix[i]:
+ return False
+ return True
+
# -------------- public API ---------------------------------
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
@@ -1,7 +1,7 @@
import sys, py
from rpython.rlib.rstring import StringBuilder, UnicodeBuilder, split, rsplit
-from rpython.rlib.rstring import replace
+from rpython.rlib.rstring import replace, startswith, endswith
from rpython.rtyper.test.tool import BaseRtypingTest, LLRtypeMixin
def test_split():
@@ -111,6 +111,37 @@
with py.test.raises(OverflowError):
replace(s, u"a", s, len(s) - 10)
+def test_startswith():
+ assert startswith('ab', 'ab') is True
+ assert startswith('ab', 'a') is True
+ assert startswith('ab', '') is True
+ assert startswith('x', 'a') is False
+ assert startswith('x', 'x') is True
+ assert startswith('', '') is True
+ assert startswith('', 'a') is False
+ assert startswith('x', 'xx') is False
+ assert startswith('y', 'xx') is False
+ assert startswith('ab', 'a', 0) is True
+ assert startswith('ab', 'a', 1) is False
+ assert startswith('ab', 'b', 1) is True
+ assert startswith('abc', 'bc', 1, 2) is False
+ assert startswith('abc', 'c', -1, 4) is True
+
+def test_endswith():
+ assert endswith('ab', 'ab') is True
+ assert endswith('ab', 'b') is True
+ assert endswith('ab', '') is True
+ assert endswith('x', 'a') is False
+ assert endswith('x', 'x') is True
+ assert endswith('', '') is True
+ assert endswith('', 'a') is False
+ assert endswith('x', 'xx') is False
+ assert endswith('y', 'xx') is False
+ assert endswith('abc', 'ab', 0, 2) is True
+ assert endswith('abc', 'bc', 1) is True
+ assert endswith('abc', 'bc', 2) is False
+ assert endswith('abc', 'b', -3, -1) is True
+
def test_string_builder():
s = StringBuilder()
s.append("a")
More information about the pypy-commit
mailing list