diff options
author | Georg Brandl <georg@python.org> | 2007-11-27 23:48:05 (GMT) |
---|---|---|
committer | Georg Brandl <georg@python.org> | 2007-11-27 23:48:05 (GMT) |
commit | ceee0773d262bfe876e40da927b03279ed9f8419 (patch) | |
tree | e0a354553f537cab6479daa9845baabbb3bc4131 /Objects | |
parent | 45f9af34b334b483678225a943578d2e1ea540b1 (diff) | |
download | cpython-ceee0773d262bfe876e40da927b03279ed9f8419.zip cpython-ceee0773d262bfe876e40da927b03279ed9f8419.tar.gz cpython-ceee0773d262bfe876e40da927b03279ed9f8419.tar.bz2 |
#1496: revert str.translate() to the old version, and add
str.maketrans() to make a table in a more comfortable way.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/unicodeobject.c | 150 |
1 files changed, 104 insertions, 46 deletions
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 02b0c7a..205576f 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -7793,68 +7793,124 @@ unicode_swapcase(PyUnicodeObject *self) return fixup(self, fixswapcase); } -PyDoc_STRVAR(translate__doc__, -"S.translate(table) -> unicode\n\ +PyDoc_STRVAR(maketrans__doc__, +"str.maketrans(x[, y[, z]]) -> dict (static method)\n\ \n\ -Return a copy of the string S, where all characters have been mapped\n\ -through the given translation table, which must be a mapping of\n\ -Unicode ordinals to Unicode ordinals, Unicode strings or None.\n\ -Unmapped characters are left untouched. Characters mapped to None\n\ -are deleted."); +Return a translation table usable for str.translate().\n\ +If there is only one argument, it must be a dictionary mapping Unicode\n\ +ordinals (integers) or characters to Unicode ordinals, strings or None.\n\ +Character keys will then be converted to ordinals.\n\ +If there are two arguments, they must be strings of equal length, and\n\ +in the resulting dictionary, each character in x will be mapped to the\n\ +character at the same position in y. If there is a third argument, it\n\ +must be a string, whose characters will be mapped to None in the result."); static PyObject* -unicode_translate(PyUnicodeObject *self, PyObject *table) +unicode_maketrans(PyUnicodeObject *null, PyObject *args) { - PyObject *newtable = NULL; + PyObject *x, *y = NULL, *z = NULL; + PyObject *new = NULL, *key, *value; Py_ssize_t i = 0; - PyObject *key, *value, *result; - - if (!PyDict_Check(table)) { - PyErr_SetString(PyExc_TypeError, "translate argument must be a dict"); + int res; + + if (!PyArg_ParseTuple(args, "O|UU:maketrans", &x, &y, &z)) return NULL; - } - /* fixup the table -- allow size-1 string keys instead of only int keys */ - newtable = PyDict_Copy(table); - if (!newtable) return NULL; - while (PyDict_Next(table, &i, &key, &value)) { - if (PyUnicode_Check(key)) { - /* convert string keys to integer keys */ - PyObject *newkey; - int res; - if (PyUnicode_GET_SIZE(key) != 1) { - PyErr_SetString(PyExc_ValueError, "string items in translate " - "table must be 1 element long"); - goto err; - } - newkey = PyInt_FromLong(PyUnicode_AS_UNICODE(key)[0]); - if (!newkey) + new = PyDict_New(); + if (!new) + return NULL; + if (y != NULL) { + /* x must be a string too, of equal length */ + Py_ssize_t ylen = PyUnicode_GET_SIZE(y); + if (!PyUnicode_Check(x)) { + PyErr_SetString(PyExc_TypeError, "first maketrans argument must " + "be a string if there is a second argument"); + goto err; + } + if (PyUnicode_GET_SIZE(x) != ylen) { + PyErr_SetString(PyExc_ValueError, "the first two maketrans " + "arguments must have equal length"); + goto err; + } + /* create entries for translating chars in x to those in y */ + for (i = 0; i < PyUnicode_GET_SIZE(x); i++) { + key = PyInt_FromLong(PyUnicode_AS_UNICODE(x)[i]); + value = PyInt_FromLong(PyUnicode_AS_UNICODE(y)[i]); + if (!key || !value) goto err; - res = PyDict_SetItem(newtable, newkey, value); - Py_DECREF(newkey); + res = PyDict_SetItem(new, key, value); + Py_DECREF(key); + Py_DECREF(value); if (res < 0) goto err; - } else if (PyInt_Check(key)) { - /* just keep integer keys */ - if (PyDict_SetItem(newtable, key, value) < 0) - goto err; - } else { - PyErr_SetString(PyExc_TypeError, "items in translate table must be " - "strings or integers"); + } + /* create entries for deleting chars in z */ + if (z != NULL) { + for (i = 0; i < PyUnicode_GET_SIZE(z); i++) { + key = PyInt_FromLong(PyUnicode_AS_UNICODE(z)[i]); + if (!key) + goto err; + res = PyDict_SetItem(new, key, Py_None); + Py_DECREF(key); + if (res < 0) + goto err; + } + } + } else { + /* x must be a dict */ + if (!PyDict_Check(x)) { + PyErr_SetString(PyExc_TypeError, "if you give only one argument " + "to maketrans it must be a dict"); goto err; } + /* copy entries into the new dict, converting string keys to int keys */ + while (PyDict_Next(x, &i, &key, &value)) { + if (PyUnicode_Check(key)) { + /* convert string keys to integer keys */ + PyObject *newkey; + if (PyUnicode_GET_SIZE(key) != 1) { + PyErr_SetString(PyExc_ValueError, "string keys in translate " + "table must be of length 1"); + goto err; + } + newkey = PyInt_FromLong(PyUnicode_AS_UNICODE(key)[0]); + if (!newkey) + goto err; + res = PyDict_SetItem(new, newkey, value); + Py_DECREF(newkey); + if (res < 0) + goto err; + } else if (PyInt_Check(key)) { + /* just keep integer keys */ + if (PyDict_SetItem(new, key, value) < 0) + goto err; + } else { + PyErr_SetString(PyExc_TypeError, "keys in translate table must " + "be strings or integers"); + goto err; + } + } } - - result = PyUnicode_TranslateCharmap(self->str, - self->length, - newtable, - "ignore"); - Py_DECREF(newtable); - return result; + return new; err: - Py_DECREF(newtable); + Py_DECREF(new); return NULL; } +PyDoc_STRVAR(translate__doc__, +"S.translate(table) -> unicode\n\ +\n\ +Return a copy of the string S, where all characters have been mapped\n\ +through the given translation table, which must be a mapping of\n\ +Unicode ordinals to Unicode ordinals, Unicode strings or None.\n\ +Unmapped characters are left untouched. Characters mapped to None\n\ +are deleted."); + +static PyObject* +unicode_translate(PyUnicodeObject *self, PyObject *table) +{ + return PyUnicode_TranslateCharmap(self->str, self->length, table, "ignore"); +} + PyDoc_STRVAR(upper__doc__, "S.upper() -> unicode\n\ \n\ @@ -8076,6 +8132,8 @@ static PyMethodDef unicode_methods[] = { {"__format__", (PyCFunction) unicode_unicode__format__, METH_VARARGS, p_format__doc__}, {"_formatter_field_name_split", (PyCFunction) formatter_field_name_split, METH_NOARGS}, {"_formatter_parser", (PyCFunction) formatter_parser, METH_NOARGS}, + {"maketrans", (PyCFunction) unicode_maketrans, + METH_VARARGS | METH_STATIC, maketrans__doc__}, #if 0 {"capwords", (PyCFunction) unicode_capwords, METH_NOARGS, capwords__doc__}, #endif |