]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
glibcompat: "Backport" 'g_string_replace'
authorPeter Krempa <pkrempa@redhat.com>
Fri, 9 Aug 2024 12:14:47 +0000 (14:14 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Fri, 9 Aug 2024 14:34:32 +0000 (16:34 +0200)
Backport the implementation of 'g_string_replace' until we require at
least glib-2.68

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
src/libvirt_private.syms
src/util/glibcompat.c
src/util/glibcompat.h

index d15d6a6a9d83bc3ed0ce5df8af64b3c8459d97ae..0accca442ae02b5901f618f70be88b865233030f 100644 (file)
@@ -1864,6 +1864,7 @@ vir_g_fsync;
 vir_g_source_unref;
 vir_g_strdup_printf;
 vir_g_strdup_vprintf;
+vir_g_string_replace;
 
 
 # util/viracpi.c
index d8912b323b72d41737a68c51e76fdd1a39362879..98dcfab38958524ac0685333c02a3b93cef07a66 100644 (file)
@@ -155,3 +155,68 @@ void vir_g_source_unref(GSource *src, GMainContext *ctx)
 }
 
 #endif
+
+
+/**
+ * Adapted (to pass syntax check) from 'g_string_replace' from
+ * glib-2.81.1. Drop once minimum glib is bumped to 2.68.
+ *
+ * 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 @limit is `0`,
+ * all instances of @find are replaced.
+ *
+ * If @find is the empty string, since versions 2.69.1 and 2.68.4 the
+ * replacement will be inserted no more than once per possible position
+ * (beginning of string, end of string and between characters). This did
+ * not work correctly in earlier versions.
+ *
+ * Returns: the number of find and replace operations performed.
+ *
+ * Since: 2.68
+ */
+guint
+vir_g_string_replace(GString *string,
+                     const gchar *find,
+                     const gchar *replace,
+                     guint limit)
+{
+    gsize f_len, r_len, pos;
+    gchar *cur, *next;
+    guint 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++;
+        /* Only match the empty string once at any given position, to
+         * avoid infinite loops */
+        if (f_len == 0) {
+            if (cur[0] == '\0')
+                break;
+            else
+                cur++;
+        }
+        if (n == limit)
+            break;
+    }
+
+    return n;
+}
index 2542b4d5dc30b73169d9b39d2cff69a68e6d3eff..3518023a41a448bfabcc331f3d806ca2c8528472 100644 (file)
@@ -85,6 +85,16 @@ char *vir_g_strdup_vprintf(const char *msg, va_list args)
 
 void vir_g_source_unref(GSource *src, GMainContext *ctx);
 
+
+/* Drop once we require glib-2.68 at minimum */
+guint
+vir_g_string_replace(GString *string,
+                     const gchar *find,
+                     const gchar *replace,
+                     guint limit);
+#undef g_string_replace
+#define g_string_replace vir_g_string_replace
+
 #if !GLIB_CHECK_VERSION(2, 73, 2)
 # if (defined(__has_attribute) && __has_attribute(__noinline__)) || G_GNUC_CHECK_VERSION (2, 96)
 #  if defined (__cplusplus) && __cplusplus >= 201103L