diff options
-rwxr-xr-x | Lib/UserString.py | 6 | ||||
-rw-r--r-- | Lib/test/string_tests.py | 12 | ||||
-rw-r--r-- | Objects/stringobject.c | 101 |
3 files changed, 101 insertions, 18 deletions
diff --git a/Lib/UserString.py b/Lib/UserString.py index 45cdeb5..f4f5cab 100755 --- a/Lib/UserString.py +++ b/Lib/UserString.py @@ -108,7 +108,7 @@ class UserString: def join(self, seq): return self.data.join(seq) def ljust(self, width): return self.__class__(self.data.ljust(width)) def lower(self): return self.__class__(self.data.lower()) - def lstrip(self): return self.__class__(self.data.lstrip()) + def lstrip(self, sep=None): return self.__class__(self.data.lstrip(sep)) def replace(self, old, new, maxsplit=-1): return self.__class__(self.data.replace(old, new, maxsplit)) def rfind(self, sub, start=0, end=sys.maxint): @@ -116,13 +116,13 @@ class UserString: def rindex(self, sub, start=0, end=sys.maxint): return self.data.rindex(sub, start, end) def rjust(self, width): return self.__class__(self.data.rjust(width)) - def rstrip(self): return self.__class__(self.data.rstrip()) + def rstrip(self, sep=None): return self.__class__(self.data.rstrip(sep)) def split(self, sep=None, maxsplit=-1): return self.data.split(sep, maxsplit) def splitlines(self, keepends=0): return self.data.splitlines(keepends) def startswith(self, prefix, start=0, end=sys.maxint): return self.data.startswith(prefix, start, end) - def strip(self): return self.__class__(self.data.strip()) + def strip(self, sep=None): return self.__class__(self.data.strip(sep)) def swapcase(self): return self.__class__(self.data.swapcase()) def title(self): return self.__class__(self.data.title()) def translate(self, *args): diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py index 4b2f0e3..5c8dd93 100644 --- a/Lib/test/string_tests.py +++ b/Lib/test/string_tests.py @@ -163,6 +163,18 @@ def run_method_tests(test): test('rstrip', ' hello ', ' hello') test('strip', 'hello', 'hello') + # strip/lstrip/rstrip with None arg + test('strip', ' hello ', 'hello', None) + test('lstrip', ' hello ', 'hello ', None) + test('rstrip', ' hello ', ' hello', None) + test('strip', 'hello', 'hello', None) + + # strip/lstrip/rstrip with real arg + test('strip', 'xyzzyhelloxyzzy', 'hello', 'xyz') + test('lstrip', 'xyzzyhelloxyzzy', 'helloxyzzy', 'xyz') + test('rstrip', 'xyzzyhelloxyzzy', 'xyzzyhello', 'xyz') + test('strip', 'hello', 'hello', 'xyz') + test('swapcase', 'HeLLo cOmpUteRs', 'hEllO CoMPuTErS') test('translate', 'xyzabcdef', 'xyzxyz', transtable, 'def') diff --git a/Objects/stringobject.c b/Objects/stringobject.c index 359e942..709c5f7 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -1002,6 +1002,9 @@ static PyBufferProcs string_as_buffer = { #define RIGHTSTRIP 1 #define BOTHSTRIP 2 +/* Arrays indexed by above */ +static const char *stripname[] = {"lstrip", "rstrip", "strip"}; + static PyObject * split_whitespace(const char *s, int len, int maxsplit) @@ -1377,6 +1380,39 @@ string_rindex(PyStringObject *self, PyObject *args) static PyObject * +do_xstrip(PyStringObject *self, int striptype, PyObject *sepobj) +{ + char *s = PyString_AS_STRING(self); + int len = PyString_GET_SIZE(self); + char *sep = PyString_AS_STRING(sepobj); + int seplen = PyString_GET_SIZE(sepobj); + int i, j; + + i = 0; + if (striptype != RIGHTSTRIP) { + while (i < len && memchr(sep, Py_CHARMASK(s[i]), seplen)) { + i++; + } + } + + j = len; + if (striptype != LEFTSTRIP) { + do { + j--; + } while (j >= i && memchr(sep, Py_CHARMASK(s[j]), seplen)); + j++; + } + + if (i == 0 && j == len && PyString_CheckExact(self)) { + Py_INCREF(self); + return (PyObject*)self; + } + else + return PyString_FromStringAndSize(s+i, j-i); +} + + +static PyObject * do_strip(PyStringObject *self, int striptype) { char *s = PyString_AS_STRING(self); @@ -1406,40 +1442,75 @@ do_strip(PyStringObject *self, int striptype) } +static PyObject * +do_argstrip(PyStringObject *self, int striptype, PyObject *args) +{ + PyObject *sep = NULL; + + if (!PyArg_ParseTuple(args, "|O:[lr]strip", &sep)) + return NULL; + + if (sep != NULL && sep != Py_None) { + /* XXX What about Unicode? */ + if (!PyString_Check(sep)) { + PyErr_Format(PyExc_TypeError, + "%s arg must be None or string", + stripname[striptype]); + return NULL; + } + return do_xstrip(self, striptype, sep); + } + + return do_strip(self, striptype); +} + + static char strip__doc__[] = -"S.strip() -> string\n\ +"S.strip([sep]) -> string\n\ \n\ Return a copy of the string S with leading and trailing\n\ -whitespace removed."; +whitespace removed.\n\ +If sep is given and not None, remove characters in sep instead."; static PyObject * -string_strip(PyStringObject *self) +string_strip(PyStringObject *self, PyObject *args) { - return do_strip(self, BOTHSTRIP); + if (PyTuple_GET_SIZE(args) == 0) + return do_strip(self, BOTHSTRIP); /* Common case */ + else + return do_argstrip(self, BOTHSTRIP, args); } static char lstrip__doc__[] = -"S.lstrip() -> string\n\ +"S.lstrip([sep]) -> string\n\ \n\ -Return a copy of the string S with leading whitespace removed."; +Return a copy of the string S with leading whitespace removed.\n\ +If sep is given and not None, remove characters in sep instead."; static PyObject * -string_lstrip(PyStringObject *self) +string_lstrip(PyStringObject *self, PyObject *args) { - return do_strip(self, LEFTSTRIP); + if (PyTuple_GET_SIZE(args) == 0) + return do_strip(self, LEFTSTRIP); /* Common case */ + else + return do_argstrip(self, LEFTSTRIP, args); } static char rstrip__doc__[] = -"S.rstrip() -> string\n\ +"S.rstrip([sep]) -> string\n\ \n\ -Return a copy of the string S with trailing whitespace removed."; +Return a copy of the string S with trailing whitespace removed.\n\ +If sep is given and not None, remove characters in sep instead."; static PyObject * -string_rstrip(PyStringObject *self) +string_rstrip(PyStringObject *self, PyObject *args) { - return do_strip(self, RIGHTSTRIP); + if (PyTuple_GET_SIZE(args) == 0) + return do_strip(self, RIGHTSTRIP); /* Common case */ + else + return do_argstrip(self, RIGHTSTRIP, args); } @@ -2644,13 +2715,13 @@ string_methods[] = { {"endswith", (PyCFunction)string_endswith, METH_VARARGS, endswith__doc__}, {"find", (PyCFunction)string_find, METH_VARARGS, find__doc__}, {"index", (PyCFunction)string_index, METH_VARARGS, index__doc__}, - {"lstrip", (PyCFunction)string_lstrip, METH_NOARGS, lstrip__doc__}, + {"lstrip", (PyCFunction)string_lstrip, METH_VARARGS, lstrip__doc__}, {"replace", (PyCFunction)string_replace, METH_VARARGS, replace__doc__}, {"rfind", (PyCFunction)string_rfind, METH_VARARGS, rfind__doc__}, {"rindex", (PyCFunction)string_rindex, METH_VARARGS, rindex__doc__}, - {"rstrip", (PyCFunction)string_rstrip, METH_NOARGS, rstrip__doc__}, + {"rstrip", (PyCFunction)string_rstrip, METH_VARARGS, rstrip__doc__}, {"startswith", (PyCFunction)string_startswith, METH_VARARGS, startswith__doc__}, - {"strip", (PyCFunction)string_strip, METH_NOARGS, strip__doc__}, + {"strip", (PyCFunction)string_strip, METH_VARARGS, strip__doc__}, {"swapcase", (PyCFunction)string_swapcase, METH_NOARGS, swapcase__doc__}, {"translate", (PyCFunction)string_translate, METH_VARARGS, translate__doc__}, {"title", (PyCFunction)string_title, METH_NOARGS, title__doc__}, |