Add function string_replace_all[_str]
to replace all occurences of a string by another.
This commit is contained in:
1 parent
0b9e27fb7f
commit
55e7b3083a
3 files changed
+168
No files matched your search
@@ -5079,6 +5079,12 @@ the string 'str1' by the string 'str2' once.
|
|||||||
Returns the offset of the replacement or STRING_FAILURE if no replacement
|
Returns the offset of the replacement or STRING_FAILURE if no replacement
|
||||||
was performed.
|
was performed.
|
||||||
|
|
||||||
|
##### size\_t string\_replace\_all\_str (string\_t v, const char str1[], const char str2[])
|
||||||
|
##### size\_t string\_replace\_all (string\_t v, const string\_t str1, const string\_t str2)
|
||||||
|
|
||||||
|
Replace in the string 'v' all the occurences of
|
||||||
|
the string 'str1' by the string 'str2'.
|
||||||
|
|
||||||
##### void string\_replace\_at (string\_t v, size\_t pos, size\_t len, const char str2[])
|
##### void string\_replace\_at (string\_t v, size\_t pos, size\_t len, const char str2[])
|
||||||
|
|
||||||
Replace in the string 'v' the sub-string defined as starting from 'pos' and
|
Replace in the string 'v' the sub-string defined as starting from 'pos' and
|
||||||
|
|||||||
+137
@@ -772,6 +772,143 @@ string_replace_at (string_t v, size_t pos, size_t len, const char str2[])
|
|||||||
STRINGI_CONTRACT (v);
|
STRINGI_CONTRACT (v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Replace all occurences of str1 into str2 when strlen(str1) >= strlen(str2) */
|
||||||
|
static inline void
|
||||||
|
stringi_replace_all_str_1ge2 (string_t v, const char str1[], size_t str1len, const char str2[], size_t str2len)
|
||||||
|
{
|
||||||
|
STRINGI_CONTRACT (v);
|
||||||
|
M_ASSERT(str1len >= str2len);
|
||||||
|
|
||||||
|
/* str1len < str2len so the string doesn't need to be resized */
|
||||||
|
size_t vlen = string_size(v);
|
||||||
|
char *org = stringi_get_str(v);
|
||||||
|
char *src = org;
|
||||||
|
char *dst = org;
|
||||||
|
|
||||||
|
// Go through all the characters of the string
|
||||||
|
while (*src != 0) {
|
||||||
|
// Get a new occurence of str1 in the v string.
|
||||||
|
char *occ = strstr(src, str1);
|
||||||
|
if (occ == NULL) {
|
||||||
|
// No new occurence
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
M_ASSERT(occ >= src);
|
||||||
|
// Copy the data until the new occurence
|
||||||
|
if (src != dst) {
|
||||||
|
memmove(dst, src, (size_t) (occ - src));
|
||||||
|
}
|
||||||
|
dst += (occ - src);
|
||||||
|
src = occ;
|
||||||
|
// Copy the replaced string
|
||||||
|
memcpy(dst, str2, str2len);
|
||||||
|
dst += str2len;
|
||||||
|
// Advance src pointer
|
||||||
|
src = occ + str1len;
|
||||||
|
}
|
||||||
|
// Finish copying the string until the end
|
||||||
|
M_ASSERT (src <= org + vlen );
|
||||||
|
if (src != dst) {
|
||||||
|
memmove(dst, src, (size_t) (org + vlen + 1 - src) );
|
||||||
|
}
|
||||||
|
// Update string size
|
||||||
|
stringi_set_size(v, (size_t) (dst + vlen - src) );
|
||||||
|
STRINGI_CONTRACT (v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reverse strstr from the end of the string
|
||||||
|
org is the start of the string
|
||||||
|
src is the current character pointer (shall be initialized to the end of the string)
|
||||||
|
pattern / pattern_size: the pattern to search.
|
||||||
|
*/
|
||||||
|
static inline char *
|
||||||
|
stringi_strstr_r(char org[], char src[], const char pattern[], size_t pattern_size)
|
||||||
|
{
|
||||||
|
src -= pattern_size - 1;
|
||||||
|
while (org <= src) {
|
||||||
|
if (src[0] == pattern[0]
|
||||||
|
&& src[pattern_size-1] == pattern[pattern_size-1]
|
||||||
|
&& memcmp(src, pattern, pattern_size) == 0) {
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
src --;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Replace all occurences of str1 into str2 when strlen(str1) < strlen(str2) */
|
||||||
|
static inline void
|
||||||
|
stringi_replace_all_str_1lo2 (string_t v, const char str1[], size_t str1len, const char str2[], size_t str2len)
|
||||||
|
{
|
||||||
|
STRINGI_CONTRACT (v);
|
||||||
|
M_ASSERT(str1len < str2len);
|
||||||
|
|
||||||
|
/* str1len < str2len so the string may need to be resized
|
||||||
|
Worst case if when v is composed fully of str1 substrings.
|
||||||
|
Needed size : v.size / str1len * str2len
|
||||||
|
*/
|
||||||
|
size_t vlen = string_size(v);
|
||||||
|
size_t alloc = vlen / str1len * str2len;
|
||||||
|
stringi_fit2size(v, alloc);
|
||||||
|
|
||||||
|
char *org = stringi_get_str(v);
|
||||||
|
char *src = org + vlen - 1;
|
||||||
|
char *end = org + string_capacity(v);
|
||||||
|
char *dst = end;
|
||||||
|
|
||||||
|
// Go through all the characters of the string in reverse !
|
||||||
|
while (src >= org) {
|
||||||
|
char *occ = stringi_strstr_r(org, src, str1, str1len);
|
||||||
|
if (occ == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
M_ASSERT(occ + str1len - 1 <= src);
|
||||||
|
// Copy the data until the new occurence
|
||||||
|
dst -= (src - (occ + str1len - 1));
|
||||||
|
memmove(dst, occ+str1len, (size_t) (src - (occ + str1len - 1)));
|
||||||
|
// Copy the replaced string
|
||||||
|
dst -= str2len;
|
||||||
|
memcpy(dst, str2, str2len);
|
||||||
|
// Advance src pointer
|
||||||
|
src = occ - 1;
|
||||||
|
}
|
||||||
|
// Finish moving data back to their natural place
|
||||||
|
memmove(src + 1, dst, (size_t) (end - dst) );
|
||||||
|
// Update string size
|
||||||
|
vlen = (size_t) (src - org + end - dst + 1);
|
||||||
|
org[vlen] = 0;
|
||||||
|
stringi_set_size(v, vlen );
|
||||||
|
STRINGI_CONTRACT (v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
string_replace_all_str (string_t v, const char str1[], const char str2[])
|
||||||
|
{
|
||||||
|
size_t str1_l = strlen(str1);
|
||||||
|
size_t str2_l = strlen(str2);
|
||||||
|
assert(str1_l > 0);
|
||||||
|
assert(str2_l > 0);
|
||||||
|
if (str1_l >= str2_l) {
|
||||||
|
stringi_replace_all_str_1ge2(v, str1, str1_l, str2, str2_l );
|
||||||
|
} else {
|
||||||
|
stringi_replace_all_str_1lo2(v, str1, str1_l, str2, str2_l );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
string_replace_all (string_t v, const string_t str1, const string_t str2)
|
||||||
|
{
|
||||||
|
size_t str1_l = string_size(str1);
|
||||||
|
size_t str2_l = string_size(str2);
|
||||||
|
assert(str1_l > 0);
|
||||||
|
assert(str2_l > 0);
|
||||||
|
if (str1_l >= str2_l) {
|
||||||
|
stringi_replace_all_str_1ge2(v, string_get_cstr(str1), str1_l, string_get_cstr(str2), str2_l );
|
||||||
|
} else {
|
||||||
|
stringi_replace_all_str_1lo2(v, string_get_cstr(str1), str1_l, string_get_cstr(str2), str2_l );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Format in the string the given printf format */
|
/* Format in the string the given printf format */
|
||||||
static inline int
|
static inline int
|
||||||
string_printf (string_t v, const char format[], ...)
|
string_printf (string_t v, const char format[], ...)
|
||||||
|
|||||||
@@ -217,6 +217,31 @@ static void test0(void)
|
|||||||
assert (i != STRING_FAILURE);
|
assert (i != STRING_FAILURE);
|
||||||
assert (string_cmp_str (s1, "Hello, Juliette!") == 0);
|
assert (string_cmp_str (s1, "Hello, Juliette!") == 0);
|
||||||
|
|
||||||
|
string_set_str(s1, "Hello world 4 life world is real another world");
|
||||||
|
string_replace_all_str(s1, "world", "earth");
|
||||||
|
assert( string_equal_str_p(s1, "Hello earth 4 life earth is real another earth"));
|
||||||
|
|
||||||
|
string_set_str(s1, "Hello world 4 life world is real another world");
|
||||||
|
string_replace_all_str(s1, "world", "Wrld");
|
||||||
|
assert( string_equal_str_p(s1, "Hello Wrld 4 life Wrld is real another Wrld"));
|
||||||
|
|
||||||
|
string_set_str(s1, "world Hello world 4 life world is real another planet");
|
||||||
|
string_replace_all_str(s1, "world", "Wrld");
|
||||||
|
assert( string_equal_str_p(s1, "Wrld Hello Wrld 4 life Wrld is real another planet"));
|
||||||
|
|
||||||
|
string_set_str(s1, "Hello world 4 life world is real another world");
|
||||||
|
string_replace_all_str(s1, "world", "**WORLD**");
|
||||||
|
assert( string_equal_str_p(s1, "Hello **WORLD** 4 life **WORLD** is real another **WORLD**"));
|
||||||
|
|
||||||
|
string_set_str(s1, "world Hello world 4 life world is real another planet");
|
||||||
|
string_replace_all_str(s1, "world", "**WORLD**");
|
||||||
|
assert( string_equal_str_p(s1, "**WORLD** Hello **WORLD** 4 life **WORLD** is real another planet"));
|
||||||
|
|
||||||
|
string_set_str(s1, "HELLO");
|
||||||
|
string_set_str(s2, "WORLD");
|
||||||
|
string_replace_all(s1, s1, s2);
|
||||||
|
assert( string_equal_str_p(s1, "WORLD"));
|
||||||
|
|
||||||
string_printf (s1, "");
|
string_printf (s1, "");
|
||||||
assert (string_cmp_str (s1, "") == 0);
|
assert (string_cmp_str (s1, "") == 0);
|
||||||
assert (string_size (s1) == 0);
|
assert (string_size (s1) == 0);
|
||||||
|
|||||||
Reference in new issue
Block a user