Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 101923b

Browse files
committed
Added replace() implementation by Perry Stoll (debugged and reformatted by me).
1 parent f643e3f commit 101923b

1 file changed

Lines changed: 167 additions & 1 deletion

File tree

Modules/stropmodule.c

Lines changed: 167 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,171 @@ strop_translate(self, args)
798798
}
799799

800800

801+
/* What follows is used for implementing replace(). Perry Stoll. */
802+
803+
/*
804+
mymemfind
805+
806+
strstr replacement for arbitrary blocks of memory.
807+
808+
Locates the first occurance in the memory pointed to by MEM of the
809+
contents of memory pointed to by PAT. Returns the index into MEM if
810+
found, or -1 if not found. If len of PAT is greater than length of
811+
MEM, the function returns -1.
812+
*/
813+
static int mymemfind(mem, len, pat, pat_len)
814+
char *mem;
815+
int len;
816+
char *pat;
817+
int pat_len;
818+
{
819+
register int ii;
820+
821+
/* pattern can not occur in the last pat_len-1 chars */
822+
len -= pat_len;
823+
824+
for (ii = 0; ii <= len; ii++) {
825+
if (mem[ii] == pat[0] &&
826+
(pat_len == 1 ||
827+
memcmp(&mem[ii+1], &pat[1], pat_len-1) == 0)) {
828+
return ii;
829+
}
830+
}
831+
return -1;
832+
}
833+
834+
/*
835+
mymemcnt
836+
837+
Return the number of distinct times PAT is found in MEM.
838+
meaning mem=1111 and pat==11 returns 2.
839+
mem=11111 and pat==11 also return 2.
840+
*/
841+
static int mymemcnt(mem, len, pat, pat_len)
842+
char *mem;
843+
int len;
844+
char *pat;
845+
int pat_len;
846+
{
847+
register int offset = 0;
848+
int nfound = 0;
849+
850+
while (len >= 0) {
851+
offset = mymemfind(mem, len, pat, pat_len);
852+
if (offset == -1)
853+
break;
854+
mem += offset + pat_len;
855+
len -= offset + pat_len;
856+
nfound++;
857+
}
858+
return nfound;
859+
}
860+
861+
/*
862+
mymemreplace
863+
864+
Return a string in which all occurences of PAT in memory STR are
865+
replaced with SUB.
866+
867+
If length of PAT is less than length of STR or there are no occurences
868+
of PAT in STR, then the original string is returned. Otherwise, a new
869+
string is allocated here and returned.
870+
871+
on return, out_len is:
872+
the length of output string, or
873+
-1 if the input string is returned, or
874+
unchanged if an error occurs (no memory).
875+
876+
return value is:
877+
the new string allocated locally, or
878+
NULL if an error occurred.
879+
*/
880+
static char *mymemreplace(str, len, pat, pat_len, sub, sub_len, out_len)
881+
char *str;
882+
int len; /* input string */
883+
char *pat;
884+
int pat_len; /* pattern string to find */
885+
char *sub;
886+
int sub_len; /* substitution string */
887+
int *out_len;
888+
889+
{
890+
char *out_s;
891+
char *new_s;
892+
int nfound, offset, new_len;
893+
894+
if (len == 0 || pat_len > len)
895+
goto return_same;
896+
897+
/* find length of output string */
898+
nfound = mymemcnt(str, len, pat, pat_len);
899+
if (nfound == 0)
900+
goto return_same;
901+
new_len = len + nfound*(sub_len - pat_len);
902+
903+
new_s = (char *)malloc(new_len);
904+
if (new_s == NULL) return NULL;
905+
906+
*out_len = new_len;
907+
out_s = new_s;
908+
909+
while (len > 0) {
910+
/* find index of next instance of pattern */
911+
offset = mymemfind(str, len, pat, pat_len);
912+
/* if not found, break out of loop */
913+
if (offset == -1) break;
914+
915+
/* copy non matching part of input string */
916+
memcpy(new_s, str, offset); /* copy part of str before pat */
917+
str += offset + pat_len; /* move str past pattern */
918+
len -= offset + pat_len; /* reduce length of str remaining */
919+
920+
/* copy substitute into the output string */
921+
new_s += offset; /* move new_s to dest for sub string */
922+
memcpy(new_s, sub, sub_len); /* copy substring into new_s */
923+
new_s += sub_len; /* offset new_s past sub string */
924+
}
925+
/* copy any remaining values into output string */
926+
if (len > 0)
927+
memcpy(new_s, str, len);
928+
return out_s;
929+
930+
return_same:
931+
*out_len = -1;
932+
return str;
933+
}
934+
935+
936+
static PyObject*
937+
strop_replace(self, args)
938+
PyObject *self; /* Not used */
939+
PyObject *args;
940+
{
941+
char *str, *pat,*sub,*new_s;
942+
int len,pat_len,sub_len,out_len;
943+
PyObject *new;
944+
945+
if (!PyArg_ParseTuple(args, "s#s#s#",
946+
&str, &len, &pat, &pat_len, &sub, &sub_len))
947+
return NULL;
948+
new_s = mymemreplace(str,len,pat,pat_len,sub,sub_len,&out_len);
949+
if (new_s == NULL) {
950+
PyErr_NoMemory();
951+
return NULL;
952+
}
953+
if (out_len == -1) {
954+
/* we're returning another reference to the input string */
955+
new = PyTuple_GetItem(args, 0);
956+
Py_XINCREF(new);
957+
}
958+
else {
959+
new = PyString_FromStringAndSize(new_s, out_len);
960+
free(new_s);
961+
}
962+
return new;
963+
}
964+
965+
801966
/* List of functions defined in the module */
802967

803968
static PyMethodDef
@@ -811,13 +976,14 @@ strop_methods[] = {
811976
{"joinfields", strop_joinfields, 1},
812977
{"lstrip", strop_lstrip},
813978
{"lower", strop_lower},
979+
{"maketrans", strop_maketrans, 1},
980+
{"replace", strop_replace, 1},
814981
{"rfind", strop_rfind, 1},
815982
{"rstrip", strop_rstrip},
816983
{"split", strop_splitfields, 1},
817984
{"splitfields", strop_splitfields, 1},
818985
{"strip", strop_strip},
819986
{"swapcase", strop_swapcase},
820-
{"maketrans", strop_maketrans, 1},
821987
{"translate", strop_translate, 1},
822988
{"upper", strop_upper},
823989
{NULL, NULL} /* sentinel */

0 commit comments

Comments
 (0)