diff -r 6fb1fb550319 Objects/unicodeobject.c --- a/Objects/unicodeobject.c Thu Oct 11 18:59:34 2012 -0700 +++ b/Objects/unicodeobject.c Sat Oct 13 20:19:47 2012 +0300 @@ -9881,6 +9881,80 @@ return 0; } +static void +replace_1char_inplace(PyObject *u, Py_ssize_t pos, Py_UCS4 u1, Py_UCS4 u2, Py_ssize_t maxcount) +{ + int kind = PyUnicode_KIND(u); + void *data = PyUnicode_DATA(u); + Py_ssize_t len = PyUnicode_GET_LENGTH(u); + if (kind == PyUnicode_1BYTE_KIND) { + Py_UCS1 *s = (Py_UCS1 *)data; + Py_UCS1 *end = s + len; + s += pos; + *s = u2; + while (--maxcount && ++s != end) { + if (*s != u1) { + int attempts = 10; + while (1) { + if (++s == end) + return; + if (*s == u1) + break; + if (!--attempts) { + s++; + s = memchr(s, u1, end - s); + if (s == NULL) + return; + break; + } + } + } + *s = u2; + } + } + else if (kind == PyUnicode_2BYTE_KIND) { + Py_UCS2 *s = (Py_UCS2 *)data; + Py_UCS2 *end = s + len; + s += pos; + *s = u2; + while (--maxcount && ++s != end) { + if (*s != u1) { + int attempts = 10; + while (1) { + if (++s == end) + return; + if (*s == u1) + break; + if (!--attempts) { + Py_ssize_t i; + s++; + i = findchar(s, PyUnicode_2BYTE_KIND, end - s, u1, 1); + if (i < 0) + return; + s += i; + break; + } + } + } + *s = u2; + } + } + else { + Py_UCS4 *s = (Py_UCS4 *)data; + Py_UCS4 *end = s + len; + s += pos; + while (1) { + *s = u2; + if (!--maxcount) + return; + do { + if (++s == end) + return; + } while (*s != u1); + } + } +} + static PyObject * replace(PyObject *self, PyObject *str1, PyObject *str2, Py_ssize_t maxcount) @@ -9897,7 +9971,7 @@ Py_ssize_t len1 = PyUnicode_GET_LENGTH(str1); Py_ssize_t len2 = PyUnicode_GET_LENGTH(str2); int mayshrink; - Py_UCS4 maxchar, maxchar_str2; + Py_UCS4 maxchar, maxchar_str1, maxchar_str2; if (maxcount < 0) maxcount = PY_SSIZE_T_MAX; @@ -9906,15 +9980,16 @@ if (str1 == str2) goto nothing; - if (skind < kind1) + + maxchar = PyUnicode_MAX_CHAR_VALUE(self); + maxchar_str1 = PyUnicode_MAX_CHAR_VALUE(str1); + if (maxchar < maxchar_str1) /* substring too wide to be present */ goto nothing; - - maxchar = PyUnicode_MAX_CHAR_VALUE(self); maxchar_str2 = PyUnicode_MAX_CHAR_VALUE(str2); /* Replacing str1 with str2 may cause a maxchar reduction in the result string. */ - mayshrink = (maxchar_str2 < maxchar); + mayshrink = (maxchar_str2 < maxchar_str1); maxchar = MAX_MAXCHAR(maxchar, maxchar_str2); if (len1 == len2) { @@ -9924,35 +9999,19 @@ if (len1 == 1) { /* replace characters */ Py_UCS4 u1, u2; - int rkind; - Py_ssize_t index, pos; - char *src; + Py_ssize_t pos; u1 = PyUnicode_READ_CHAR(str1, 0); - pos = findchar(sbuf, PyUnicode_KIND(self), slen, u1, 1); + pos = findchar(sbuf, skind, slen, u1, 1); if (pos < 0) goto nothing; u2 = PyUnicode_READ_CHAR(str2, 0); u = PyUnicode_New(slen, maxchar); if (!u) goto error; + _PyUnicode_FastCopyCharacters(u, 0, self, 0, slen); - rkind = PyUnicode_KIND(u); - - PyUnicode_WRITE(rkind, PyUnicode_DATA(u), pos, u2); - index = 0; - src = sbuf; - while (--maxcount) - { - pos++; - src += pos * PyUnicode_KIND(self); - slen -= pos; - index += pos; - pos = findchar(src, PyUnicode_KIND(self), slen, u1, 1); - if (pos < 0) - break; - PyUnicode_WRITE(rkind, PyUnicode_DATA(u), index + pos, u2); - } + replace_1char_inplace(u, pos, u1, u2, maxcount); } else { int rkind = skind;