[glib/wip/chergert/g_set_str] strfuncs: add g_set_str()




commit 96c9766843c1bbc13d8c5971a4df46b10a848215
Author: Christian Hergert <chergert redhat com>
Date:   Thu Sep 29 11:57:53 2022 -0700

    strfuncs: add g_set_str()
    
    This is like our other suite of g_set_*() based APIs to simplify and
    improve correctness of setters for fields, properties, and more.
    
    This implementation specifically handles setting string values that may
    point to an offset within the current string by copying before free.
    
    strcmp() is used directly (as opposed to g_strcmp0() due to it being in
    gtestutils.h as well as to increase the chance that the compiler will
    hoist the implementation.
    
    Fixes #2747

 docs/reference/glib/glib-sections.txt |  1 +
 glib/gstrfuncs.h                      | 47 +++++++++++++++++++++++++++++++++++
 glib/tests/strfuncs.c                 | 28 +++++++++++++++++++++
 3 files changed, 76 insertions(+)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index 251d0a09c9..e7099eb0ca 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -1811,6 +1811,7 @@ utimbuf
 <TITLE>String Utility Functions</TITLE>
 <FILE>string_utils</FILE>
 <INCLUDE>glib.h,glib/gprintf.h</INCLUDE>
+g_set_str
 g_strdup
 g_strndup
 g_strdupv
diff --git a/glib/gstrfuncs.h b/glib/gstrfuncs.h
index 37d2728d89..3c1dc45ecb 100644
--- a/glib/gstrfuncs.h
+++ b/glib/gstrfuncs.h
@@ -32,9 +32,11 @@
 #endif
 
 #include <stdarg.h>
+#include <string.h>
 #include <glib/gmacros.h>
 #include <glib/gtypes.h>
 #include <glib/gerror.h>
+#include <glib/gmem.h>
 
 G_BEGIN_DECLS
 
@@ -363,6 +365,51 @@ gboolean              g_ascii_string_to_unsigned   (const gchar  *str,
                                                     guint64      *out_num,
                                                     GError      **error);
 
+/**
+ * g_set_str: (skip)
+ * @str_pointer: (inout) (not optional) (nullable): a pointer to either a string or %NULL
+ * @new_str: (nullable): a string to assign to @str_pointer, or %NULL
+ *
+ * Updates a pointer to a string to a copy of @new_str. The previous string
+ * pointed to by @str_pointer will be freed with g_free().
+ *
+ * @str_pointer must not be %NULL, but can point to a %NULL value.
+ *
+ * One convenient usage of this function is in implementing property settings:
+ * |[
+ *   void
+ *   foo_set_bar (Foo        *foo,
+ *                const char *new_bar)
+ *   {
+ *     g_return_if_fail (IS_FOO (foo));
+ *
+ *     if (g_set_str (&foo->bar, new_bar))
+ *       g_object_notify (foo, "bar");
+ *   }
+ * ]|
+ *
+ * Returns: %TRUE if the value of @str_pointer changed, %FALSE otherwise
+ *
+ * Since: 2.76
+ */
+GLIB_AVAILABLE_STATIC_INLINE_IN_2_76
+static inline gboolean
+g_set_str (char       **str_pointer,
+           const char  *new_str)
+{
+  char *copy;
+
+  if (*str_pointer == new_str ||
+      (*str_pointer && new_str && strcmp (*str_pointer, new_str) == 0))
+    return FALSE;
+
+  copy = g_strdup (new_str);
+  g_free (*str_pointer);
+  *str_pointer = copy;
+
+  return TRUE;
+}
+
 G_END_DECLS
 
 #endif /* __G_STRFUNCS_H__ */
diff --git a/glib/tests/strfuncs.c b/glib/tests/strfuncs.c
index 082eec0743..0ae3f89c11 100644
--- a/glib/tests/strfuncs.c
+++ b/glib/tests/strfuncs.c
@@ -2546,6 +2546,33 @@ test_ascii_string_to_number_pathological (void)
   g_assert_cmpint (svalue, ==, G_MININT64);
 }
 
+static void
+test_set_str (void)
+{
+  char *str = NULL;
+
+  g_assert_false (g_set_str (&str, NULL));
+  g_assert_null (str);
+
+  g_assert_true (g_set_str (&str, ""));
+  g_assert_false (g_set_str (&str, ""));
+  g_assert_nonnull (str);
+  g_assert_true ((gpointer)str != (gpointer)"");
+  g_assert_cmpstr (str, ==, "");
+
+  g_assert_true (g_set_str (&str, NULL));
+  g_assert_null (str);
+
+  g_assert_true (g_set_str (&str, ""));
+  g_assert_true (g_set_str (&str, "test"));
+  g_assert_cmpstr (str, ==, "test");
+
+  g_assert_true (g_set_str (&str, &str[2]));
+  g_assert_cmpstr (str, ==, "st");
+
+  g_free (str);
+}
+
 int
 main (int   argc,
       char *argv[])
@@ -2563,6 +2590,7 @@ main (int   argc,
   g_test_add_func ("/strfuncs/has-suffix", test_has_suffix);
   g_test_add_func ("/strfuncs/memdup", test_memdup);
   g_test_add_func ("/strfuncs/memdup2", test_memdup2);
+  g_test_add_func ("/strfuncs/set_str", test_set_str);
   g_test_add_func ("/strfuncs/stpcpy", test_stpcpy);
   g_test_add_func ("/strfuncs/str_match_string", test_str_match_string);
   g_test_add_func ("/strfuncs/str_tokenize_and_fold", test_str_tokenize_and_fold);


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