diff options
author | Hye-Shik Chang <hyeshik@gmail.com> | 2003-12-15 18:49:53 (GMT) |
---|---|---|
committer | Hye-Shik Chang <hyeshik@gmail.com> | 2003-12-15 18:49:53 (GMT) |
commit | 3ae811b57d227a220f207869487fd9251e278608 (patch) | |
tree | ccbc4b81578fa69e6bc65df8da4994bf9a4b6e49 /Objects/stringobject.c | |
parent | dce391cb398f4ce266d98130d10810a6a36617b3 (diff) | |
download | cpython-3ae811b57d227a220f207869487fd9251e278608.zip cpython-3ae811b57d227a220f207869487fd9251e278608.tar.gz cpython-3ae811b57d227a220f207869487fd9251e278608.tar.bz2 |
Add rsplit method for str and unicode builtin types.
SF feature request #801847.
Original patch is written by Sean Reifschneider.
Diffstat (limited to 'Objects/stringobject.c')
-rw-r--r-- | Objects/stringobject.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/Objects/stringobject.c b/Objects/stringobject.c index d3351df..9512059 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -1407,6 +1407,129 @@ string_split(PyStringObject *self, PyObject *args) return NULL; } +static PyObject * +rsplit_whitespace(const char *s, int len, int maxsplit) +{ + int i, j, err; + PyObject* item; + PyObject *list = PyList_New(0); + + if (list == NULL) + return NULL; + + for (i = j = len - 1; i >= 0; ) { + while (i >= 0 && isspace(Py_CHARMASK(s[i]))) + i--; + j = i; + while (i >= 0 && !isspace(Py_CHARMASK(s[i]))) + i--; + if (j > i) { + if (maxsplit-- <= 0) + break; + item = PyString_FromStringAndSize(s+i+1, (int)(j-i)); + if (item == NULL) + goto finally; + err = PyList_Insert(list, 0, item); + Py_DECREF(item); + if (err < 0) + goto finally; + while (i >= 0 && isspace(Py_CHARMASK(s[i]))) + i--; + j = i; + } + } + if (j >= 0) { + item = PyString_FromStringAndSize(s, (int)(j + 1)); + if (item == NULL) + goto finally; + err = PyList_Insert(list, 0, item); + Py_DECREF(item); + if (err < 0) + goto finally; + } + return list; + finally: + Py_DECREF(list); + return NULL; +} + + +PyDoc_STRVAR(rsplit__doc__, +"S.rsplit([sep [,maxsplit]]) -> list of strings\n\ +\n\ +Return a list of the words in the string S, using sep as the\n\ +delimiter string, starting at the end of the string and working\n\ +to the front. If maxsplit is given, at most maxsplit splits are\n\ +done. If sep is not specified or is None, any whitespace string\n\ +is a separator."); + +static PyObject * +string_rsplit(PyStringObject *self, PyObject *args) +{ + int len = PyString_GET_SIZE(self), n, i, j, err; + int maxsplit = -1; + const char *s = PyString_AS_STRING(self), *sub; + PyObject *list, *item, *subobj = Py_None; + + if (!PyArg_ParseTuple(args, "|Oi:rsplit", &subobj, &maxsplit)) + return NULL; + if (maxsplit < 0) + maxsplit = INT_MAX; + if (subobj == Py_None) + return rsplit_whitespace(s, len, maxsplit); + if (PyString_Check(subobj)) { + sub = PyString_AS_STRING(subobj); + n = PyString_GET_SIZE(subobj); + } +#ifdef Py_USING_UNICODE + else if (PyUnicode_Check(subobj)) + return PyUnicode_RSplit((PyObject *)self, subobj, maxsplit); +#endif + else if (PyObject_AsCharBuffer(subobj, &sub, &n)) + return NULL; + if (n == 0) { + PyErr_SetString(PyExc_ValueError, "empty separator"); + return NULL; + } + + list = PyList_New(0); + if (list == NULL) + return NULL; + + j = len; + i = j - n; + while (i >= 0) { + if (s[i] == sub[0] && memcmp(s+i, sub, n) == 0) { + if (maxsplit-- <= 0) + break; + item = PyString_FromStringAndSize(s+i+n, (int)(j-i-n)); + if (item == NULL) + goto fail; + err = PyList_Insert(list, 0, item); + Py_DECREF(item); + if (err < 0) + goto fail; + j = i; + i -= n; + } + else + i--; + } + item = PyString_FromStringAndSize(s, j); + if (item == NULL) + goto fail; + err = PyList_Insert(list, 0, item); + Py_DECREF(item); + if (err < 0) + goto fail; + + return list; + + fail: + Py_DECREF(list); + return NULL; +} + PyDoc_STRVAR(join__doc__, "S.join(sequence) -> string\n\ @@ -3064,6 +3187,7 @@ string_methods[] = { string.maketrans(). */ {"join", (PyCFunction)string_join, METH_O, join__doc__}, {"split", (PyCFunction)string_split, METH_VARARGS, split__doc__}, + {"rsplit", (PyCFunction)string_rsplit, METH_VARARGS, rsplit__doc__}, {"lower", (PyCFunction)string_lower, METH_NOARGS, lower__doc__}, {"upper", (PyCFunction)string_upper, METH_NOARGS, upper__doc__}, {"islower", (PyCFunction)string_islower, METH_NOARGS, islower__doc__}, |