test('replace', 'one!two!three!', 'one@two@three!', '!', '@', 2)
test('replace', 'one!two!three!', 'one@two@three@', '!', '@', 3)
test('replace', 'one!two!three!', 'one@two@three@', '!', '@', 4)
+# CAUTION: a replace count of 0 means infinity only to strop, not to the
+# string .replace() method or to the string.replace() function.
test('replace', 'one!two!three!', 'one@two@three@', '!', '@', 0)
test('replace', 'one!two!three!', 'one@two@three@', '!', '@')
test('replace', 'one!two!three!', 'one!two!three!', 'x', '@')
found, or -1 if not found. If len of PAT is greater than length of
MEM, the function returns -1.
*/
-static int mymemfind(char *mem, int len, char *pat, int pat_len)
+static int
+mymemfind(const char *mem, int len, const char *pat, int pat_len)
{
register int ii;
meaning mem=1111 and pat==11 returns 2.
mem=11111 and pat==11 also return 2.
*/
-static int mymemcnt(char *mem, int len, char *pat, int pat_len)
+static int
+mymemcnt(const char *mem, int len, const char *pat, int pat_len)
{
register int offset = 0;
int nfound = 0;
the new string allocated locally, or
NULL if an error occurred.
*/
-static char *mymemreplace(char *str, int len, char *pat, int pat_len, char *sub, int sub_len, int count, int *out_len)
+static char *
+mymemreplace(const char *str, int len, /* input string */
+ const char *pat, int pat_len, /* pattern string to find */
+ const char *sub, int sub_len, /* substitution string */
+ int count, /* number of replacements */
+ int *out_len)
{
char *out_s;
char *new_s;
/* find length of output string */
nfound = mymemcnt(str, len, pat, pat_len);
- if (count > 0)
- nfound = nfound > count ? count : nfound;
+ if (count < 0)
+ count = INT_MAX;
+ else if (nfound > count)
+ nfound = count;
if (nfound == 0)
goto return_same;
new_len = len + nfound*(sub_len - pat_len);
if (new_len == 0) {
- out_s = "";
+ /* Have to allocate something for the caller to free(). */
+ out_s = (char *)PyMem_MALLOC(1);
+ if (out_s == NULL)
+ return NULL;
+ out_s[0] = '\0';
}
else {
assert(new_len > 0);
return NULL;
out_s = new_s;
- while (len > 0) {
+ for (; count > 0 && len > 0; --count) {
/* find index of next instance of pattern */
offset = mymemfind(str, len, pat, pat_len);
if (offset == -1)
new_s += offset;
memcpy(new_s, sub, sub_len);
new_s += sub_len;
-
- /* note count==0 is effectively infinity */
- if (--count == 0)
- break;
}
/* copy any remaining values into output string */
if (len > 0)
return_same:
*out_len = -1;
- return str;
+ return (char *)str; /* cast away const */
}
{
char *str, *pat,*sub,*new_s;
int len,pat_len,sub_len,out_len;
- int count = 0;
+ int count = -1;
PyObject *new;
if (!PyArg_ParseTuple(args, "t#t#t#|i:replace",
PyErr_SetString(PyExc_ValueError, "empty pattern string");
return NULL;
}
+ /* CAUTION: strop treats a replace count of 0 as infinity, unlke
+ * current (2.1) string.py and string methods. Preserve this for
+ * ... well, hard to say for what <wink>.
+ */
+ if (count == 0)
+ count = -1;
new_s = mymemreplace(str,len,pat,pat_len,sub,sub_len,count,&out_len);
if (new_s == NULL) {
PyErr_NoMemory();
const char *pat, int pat_len, /* pattern string to find */
const char *sub, int sub_len, /* substitution string */
int count, /* number of replacements */
- int *out_len)
+ int *out_len)
{
char *out_s;
char *new_s;
nfound = count;
if (nfound == 0)
goto return_same;
+
new_len = len + nfound*(sub_len - pat_len);
+ if (new_len == 0) {
+ /* Have to allocate something for the caller to free(). */
+ out_s = (char *)PyMem_MALLOC(1);
+ if (out_s == NULL)
+ return NULL;
+ out_s[0] = '\0';
+ }
+ else {
+ assert(new_len > 0);
+ new_s = (char *)PyMem_MALLOC(new_len);
+ if (new_s == NULL)
+ return NULL;
+ out_s = new_s;
- new_s = (char *)PyMem_MALLOC(new_len);
- if (new_s == NULL) return NULL;
+ 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;
+ }
+ /* copy any remaining values into output string */
+ if (len > 0)
+ memcpy(new_s, str, len);
+ }
*out_len = new_len;
- out_s = new_s;
-
- while (len > 0) {
- /* find index of next instance of pattern */
- offset = mymemfind(str, len, pat, pat_len);
- /* if not found, break out of loop */
- if (offset == -1) break;
-
- /* copy non matching part of input string */
- memcpy(new_s, str, offset); /* copy part of str before pat */
- str += offset + pat_len; /* move str past pattern */
- len -= offset + pat_len; /* reduce length of str remaining */
-
- /* copy substitute into the output string */
- new_s += offset; /* move new_s to dest for sub string */
- memcpy(new_s, sub, sub_len); /* copy substring into new_s */
- new_s += sub_len; /* offset new_s past sub string */
-
- /* break when we've done count replacements */
- if (--count == 0) break;
- }
- /* copy any remaining values into output string */
- if (len > 0)
- memcpy(new_s, str, len);
return out_s;
return_same:
*out_len = -1;
- return (char*)str; /* have to cast away constness here */
+ return (char *)str; /* cast away const */
}