strop_upper(), strop_lower(): shared code version caused to much of a
performance hit. Urg. Reverted. strop_joinfields(): re-instate optimizations for lists and tuples, but support arbitrary other kinds of sequences as well.
This commit is contained in:
parent
7fc0bf8247
commit
04d2d15b6b
|
@ -169,52 +169,73 @@ strop_joinfields(self, args)
|
|||
PyObject *args;
|
||||
{
|
||||
PyObject *seq, *item, *res;
|
||||
char *sep, *p;
|
||||
int seplen, seqlen, reslen, itemlen, i;
|
||||
char *p, *sep = NULL;
|
||||
int seqlen, reslen, itemlen, i, seplen = 0;
|
||||
int ownrefs = 0;
|
||||
PyObject* (*getitemfunc) Py_PROTO((PyObject*, int));
|
||||
|
||||
sep = NULL;
|
||||
seplen = 0;
|
||||
if (!PyArg_ParseTuple(args, "O|s#", &seq, &sep, &seplen))
|
||||
return NULL;
|
||||
if (sep == NULL) {
|
||||
sep = " ";
|
||||
seplen = 1;
|
||||
}
|
||||
if (!PySequence_Check(seq)) {
|
||||
/* do it this way to optimize for the common cases, but also
|
||||
* support the more general sequence protocol
|
||||
*/
|
||||
if (PyList_Check(seq)) {
|
||||
getitemfunc = PyList_GetItem;
|
||||
seqlen = PyList_Size(seq);
|
||||
}
|
||||
else if (PyTuple_Check(seq)) {
|
||||
getitemfunc = PyTuple_GetItem;
|
||||
seqlen = PyTuple_Size(seq);
|
||||
}
|
||||
else if (PySequence_Check(seq)) {
|
||||
getitemfunc = PySequence_GetItem;
|
||||
seqlen = PySequence_Length(seq);
|
||||
ownrefs = 1;
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"first argument must be a sequence");
|
||||
return NULL;
|
||||
}
|
||||
seqlen = PySequence_Length(seq);
|
||||
if (seqlen < 0 && PyErr_Occurred())
|
||||
return NULL;
|
||||
|
||||
reslen = 0;
|
||||
for (i = 0; i < seqlen; i++) {
|
||||
if (!(item = PySequence_GetItem(seq, i)))
|
||||
if (!(item = getitemfunc(seq, i)))
|
||||
return NULL;
|
||||
|
||||
if (!PyString_Check(item)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"first argument must be sequence of strings");
|
||||
Py_DECREF(item);
|
||||
if (ownrefs)
|
||||
Py_DECREF(item);
|
||||
return NULL;
|
||||
}
|
||||
if (i > 0)
|
||||
reslen += seplen;
|
||||
reslen += PyString_Size(item);
|
||||
Py_DECREF(item);
|
||||
if (ownrefs)
|
||||
Py_DECREF(item);
|
||||
}
|
||||
if (seqlen == 1)
|
||||
if (seqlen == 1) {
|
||||
/* Optimization if there's only one item */
|
||||
return PySequence_GetItem(seq, 0);
|
||||
item = getitemfunc(seq, 0);
|
||||
if (!ownrefs)
|
||||
Py_XINCREF(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
res = PyString_FromStringAndSize((char *)NULL, reslen);
|
||||
if (res == NULL)
|
||||
return NULL;
|
||||
p = PyString_AsString(res);
|
||||
for (i = 0; i < seqlen; i++) {
|
||||
if (!(item = PySequence_GetItem(seq, i))) {
|
||||
if (!(item = getitemfunc(seq, i))) {
|
||||
Py_DECREF(res);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -225,7 +246,8 @@ strop_joinfields(self, args)
|
|||
itemlen = PyString_Size(item);
|
||||
memcpy(p, PyString_AsString(item), itemlen);
|
||||
p += itemlen;
|
||||
Py_DECREF(item);
|
||||
if (ownrefs)
|
||||
Py_DECREF(item);
|
||||
}
|
||||
if (p != PyString_AsString(res) + reslen) {
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
|
@ -356,11 +378,9 @@ strop_rstrip(self, args)
|
|||
|
||||
|
||||
static PyObject *
|
||||
do_casechange(self, args, test, conv)
|
||||
strop_lower(self, args)
|
||||
PyObject *self; /* Not used */
|
||||
PyObject *args;
|
||||
int (*test) Py_PROTO((int));
|
||||
int (*conv) Py_PROTO((int));
|
||||
{
|
||||
char *s, *s_new;
|
||||
int i, n;
|
||||
|
@ -376,9 +396,9 @@ do_casechange(self, args, test, conv)
|
|||
changed = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
int c = Py_CHARMASK(*s++);
|
||||
if (test(c)) {
|
||||
if (isupper(c)) {
|
||||
changed = 1;
|
||||
*s_new = conv(c);
|
||||
*s_new = tolower(c);
|
||||
} else
|
||||
*s_new = c;
|
||||
s_new++;
|
||||
|
@ -391,21 +411,39 @@ do_casechange(self, args, test, conv)
|
|||
return new;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
strop_lower(self, args)
|
||||
PyObject *self; /* Not used */
|
||||
PyObject *args;
|
||||
{
|
||||
return do_casechange(self, args, isupper, tolower);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
strop_upper(self, args)
|
||||
PyObject *self; /* Not used */
|
||||
PyObject *args;
|
||||
{
|
||||
return do_casechange(self, args, islower, toupper);
|
||||
char *s, *s_new;
|
||||
int i, n;
|
||||
PyObject *new;
|
||||
int changed;
|
||||
|
||||
if (!PyArg_Parse(args, "s#", &s, &n))
|
||||
return NULL;
|
||||
new = PyString_FromStringAndSize(NULL, n);
|
||||
if (new == NULL)
|
||||
return NULL;
|
||||
s_new = PyString_AsString(new);
|
||||
changed = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
int c = Py_CHARMASK(*s++);
|
||||
if (islower(c)) {
|
||||
changed = 1;
|
||||
*s_new = toupper(c);
|
||||
} else
|
||||
*s_new = c;
|
||||
s_new++;
|
||||
}
|
||||
if (!changed) {
|
||||
Py_DECREF(new);
|
||||
Py_INCREF(args);
|
||||
return args;
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue