@@ -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
803968static 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