diff options
author | Damien George <damien.p.george@gmail.com> | 2014-01-31 23:29:57 +0000 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2014-01-31 23:29:57 +0000 |
commit | 1aa1c511dd1550acbc9b65e46f6a7fc11273c02e (patch) | |
tree | 3db2802cb6df9549fdabe5da73ca7a3955d4813e /py | |
parent | 7ee8e468784480e516d199362ee93a84f42e2594 (diff) | |
parent | 480c15afb52adbb01a257eb4d533bac627eafeb2 (diff) | |
download | micropython-1aa1c511dd1550acbc9b65e46f6a7fc11273c02e.tar.gz micropython-1aa1c511dd1550acbc9b65e46f6a7fc11273c02e.zip |
Merge branch 'master' of github.com:xbe/micropython into xbe-master
Diffstat (limited to 'py')
-rw-r--r-- | py/objstr.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/py/objstr.c b/py/objstr.c index c30da00d71..fc9dfd200b 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -408,12 +408,76 @@ mp_obj_t str_format(uint n_args, const mp_obj_t *args) { return s; } +mp_obj_t str_replace(uint n_args, const mp_obj_t *args) { + assert(MP_OBJ_IS_STR(args[0])); + assert(MP_OBJ_IS_STR(args[1])); + assert(MP_OBJ_IS_STR(args[2])); + + int max_rep = 0; + if (n_args == 4) { + assert(MP_OBJ_IS_SMALL_INT(args[3])); + max_rep = MP_OBJ_SMALL_INT_VALUE(args[3]); + if (max_rep == 0) { + return(args[0]); + } + else if (max_rep < 0) { + max_rep = 0; + } + } + //if max_rep is still 0 by this point we will need to do all possible replacements + + GET_STR_DATA_LEN(args[0], str, str_len); + GET_STR_DATA_LEN(args[1], old, old_len); + GET_STR_DATA_LEN(args[2], new, new_len); + if (old_len > str_len) { + return(args[0]); + } + + size_t required_len = 0; + const byte *old_occurrence; + const byte *offset_ptr = str; + size_t offset_num = 0; + while((old_occurrence = find_subbytes(offset_ptr, str_len - offset_num, old, old_len)) != NULL){ + required_len += old_occurrence - offset_ptr; + required_len += new_len; + offset_ptr = old_occurrence + old_len; + offset_num = offset_ptr - str; + } + required_len += str_len - offset_num; + byte *data; + mp_obj_t replaced_str = mp_obj_str_builder_start(mp_obj_get_type(args[0]), required_len, &data); + + size_t replaced_str_index = 0; + int replacements_done = 0; + offset_ptr = str; + offset_num = 0; + while((old_occurrence = find_subbytes(offset_ptr, str_len - offset_num, old, old_len)) != NULL){ + //copy from just after end of last occurrence of to-be-replaced string to right before start of next occurrence + memcpy(data + replaced_str_index, offset_ptr, old_occurrence - offset_ptr); + replaced_str_index += old_occurrence - offset_ptr; + //copy the replacement string + memcpy(data + replaced_str_index, new, new_len); + replaced_str_index += new_len; + offset_ptr = old_occurrence + old_len; + offset_num = offset_ptr - str; + + replacements_done++; + if (max_rep != 0 && replacements_done == max_rep){ + break; + } + } + //copy from just after end of last occurrence of to-be-replaced string to end of old string + memcpy(data + replaced_str_index, offset_ptr, str_len - offset_num); + return mp_obj_str_builder_end(replaced_str); +} + static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find); static MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, str_split); static MP_DEFINE_CONST_FUN_OBJ_2(str_startswith_obj, str_startswith); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip); static MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, str_format); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj, 3, 4, str_replace); static const mp_method_t str_type_methods[] = { { "find", &str_find_obj }, @@ -422,6 +486,7 @@ static const mp_method_t str_type_methods[] = { { "startswith", &str_startswith_obj }, { "strip", &str_strip_obj }, { "format", &str_format_obj }, + { "replace", &str_replace_obj }, { NULL, NULL }, // end-of-list sentinel }; |