Backport the implementation of 'g_string_replace' until we require at
least glib-2.68
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/glibcompat.c | 65 ++++++++++++++++++++++++++++++++++++++++
src/util/glibcompat.h | 10 +++++++
3 files changed, 76 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d15d6a6a9d..0accca442a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -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
diff --git a/src/util/glibcompat.c b/src/util/glibcompat.c
index d8912b323b..98dcfab389 100644
--- a/src/util/glibcompat.c
+++ b/src/util/glibcompat.c
@@ -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;
+}
diff --git a/src/util/glibcompat.h b/src/util/glibcompat.h
index 2542b4d5dc..3518023a41 100644
--- a/src/util/glibcompat.h
+++ b/src/util/glibcompat.h
@@ -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
--
2.45.2