glibcompat: "Backport" 'g_string_replace'

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>
This commit is contained in:
Peter Krempa 2024-08-09 14:14:47 +02:00
parent 66112fbabb
commit 63080f0582
3 changed files with 76 additions and 0 deletions

View 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

View 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;
}

View 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