[glib: 1/2] string: Add find and replace function




commit c576a4cd825462be4998bcf67937bf24bee475ac
Author: Joshua Lee <lee son wai gmail com>
Date:   Tue Feb 9 10:50:16 2021 +0000

    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

 docs/reference/glib/glib-sections.txt |  1 +
 glib/gstring.c                        | 49 +++++++++++++++++++++++++++++++++++
 glib/gstring.h                        |  5 ++++
 glib/tests/string.c                   | 29 +++++++++++++++++++++
 4 files changed, 84 insertions(+)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index 2e219cf0c..1f27ec501 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -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
diff --git a/glib/gstring.c b/glib/gstring.c
index 85294258b..030d75316 100644
--- a/glib/gstring.c
+++ b/glib/gstring.c
@@ -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
diff --git a/glib/gstring.h b/glib/gstring.h
index e1b2e7fca..eec4c138f 100644
--- a/glib/gstring.h
+++ b/glib/gstring.h
@@ -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
diff --git a/glib/tests/string.c b/glib/tests/string.c
index cb5df4cec..819b192fb 100644
--- a/glib/tests/string.c
+++ b/glib/tests/string.c
@@ -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();
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]