summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/string_tests.py4
-rw-r--r--Lib/test/test_descr.py4
-rw-r--r--Lib/test/test_unicode.py10
-rw-r--r--Objects/stringobject.c57
-rw-r--r--Objects/unicodeobject.c34
5 files changed, 61 insertions, 48 deletions
diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py
index a071f20..f2d6853 100644
--- a/Lib/test/string_tests.py
+++ b/Lib/test/string_tests.py
@@ -202,6 +202,10 @@ def run_method_tests(test):
test('replace', 'one!two!three!', 'one@two@three@', '!', '@')
test('replace', 'one!two!three!', 'one!two!three!', 'x', '@')
test('replace', 'one!two!three!', 'one!two!three!', 'x', '@', 2)
+ test('replace', 'abc', '-a-b-c-', '', '-')
+ test('replace', 'abc', '-a-b-c', '', '-', 3)
+ test('replace', 'abc', 'abc', '', '-', 0)
+ test('replace', '', '', '', '')
# Next three for SF bug 422088: [OSF1 alpha] string.replace(); died with
# MemoryError due to empty result (platform malloc issue when requesting
# 0 bytes).
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index bedb9d2..0c7def1 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -2996,10 +2996,6 @@ def strops():
except ValueError: pass
else: raise TestFailed, "''.rindex('5') doesn't raise ValueError"
- try: ''.replace('', '')
- except ValueError: pass
- else: raise TestFailed, "''.replace('', '') doesn't raise ValueError"
-
try: '%(n)s' % None
except TypeError: pass
else: raise TestFailed, "'%(n)s' % None doesn't raise TypeError"
diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py
index 4efa39c..90147eb 100644
--- a/Lib/test/test_unicode.py
+++ b/Lib/test/test_unicode.py
@@ -210,12 +210,10 @@ test('replace', u'one!two!three!', u'one!two!three!', u'!', u'@', 0)
test('replace', u'one!two!three!', u'one@two@three@', u'!', u'@')
test('replace', u'one!two!three!', u'one!two!three!', u'x', u'@')
test('replace', u'one!two!three!', u'one!two!three!', u'x', u'@', 2)
-try:
- u"abc".replace(u"", u"x")
-except ValueError:
- pass
-else:
- raise TestFailed, "u.replace('', ...) should raise ValueError"
+test('replace', u'abc', u'-a-b-c-', u'', u'-')
+test('replace', u'abc', u'-a-b-c', u'', u'-', 3)
+test('replace', u'abc', u'abc', u'', u'-', 0)
+test('replace', u'', u'', u'', u'')
test('startswith', u'hello', True, u'he')
test('startswith', u'hello', True, u'hello')
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index 9f41317..0b79a06 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -2215,11 +2215,11 @@ mymemreplace(const char *str, int len, /* input string */
char *new_s;
int nfound, offset, new_len;
- if (len == 0 || pat_len > len)
+ if (len == 0 || (pat_len == 0 && sub_len == 0) || pat_len > len)
goto return_same;
/* find length of output string */
- nfound = mymemcnt(str, len, pat, pat_len);
+ nfound = (pat_len > 0) ? mymemcnt(str, len, pat, pat_len) : len + 1;
if (count < 0)
count = INT_MAX;
else if (nfound > count)
@@ -2242,25 +2242,38 @@ mymemreplace(const char *str, int len, /* input string */
return NULL;
out_s = new_s;
- for (; count > 0 && len > 0; --count) {
- /* find index of next instance of pattern */
- offset = mymemfind(str, len, pat, pat_len);
- if (offset == -1)
- break;
-
- /* copy non matching part of input string */
- memcpy(new_s, str, offset);
- str += offset + pat_len;
- len -= offset + pat_len;
-
- /* copy substitute into the output string */
- new_s += offset;
- memcpy(new_s, sub, sub_len);
- new_s += sub_len;
+ if (pat_len > 0) {
+ for (; nfound > 0; --nfound) {
+ /* find index of next instance of pattern */
+ offset = mymemfind(str, len, pat, pat_len);
+ if (offset == -1)
+ break;
+
+ /* copy non matching part of input string */
+ memcpy(new_s, str, offset);
+ str += offset + pat_len;
+ len -= offset + pat_len;
+
+ /* copy substitute into the output string */
+ new_s += offset;
+ memcpy(new_s, sub, sub_len);
+ new_s += sub_len;
+ }
+ /* copy any remaining values into output string */
+ if (len > 0)
+ memcpy(new_s, str, len);
+ }
+ else {
+ for (;;++str, --len) {
+ memcpy(new_s, sub, sub_len);
+ new_s += sub_len;
+ if (--nfound <= 0) {
+ memcpy(new_s, str, len);
+ break;
+ }
+ *new_s++ = *str;
+ }
}
- /* copy any remaining values into output string */
- if (len > 0)
- memcpy(new_s, str, len);
}
*out_len = new_len;
return out_s;
@@ -2317,10 +2330,6 @@ string_replace(PyStringObject *self, PyObject *args)
else if (PyObject_AsCharBuffer(replobj, &repl, &repl_len))
return NULL;
- if (sub_len <= 0) {
- PyErr_SetString(PyExc_ValueError, "empty pattern string");
- return NULL;
- }
new_s = mymemreplace(str,len,sub,sub_len,repl,repl_len,count,&out_len);
if (new_s == NULL) {
PyErr_NoMemory();
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index b264936..6dea94f 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -3494,11 +3494,6 @@ PyObject *replace(PyUnicodeObject *self,
{
PyUnicodeObject *u;
- if (str1->length == 0) {
- PyErr_SetString(PyExc_ValueError, "empty pattern string");
- return NULL;
- }
-
if (maxcount < 0)
maxcount = INT_MAX;
@@ -3549,19 +3544,30 @@ PyObject *replace(PyUnicodeObject *self,
if (u) {
i = 0;
p = u->str;
- while (i <= self->length - str1->length)
- if (Py_UNICODE_MATCH(self, i, str1)) {
- /* replace string segment */
+ if (str1->length > 0) {
+ while (i <= self->length - str1->length)
+ if (Py_UNICODE_MATCH(self, i, str1)) {
+ /* replace string segment */
+ Py_UNICODE_COPY(p, str2->str, str2->length);
+ p += str2->length;
+ i += str1->length;
+ if (--n <= 0) {
+ /* copy remaining part */
+ Py_UNICODE_COPY(p, self->str+i, self->length-i);
+ break;
+ }
+ } else
+ *p++ = self->str[i++];
+ } else {
+ while (n > 0) {
Py_UNICODE_COPY(p, str2->str, str2->length);
p += str2->length;
- i += str1->length;
- if (--n <= 0) {
- /* copy remaining part */
- Py_UNICODE_COPY(p, self->str+i, self->length-i);
+ if (--n <= 0)
break;
- }
- } else
*p++ = self->str[i++];
+ }
+ Py_UNICODE_COPY(p, self->str+i, self->length-i);
+ }
}
}
}