@@ -1106,22 +1106,31 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, uint n_args, const mp_obj_t
11061106
11071107STATIC mp_obj_t str_replace (uint n_args , const mp_obj_t * args ) {
11081108 assert (MP_OBJ_IS_STR (args [0 ]));
1109- assert (MP_OBJ_IS_STR (args [1 ]));
1110- assert (MP_OBJ_IS_STR (args [2 ]));
11111109
1112- machine_int_t max_rep = 0 ;
1110+ machine_int_t max_rep = -1 ;
11131111 if (n_args == 4 ) {
1114- assert (MP_OBJ_IS_SMALL_INT (args [3 ]));
1115- max_rep = MP_OBJ_SMALL_INT_VALUE (args [3 ]);
1112+ max_rep = mp_obj_get_int (args [3 ]);
11161113 if (max_rep == 0 ) {
11171114 return args [0 ];
11181115 } else if (max_rep < 0 ) {
1119- max_rep = 0 ;
1116+ max_rep = -1 ;
11201117 }
11211118 }
11221119
11231120 // if max_rep is still 0 by this point we will need to do all possible replacements
11241121
1122+ // check argument types
1123+
1124+ if (!MP_OBJ_IS_STR (args [1 ])) {
1125+ bad_implicit_conversion (args [1 ]);
1126+ }
1127+
1128+ if (!MP_OBJ_IS_STR (args [2 ])) {
1129+ bad_implicit_conversion (args [2 ]);
1130+ }
1131+
1132+ // extract string data
1133+
11251134 GET_STR_DATA_LEN (args [0 ], str , str_len );
11261135 GET_STR_DATA_LEN (args [1 ], old , old_len );
11271136 GET_STR_DATA_LEN (args [2 ], new , new_len );
@@ -1143,8 +1152,20 @@ STATIC mp_obj_t str_replace(uint n_args, const mp_obj_t *args) {
11431152 machine_uint_t num_replacements_done = 0 ;
11441153 const byte * old_occurrence ;
11451154 const byte * offset_ptr = str ;
1146- machine_uint_t offset_num = 0 ;
1147- while ((old_occurrence = find_subbytes (offset_ptr , str_len - offset_num , old , old_len , 1 )) != NULL ) {
1155+ machine_uint_t str_len_remain = str_len ;
1156+ if (old_len == 0 ) {
1157+ // if old_str is empty, copy new_str to start of replaced string
1158+ // copy the replacement string
1159+ if (data != NULL ) {
1160+ memcpy (data , new , new_len );
1161+ }
1162+ replaced_str_index += new_len ;
1163+ num_replacements_done ++ ;
1164+ }
1165+ while (num_replacements_done != max_rep && str_len_remain > 0 && (old_occurrence = find_subbytes (offset_ptr , str_len_remain , old , old_len , 1 )) != NULL ) {
1166+ if (old_len == 0 ) {
1167+ old_occurrence += 1 ;
1168+ }
11481169 // copy from just after end of last occurrence of to-be-replaced string to right before start of next occurrence
11491170 if (data != NULL ) {
11501171 memcpy (data + replaced_str_index , offset_ptr , old_occurrence - offset_ptr );
@@ -1156,19 +1177,15 @@ STATIC mp_obj_t str_replace(uint n_args, const mp_obj_t *args) {
11561177 }
11571178 replaced_str_index += new_len ;
11581179 offset_ptr = old_occurrence + old_len ;
1159- offset_num = offset_ptr - str ;
1160-
1180+ str_len_remain = str + str_len - offset_ptr ;
11611181 num_replacements_done ++ ;
1162- if (max_rep != 0 && num_replacements_done == max_rep ){
1163- break ;
1164- }
11651182 }
11661183
11671184 // copy from just after end of last occurrence of to-be-replaced string to end of old string
11681185 if (data != NULL ) {
1169- memcpy (data + replaced_str_index , offset_ptr , str_len - offset_num );
1186+ memcpy (data + replaced_str_index , offset_ptr , str_len_remain );
11701187 }
1171- replaced_str_index += str_len - offset_num ;
1188+ replaced_str_index += str_len_remain ;
11721189
11731190 if (data == NULL ) {
11741191 // first pass
@@ -1178,6 +1195,7 @@ STATIC mp_obj_t str_replace(uint n_args, const mp_obj_t *args) {
11781195 } else {
11791196 // substr found, allocate new string
11801197 replaced_str = mp_obj_str_builder_start (mp_obj_get_type (args [0 ]), replaced_str_index , & data );
1198+ assert (data != NULL );
11811199 }
11821200 } else {
11831201 // second pass, we are done
0 commit comments