Added replace() implementation by Perry Stoll (debugged and reformatted by me).
This commit is contained in:
parent
f643e3ff7e
commit
101923bba6
|
@ -798,6 +798,171 @@ strop_translate(self, args)
|
|||
}
|
||||
|
||||
|
||||
/* What follows is used for implementing replace(). Perry Stoll. */
|
||||
|
||||
/*
|
||||
mymemfind
|
||||
|
||||
strstr replacement for arbitrary blocks of memory.
|
||||
|
||||
Locates the first occurance in the memory pointed to by MEM of the
|
||||
contents of memory pointed to by PAT. Returns the index into MEM if
|
||||
found, or -1 if not found. If len of PAT is greater than length of
|
||||
MEM, the function returns -1.
|
||||
*/
|
||||
static int mymemfind(mem, len, pat, pat_len)
|
||||
char *mem;
|
||||
int len;
|
||||
char *pat;
|
||||
int pat_len;
|
||||
{
|
||||
register int ii;
|
||||
|
||||
/* pattern can not occur in the last pat_len-1 chars */
|
||||
len -= pat_len;
|
||||
|
||||
for (ii = 0; ii <= len; ii++) {
|
||||
if (mem[ii] == pat[0] &&
|
||||
(pat_len == 1 ||
|
||||
memcmp(&mem[ii+1], &pat[1], pat_len-1) == 0)) {
|
||||
return ii;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
mymemcnt
|
||||
|
||||
Return the number of distinct times PAT is found in MEM.
|
||||
meaning mem=1111 and pat==11 returns 2.
|
||||
mem=11111 and pat==11 also return 2.
|
||||
*/
|
||||
static int mymemcnt(mem, len, pat, pat_len)
|
||||
char *mem;
|
||||
int len;
|
||||
char *pat;
|
||||
int pat_len;
|
||||
{
|
||||
register int offset = 0;
|
||||
int nfound = 0;
|
||||
|
||||
while (len >= 0) {
|
||||
offset = mymemfind(mem, len, pat, pat_len);
|
||||
if (offset == -1)
|
||||
break;
|
||||
mem += offset + pat_len;
|
||||
len -= offset + pat_len;
|
||||
nfound++;
|
||||
}
|
||||
return nfound;
|
||||
}
|
||||
|
||||
/*
|
||||
mymemreplace
|
||||
|
||||
Return a string in which all occurences of PAT in memory STR are
|
||||
replaced with SUB.
|
||||
|
||||
If length of PAT is less than length of STR or there are no occurences
|
||||
of PAT in STR, then the original string is returned. Otherwise, a new
|
||||
string is allocated here and returned.
|
||||
|
||||
on return, out_len is:
|
||||
the length of output string, or
|
||||
-1 if the input string is returned, or
|
||||
unchanged if an error occurs (no memory).
|
||||
|
||||
return value is:
|
||||
the new string allocated locally, or
|
||||
NULL if an error occurred.
|
||||
*/
|
||||
static char *mymemreplace(str, len, pat, pat_len, sub, sub_len, out_len)
|
||||
char *str;
|
||||
int len; /* input string */
|
||||
char *pat;
|
||||
int pat_len; /* pattern string to find */
|
||||
char *sub;
|
||||
int sub_len; /* substitution string */
|
||||
int *out_len;
|
||||
|
||||
{
|
||||
char *out_s;
|
||||
char *new_s;
|
||||
int nfound, offset, new_len;
|
||||
|
||||
if (len == 0 || pat_len > len)
|
||||
goto return_same;
|
||||
|
||||
/* find length of output string */
|
||||
nfound = mymemcnt(str, len, pat, pat_len);
|
||||
if (nfound == 0)
|
||||
goto return_same;
|
||||
new_len = len + nfound*(sub_len - pat_len);
|
||||
|
||||
new_s = (char *)malloc(new_len);
|
||||
if (new_s == NULL) return NULL;
|
||||
|
||||
*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 */
|
||||
}
|
||||
/* copy any remaining values into output string */
|
||||
if (len > 0)
|
||||
memcpy(new_s, str, len);
|
||||
return out_s;
|
||||
|
||||
return_same:
|
||||
*out_len = -1;
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
static PyObject*
|
||||
strop_replace(self, args)
|
||||
PyObject *self; /* Not used */
|
||||
PyObject *args;
|
||||
{
|
||||
char *str, *pat,*sub,*new_s;
|
||||
int len,pat_len,sub_len,out_len;
|
||||
PyObject *new;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s#s#s#",
|
||||
&str, &len, &pat, &pat_len, &sub, &sub_len))
|
||||
return NULL;
|
||||
new_s = mymemreplace(str,len,pat,pat_len,sub,sub_len,&out_len);
|
||||
if (new_s == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
if (out_len == -1) {
|
||||
/* we're returning another reference to the input string */
|
||||
new = PyTuple_GetItem(args, 0);
|
||||
Py_XINCREF(new);
|
||||
}
|
||||
else {
|
||||
new = PyString_FromStringAndSize(new_s, out_len);
|
||||
free(new_s);
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
/* List of functions defined in the module */
|
||||
|
||||
static PyMethodDef
|
||||
|
@ -811,13 +976,14 @@ strop_methods[] = {
|
|||
{"joinfields", strop_joinfields, 1},
|
||||
{"lstrip", strop_lstrip},
|
||||
{"lower", strop_lower},
|
||||
{"maketrans", strop_maketrans, 1},
|
||||
{"replace", strop_replace, 1},
|
||||
{"rfind", strop_rfind, 1},
|
||||
{"rstrip", strop_rstrip},
|
||||
{"split", strop_splitfields, 1},
|
||||
{"splitfields", strop_splitfields, 1},
|
||||
{"strip", strop_strip},
|
||||
{"swapcase", strop_swapcase},
|
||||
{"maketrans", strop_maketrans, 1},
|
||||
{"translate", strop_translate, 1},
|
||||
{"upper", strop_upper},
|
||||
{NULL, NULL} /* sentinel */
|
||||
|
|
Loading…
Reference in New Issue