Rewrote translate() as follows:

- 'delete' is a C++ keyword; use 'del_table' instead
	- apply Py_CHARMASK() to del_table[i] before using it as an index
	  *** this fixes a bug that was just reported on the list ***
	- if the translation didn't make any changes, INCREF and return
	  the original string
	- when del_table is empty or omitted, don't copy the translation
	  table to a table of ints (should be a bit faster)

Rewrote maketrans() to avoid copying the table (2-3% faster).
This commit is contained in:
Guido van Rossum 1997-01-06 16:50:09 +00:00
parent 04d2d15b6b
commit e0548b8da7
1 changed files with 51 additions and 27 deletions

View File

@ -661,8 +661,9 @@ strop_maketrans(self, args)
PyObject *self; /* Not used */
PyObject *args;
{
unsigned char c[256], *from=NULL, *to=NULL;
unsigned char *c, *from=NULL, *to=NULL;
int i, fromlen=0, tolen=0;
PyObject *result;
if (!PyArg_ParseTuple(args, "s#s#", &from, &fromlen, &to, &tolen))
return NULL;
@ -672,12 +673,17 @@ strop_maketrans(self, args)
"maketrans arguments must have same length");
return NULL;
}
result = PyString_FromStringAndSize((char *)NULL, 256);
if (result == NULL)
return NULL;
c = (unsigned char *) PyString_AS_STRING((PyStringObject *)result);
for (i = 0; i < 256; i++)
c[i]=(unsigned char)i;
for (i = 0; i < fromlen; i++)
c[from[i]]=to[i];
return PyString_FromStringAndSize((char *)c, 256);
return result;
}
@ -686,48 +692,66 @@ strop_translate(self, args)
PyObject *self;
PyObject *args;
{
char *input, *table, *output, *output_start, *delete=NULL;
register char *input, *table, *output;
register int i, c, changed = 0;
PyObject *input_obj;
char *table1, *output_start, *del_table=NULL;
int inlen, tablen, dellen = 0;
PyObject *result;
int i, trans_table[256];
int trans_table[256];
if (!PyArg_ParseTuple(args, "s#s#|s#", &input, &inlen,
&table, &tablen, &delete, &dellen))
if (!PyArg_ParseTuple(args, "Ss#|s#", &input_obj,
&table1, &tablen, &del_table, &dellen))
return NULL;
if (tablen != 256) {
PyErr_SetString(PyExc_ValueError,
"translation table must be 256 characters long");
return NULL;
}
for (i = 0; i < 256; i++)
trans_table[i] = Py_CHARMASK(table[i]);
if (delete != NULL) {
for (i = 0; i < dellen; i++)
trans_table[(int)delete[i]] = -1;
}
table = table1;
inlen = PyString_Size(input_obj);
result = PyString_FromStringAndSize((char *)NULL, inlen);
if (result == NULL)
return NULL;
output_start = output = PyString_AsString(result);
input = PyString_AsString(input_obj);
if (delete != NULL && dellen != 0) {
for (i = 0; i < inlen; i++) {
int c = Py_CHARMASK(*input++);
if (trans_table[c] != -1)
*output++ = (char)trans_table[c];
}
/* Fix the size of the resulting string */
if (inlen > 0 &&_PyString_Resize(&result, output-output_start))
return NULL;
} else {
/* If no deletions are required, use a faster loop */
for (i = 0; i < inlen; i++) {
int c = Py_CHARMASK(*input++);
*output++ = (char)trans_table[c];
if (dellen == 0) {
/* If no deletions are required, use faster code */
for (i = inlen; --i >= 0; ) {
c = Py_CHARMASK(*input++);
if (Py_CHARMASK((*output++ = table[c])) != c)
changed = 1;
}
if (changed)
return result;
Py_DECREF(result);
Py_INCREF(input_obj);
return input_obj;
}
for (i = 0; i < 256; i++)
trans_table[i] = Py_CHARMASK(table[i]);
for (i = 0; i < dellen; i++)
trans_table[Py_CHARMASK(del_table[i])] = -1;
for (i = inlen; --i >= 0; ) {
c = Py_CHARMASK(*input++);
if (trans_table[c] != -1)
if (Py_CHARMASK(*output++ = (char)trans_table[c]) == c)
continue;
changed = 1;
}
if (!changed) {
Py_DECREF(result);
Py_INCREF(input_obj);
return input_obj;
}
/* Fix the size of the resulting string */
if (inlen > 0 &&_PyString_Resize(&result, output-output_start))
return NULL;
return result;
}