string: Add find and replace function

This adds g_string_replace(), a function that replaces instances of one string
with another in a GString. It allows the caller to specify the maximum number
of replacements to perform, and returns the number of replacements performed
to the caller.

Fixes: #225
This commit is contained in:
Joshua Lee 2021-02-09 10:50:16 +00:00 committed by Philip Withnall
parent 203e078fdf
commit c576a4cd82
4 changed files with 84 additions and 0 deletions

View File

@ -2861,6 +2861,7 @@ g_string_insert_unichar
g_string_insert_len
g_string_overwrite
g_string_overwrite_len
g_string_replace
g_string_erase
g_string_truncate
g_string_set_size

View File

@ -953,6 +953,55 @@ g_string_erase (GString *string,
return string;
}
/**
* g_string_replace:
* @string: a #GString
* @find: the string to find in @string
* @replace: the string to insert in place of @find
* @limit: the maximum instances of @find to replace with @replace, or `0` for
* no limit
*
* Replaces the string @find with the string @replace in a #GString up to
* @limit times. If the number of instances of @find in the #GString is
* less than @limit, all instances are replaced. If the number of
* instances is `0`, all instances of @find are replaced.
*
* Returns: the number of find and replace operations performed.
*
* Since: 2.68
*/
guint
g_string_replace (GString *string,
const gchar *find,
const gchar *replace,
guint limit)
{
gsize f_len, r_len, pos;
gchar *cur, *next;
gint n = 0;
g_return_val_if_fail (string != NULL, 0);
g_return_val_if_fail (find != NULL, 0);
g_return_val_if_fail (replace != NULL, 0);
f_len = strlen (find);
r_len = strlen (replace);
cur = string->str;
while ((next = strstr (cur, find)) != NULL)
{
pos = next - string->str;
g_string_erase (string, pos, f_len);
g_string_insert (string, pos, replace);
cur = string->str + pos + r_len;
n++;
if (n == limit)
break;
}
return n;
}
/**
* g_string_ascii_down:
* @string: a GString

View File

@ -127,6 +127,11 @@ GLIB_AVAILABLE_IN_ALL
GString* g_string_erase (GString *string,
gssize pos,
gssize len);
GLIB_AVAILABLE_IN_2_68
guint g_string_replace (GString *string,
const gchar *find,
const gchar *replace,
guint limit);
GLIB_AVAILABLE_IN_ALL
GString* g_string_ascii_down (GString *string);
GLIB_AVAILABLE_IN_ALL

View File

@ -495,6 +495,34 @@ test_string_to_bytes (void)
g_bytes_unref (bytes);
}
static void
test_string_replace (void)
{
GString *s;
gint n;
s = g_string_new ("foo bar foo baz foo bar foobarbaz");
n = g_string_replace (s, "bar", "baz", 0);
g_assert_cmpstr ("foo baz foo baz foo baz foobazbaz", ==, s->str);
g_assert_cmpint (n, ==, 3);
n = g_string_replace (s, "baz", "bar", 3);
g_assert_cmpstr ("foo bar foo bar foo bar foobazbaz", ==, s->str);
g_assert_cmpint (n, ==, 3);
n = g_string_replace (s, "foobar", "bar", 1);
g_assert_cmpstr ("foo bar foo bar foo bar foobazbaz", ==, s->str);
g_assert_cmpint (n, ==, 0);
s = g_string_assign (s, "aaaaaaaa");
n = g_string_replace (s, "a", "abcdefghijkl", 0);
g_assert_cmpstr ("abcdefghijklabcdefghijklabcdefghijklabcdefghijklabcdefghijklabcdefghijklabcdefghijklabcdefghijkl",
==, s->str);
g_string_free (s, TRUE);
}
int
main (int argc,
char *argv[])
@ -519,6 +547,7 @@ main (int argc,
g_test_add_func ("/string/test-string-up-down", test_string_up_down);
g_test_add_func ("/string/test-string-set-size", test_string_set_size);
g_test_add_func ("/string/test-string-to-bytes", test_string_to_bytes);
g_test_add_func ("/string/test-string-replace", test_string_replace);
return g_test_run();
}