needforspeed: added rpartition implementation

This commit is contained in:
Fredrik Lundh 2006-05-26 18:15:38 +00:00
parent be9f219e40
commit b3167cbcd7
5 changed files with 166 additions and 2 deletions

View file

@ -95,3 +95,10 @@ fastsearch(const STRINGLIB_CHAR* s, Py_ssize_t n,
}
#endif
/*
Local variables:
c-basic-offset: 4
indent-tabs-mode: nil
End:
*/

View file

@ -5,7 +5,7 @@
Py_LOCAL(PyObject*)
partition(PyObject* str_obj, const STRINGLIB_CHAR* str, Py_ssize_t str_len,
PyObject* sep_obj, const STRINGLIB_CHAR* sep, Py_ssize_t sep_len)
PyObject* sep_obj, const STRINGLIB_CHAR* sep, Py_ssize_t sep_len)
{
PyObject* out;
Py_ssize_t pos;
@ -45,4 +45,64 @@ partition(PyObject* str_obj, const STRINGLIB_CHAR* str, Py_ssize_t str_len,
return out;
}
Py_LOCAL(PyObject*)
rpartition(PyObject* str_obj, const STRINGLIB_CHAR* str, Py_ssize_t str_len,
PyObject* sep_obj, const STRINGLIB_CHAR* sep, Py_ssize_t sep_len)
{
PyObject* out;
Py_ssize_t pos;
if (sep_len == 0) {
PyErr_SetString(PyExc_ValueError, "empty separator");
return NULL;
}
out = PyTuple_New(3);
if (!out)
return NULL;
/* XXX - create reversefastsearch helper! */
if (sep_len == 0)
pos = str_len;
else {
Py_ssize_t j;
pos = -1;
for (j = str_len - sep_len; j >= 0; --j)
if (STRINGLIB_CMP(str+j, sep, sep_len) == 0) {
pos = j;
break;
}
}
if (pos < 0) {
Py_INCREF(str_obj);
PyTuple_SET_ITEM(out, 0, (PyObject*) str_obj);
Py_INCREF(STRINGLIB_EMPTY);
PyTuple_SET_ITEM(out, 1, (PyObject*) STRINGLIB_EMPTY);
Py_INCREF(STRINGLIB_EMPTY);
PyTuple_SET_ITEM(out, 2, (PyObject*) STRINGLIB_EMPTY);
return out;
}
PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(str, pos));
Py_INCREF(sep_obj);
PyTuple_SET_ITEM(out, 1, sep_obj);
pos += sep_len;
PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(str + pos, str_len - pos));
if (PyErr_Occurred()) {
Py_DECREF(out);
return NULL;
}
return out;
}
#endif
/*
Local variables:
c-basic-offset: 4
indent-tabs-mode: nil
End:
*/

View file

@ -768,7 +768,10 @@ PyString_AsStringAndSize(register PyObject *obj,
/* stringlib components */
#define STRINGLIB_CHAR char
#define STRINGLIB_NEW PyString_FromStringAndSize
#define STRINGLIB_CMP memcmp
#define STRINGLIB_EMPTY nullstring
#include "stringlib/fastsearch.h"
@ -1530,6 +1533,37 @@ string_partition(PyStringObject *self, PyObject *sep_obj)
);
}
PyDoc_STRVAR(rpartition__doc__,
"S.rpartition(sep) -> (head, sep, tail)\n\
\n\
Searches for the separator sep in S, starting at the end of S, and returns\n\
the part before it, the separator itself, and the part after it. If the\n\
separator is not found, returns S and two empty strings.");
static PyObject *
string_rpartition(PyStringObject *self, PyObject *sep_obj)
{
const char *sep;
Py_ssize_t sep_len;
if (PyString_Check(sep_obj)) {
sep = PyString_AS_STRING(sep_obj);
sep_len = PyString_GET_SIZE(sep_obj);
}
#ifdef Py_USING_UNICODE
else if (PyUnicode_Check(sep_obj))
return PyUnicode_Partition((PyObject *) self, sep_obj);
#endif
else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len))
return NULL;
return rpartition(
(PyObject*) self,
PyString_AS_STRING(self), PyString_GET_SIZE(self),
sep_obj, sep, sep_len
);
}
Py_LOCAL(PyObject *)
rsplit_whitespace(const char *s, Py_ssize_t len, Py_ssize_t maxsplit)
{
@ -3810,6 +3844,8 @@ string_methods[] = {
{"rfind", (PyCFunction)string_rfind, METH_VARARGS, rfind__doc__},
{"rindex", (PyCFunction)string_rindex, METH_VARARGS, rindex__doc__},
{"rstrip", (PyCFunction)string_rstrip, METH_VARARGS, rstrip__doc__},
{"rpartition", (PyCFunction)string_rpartition, METH_O,
rpartition__doc__},
{"startswith", (PyCFunction)string_startswith, METH_VARARGS,
startswith__doc__},
{"strip", (PyCFunction)string_strip, METH_VARARGS, strip__doc__},

View file

@ -3858,6 +3858,14 @@ int PyUnicode_EncodeDecimal(Py_UNICODE *s,
#define STRINGLIB_NEW PyUnicode_FromUnicode
Py_LOCAL(int)
STRINGLIB_CMP(const Py_UNICODE* str, const Py_UNICODE* other, Py_ssize_t len)
{
if (str[0] == other[0])
return 0;
return memcmp((void*) str, (void*) other, len * sizeof(Py_UNICODE));
}
#define STRINGLIB_EMPTY unicode_empty
#include "stringlib/fastsearch.h"
@ -6225,6 +6233,34 @@ PyUnicode_Partition(PyObject *str_in, PyObject *sep_in)
return out;
}
PyObject *
PyUnicode_RPartition(PyObject *str_in, PyObject *sep_in)
{
PyObject* str_obj;
PyObject* sep_obj;
PyObject* out;
str_obj = PyUnicode_FromObject(str_in);
if (!str_obj)
return NULL;
sep_obj = PyUnicode_FromObject(sep_in);
if (!sep_obj) {
Py_DECREF(str_obj);
return NULL;
}
out = rpartition(
str_obj, PyUnicode_AS_UNICODE(str_obj), PyUnicode_GET_SIZE(str_obj),
sep_obj, PyUnicode_AS_UNICODE(sep_obj), PyUnicode_GET_SIZE(sep_obj)
);
Py_DECREF(sep_obj);
Py_DECREF(str_obj);
return out;
}
PyDoc_STRVAR(partition__doc__,
"S.partition(sep) -> (head, sep, tail)\n\
\n\
@ -6238,6 +6274,19 @@ unicode_partition(PyUnicodeObject *self, PyObject *separator)
return PyUnicode_Partition((PyObject *)self, separator);
}
PyDoc_STRVAR(rpartition__doc__,
"S.rpartition(sep) -> (head, sep, tail)\n\
\n\
Searches for the separator sep in S, starting at the end of S, and returns\n\
the part before it, the separator itself, and the part after it. If the\n\
separator is not found, returns S and two empty strings.");
static PyObject*
unicode_rpartition(PyUnicodeObject *self, PyObject *separator)
{
return PyUnicode_RPartition((PyObject *)self, separator);
}
PyObject *PyUnicode_RSplit(PyObject *s,
PyObject *sep,
Py_ssize_t maxsplit)
@ -6502,6 +6551,7 @@ static PyMethodDef unicode_methods[] = {
{"rindex", (PyCFunction) unicode_rindex, METH_VARARGS, rindex__doc__},
{"rjust", (PyCFunction) unicode_rjust, METH_VARARGS, rjust__doc__},
{"rstrip", (PyCFunction) unicode_rstrip, METH_VARARGS, rstrip__doc__},
{"rpartition", (PyCFunction) unicode_rpartition, METH_O, rpartition__doc__},
{"splitlines", (PyCFunction) unicode_splitlines, METH_VARARGS, splitlines__doc__},
{"strip", (PyCFunction) unicode_strip, METH_VARARGS, strip__doc__},
{"swapcase", (PyCFunction) unicode_swapcase, METH_NOARGS, swapcase__doc__},