Commit 3913a716 authored by Guido van Rossum's avatar Guido van Rossum

Code by Inyeol Lee, submitted to SF bug 595350, to implement

the string/unicode method .replace() with a zero-lengt first argument.
Inyeol contributed tests for this too.
parent 771287b6
...@@ -202,6 +202,10 @@ def run_method_tests(test): ...@@ -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@', '!', '@')
test('replace', 'one!two!three!', 'one!two!three!', 'x', '@') test('replace', 'one!two!three!', 'one!two!three!', 'x', '@')
test('replace', 'one!two!three!', 'one!two!three!', 'x', '@', 2) 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 # Next three for SF bug 422088: [OSF1 alpha] string.replace(); died with
# MemoryError due to empty result (platform malloc issue when requesting # MemoryError due to empty result (platform malloc issue when requesting
# 0 bytes). # 0 bytes).
......
...@@ -2996,10 +2996,6 @@ def strops(): ...@@ -2996,10 +2996,6 @@ def strops():
except ValueError: pass except ValueError: pass
else: raise TestFailed, "''.rindex('5') doesn't raise ValueError" 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 try: '%(n)s' % None
except TypeError: pass except TypeError: pass
else: raise TestFailed, "'%(n)s' % None doesn't raise TypeError" else: raise TestFailed, "'%(n)s' % None doesn't raise TypeError"
......
...@@ -210,12 +210,10 @@ test('replace', u'one!two!three!', u'one!two!three!', u'!', u'@', 0) ...@@ -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'!', 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'@')
test('replace', u'one!two!three!', u'one!two!three!', u'x', u'@', 2) test('replace', u'one!two!three!', u'one!two!three!', u'x', u'@', 2)
try: test('replace', u'abc', u'-a-b-c-', u'', u'-')
u"abc".replace(u"", u"x") test('replace', u'abc', u'-a-b-c', u'', u'-', 3)
except ValueError: test('replace', u'abc', u'abc', u'', u'-', 0)
pass test('replace', u'', u'', u'', u'')
else:
raise TestFailed, "u.replace('', ...) should raise ValueError"
test('startswith', u'hello', True, u'he') test('startswith', u'hello', True, u'he')
test('startswith', u'hello', True, u'hello') test('startswith', u'hello', True, u'hello')
......
...@@ -2215,11 +2215,11 @@ mymemreplace(const char *str, int len, /* input string */ ...@@ -2215,11 +2215,11 @@ mymemreplace(const char *str, int len, /* input string */
char *new_s; char *new_s;
int nfound, offset, new_len; 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; goto return_same;
/* find length of output string */ /* 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) if (count < 0)
count = INT_MAX; count = INT_MAX;
else if (nfound > count) else if (nfound > count)
...@@ -2242,25 +2242,38 @@ mymemreplace(const char *str, int len, /* input string */ ...@@ -2242,25 +2242,38 @@ mymemreplace(const char *str, int len, /* input string */
return NULL; return NULL;
out_s = new_s; out_s = new_s;
for (; count > 0 && len > 0; --count) { if (pat_len > 0) {
/* find index of next instance of pattern */ for (; nfound > 0; --nfound) {
offset = mymemfind(str, len, pat, pat_len); /* find index of next instance of pattern */
if (offset == -1) offset = mymemfind(str, len, pat, pat_len);
break; if (offset == -1)
break;
/* copy non matching part of input string */
memcpy(new_s, str, offset); /* copy non matching part of input string */
str += offset + pat_len; memcpy(new_s, str, offset);
len -= offset + pat_len; str += offset + pat_len;
len -= offset + pat_len;
/* copy substitute into the output string */
new_s += offset; /* copy substitute into the output string */
memcpy(new_s, sub, sub_len); new_s += offset;
new_s += sub_len; 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; *out_len = new_len;
return out_s; return out_s;
...@@ -2317,10 +2330,6 @@ string_replace(PyStringObject *self, PyObject *args) ...@@ -2317,10 +2330,6 @@ string_replace(PyStringObject *self, PyObject *args)
else if (PyObject_AsCharBuffer(replobj, &repl, &repl_len)) else if (PyObject_AsCharBuffer(replobj, &repl, &repl_len))
return NULL; 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); new_s = mymemreplace(str,len,sub,sub_len,repl,repl_len,count,&out_len);
if (new_s == NULL) { if (new_s == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
......
...@@ -3494,11 +3494,6 @@ PyObject *replace(PyUnicodeObject *self, ...@@ -3494,11 +3494,6 @@ PyObject *replace(PyUnicodeObject *self,
{ {
PyUnicodeObject *u; PyUnicodeObject *u;
if (str1->length == 0) {
PyErr_SetString(PyExc_ValueError, "empty pattern string");
return NULL;
}
if (maxcount < 0) if (maxcount < 0)
maxcount = INT_MAX; maxcount = INT_MAX;
...@@ -3549,19 +3544,30 @@ PyObject *replace(PyUnicodeObject *self, ...@@ -3549,19 +3544,30 @@ PyObject *replace(PyUnicodeObject *self,
if (u) { if (u) {
i = 0; i = 0;
p = u->str; p = u->str;
while (i <= self->length - str1->length) if (str1->length > 0) {
if (Py_UNICODE_MATCH(self, i, str1)) { while (i <= self->length - str1->length)
/* replace string segment */ 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); Py_UNICODE_COPY(p, str2->str, str2->length);
p += str2->length; p += str2->length;
i += str1->length; if (--n <= 0)
if (--n <= 0) {
/* copy remaining part */
Py_UNICODE_COPY(p, self->str+i, self->length-i);
break; break;
}
} else
*p++ = self->str[i++]; *p++ = self->str[i++];
}
Py_UNICODE_COPY(p, self->str+i, self->length-i);
}
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment