[glib/gsettings] improve g_variant_{new,get}_va API



commit a176e3cab09a6774bc870bbcc02385e5b9c90bcd
Author: Ryan Lortie <desrt desrt ca>
Date:   Thu Aug 27 17:33:32 2009 -0400

    improve g_variant_{new,get}_va API

 glib/gvariant-parser.c |   12 +++---
 glib/gvariant-valist.c |  101 +++++++++++++++++++++++++++---------------------
 glib/gvariant.h        |    6 ++-
 3 files changed, 67 insertions(+), 52 deletions(-)
---
diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c
index ebd9cf5..1d657ea 100644
--- a/glib/gvariant-parser.c
+++ b/glib/gvariant-parser.c
@@ -1769,24 +1769,24 @@ positional_parse (TokenStream *stream,
     positional_free
   };
   Positional *positional;
-  const gchar *format;
+  const gchar *endptr;
   gchar *token;
 
   token = token_stream_get (stream);
   g_assert (token[0] == '%');
 
-  format = token + 1;
-
   positional = g_slice_new (Positional);
   positional->ast.class = &positional_class;
-  positional->value = g_variant_new_va (NULL, &format, app);
+  positional->value = g_variant_new_va (NULL, token + 1, &endptr, app);
 
-  if (*format)
+  if (*endptr || positional->value == NULL)
     {
       set_error (&stream->error, stream->stream, stream->stream,
                  "invalid GVariant format string");
 
-      g_variant_unref (g_variant_ref_sink (positional->value));
+      if (positional->value != NULL)
+        g_variant_unref (g_variant_ref_sink (positional->value));
+
       g_slice_free (Positional, positional);
       g_free (token);
 
diff --git a/glib/gvariant-valist.c b/glib/gvariant-valist.c
index 641cebe..60fab67 100644
--- a/glib/gvariant-valist.c
+++ b/glib/gvariant-valist.c
@@ -1048,8 +1048,7 @@ g_variant_new (const gchar *format_string,
   g_assert (strchr ("*? r", format_string[0]) == NULL);
 
   va_start (ap, format_string);
-  value = g_variant_new_va (NULL, &format_string, &ap);
-  g_assert (*format_string == '\0');
+  value = g_variant_new_va (NULL, format_string, NULL, &ap);
   va_end (ap);
 
   return value;
@@ -1058,7 +1057,8 @@ g_variant_new (const gchar *format_string,
 /**
  * g_variant_new_va:
  * @must_be_null: %NULL (for future expansion)
- * @format_string: a pointer to a format string
+ * @format_string: a string that is prefixed with a format string
+ * @endptr: location to store the end pointer, or %NULL
  * @app: a pointer to a #va_list
  * @returns: a new, usually floating, #GVariant
  *
@@ -1068,25 +1068,25 @@ g_variant_new (const gchar *format_string,
  *
  * The API is more general than g_variant_new() to allow a wider range
  * of possible uses.
- *
- * @format_string must still point to a valid format string, but it
- * need not be nul-terminated.  Instead, @format_string is updated to
- * point to the first character past the end of the given format
- * string.
+
+ * @format_string must still point to a valid format string, but it only
+ * need to be nul-terminated if @endptr is %NULL.  If @endptr is
+ * non-%NULL then it is updated to point to the first character past the
+ * end of the format string.
  *
  * @app is a pointer to a #va_list.  The arguments, according to
- * @format_string, are collected from this #va_list and the list is
- * left pointing to the argument following the last.
+ * @format_string, are collected from this #va_list and the list is left
+ * pointing to the argument following the last.
  *
  * These two generalisations allow mixing of multiple calls to
  * g_variant_new_va() and g_variant_get_va() within a single actual
  * varargs call by the user.
  *
- * The return value will be floating if it was a newly created
- * GVariant instance (for example, if the format string was "(ii)").
- * In the case that the format_string was '*', '?', 'r', or a format
- * starting with '@' then the collected #GVariant pointer will be
- * returned unmodified, without adding any additional references.
+ * The return value will be floating if it was a newly created GVariant
+ * instance (for example, if the format string was "(ii)").  In the case
+ * that the format_string was '*', '?', 'r', or a format starting with
+ * '@' then the collected #GVariant pointer will be returned unmodified,
+ * without adding any additional references.
  *
  * In order to behave correctly in all cases it is necessary for the
  * calling function to g_variant_ref_sink() the return result before
@@ -1097,14 +1097,23 @@ g_variant_new (const gchar *format_string,
  **/
 GVariant *
 g_variant_new_va (gpointer      must_be_null,
-                  const gchar **format_string,
+                  const gchar  *format_string,
+                  const gchar **endptr,
                   va_list      *app)
 {
   GVariant *value;
 
-  g_assert (must_be_null == NULL);
+  g_return_val_if_fail (format_string != NULL, NULL);
+  g_return_val_if_fail (must_be_null == NULL, NULL);
+  g_return_val_if_fail (app != NULL, NULL);
+
+  value = g_variant_valist_new (&format_string, app);
+
+  if (endptr != NULL)
+    *endptr = format_string;
+  else
+    g_assert (*format_string == '\0');
 
-  value = g_variant_valist_new (format_string, app);
   g_variant_flatten (value);
 
   return value;
@@ -1296,7 +1305,7 @@ g_variant_get (GVariant    *value,
   va_list ap;
 
   va_start (ap, format_string);
-  g_variant_get_va (value, NULL, &format_string, &ap);
+  g_variant_get_va (value, NULL, format_string, NULL, &ap);
   va_end (ap);
 }
 
@@ -1304,24 +1313,25 @@ g_variant_get (GVariant    *value,
  * g_variant_get_va:
  * @value: a #GVariant
  * @must_be_null: %NULL (for future expansion)
- * @format_string: a pointer to a format string
+ * @format_string: a string that is prefixed with a format string
+ * @endptr: location to store the end pointer, or %NULL
  * @app: a pointer to a #va_list
  *
- * This function is intended to be used by libraries based on
- * #GVariant that want to provide g_variant_new()-like functionality
- * to their users.
+ * This function is intended to be used by libraries based on #GVariant
+ * that want to provide g_variant_get()-like functionality to their
+ * users.
  *
  * The API is more general than g_variant_get() to allow a wider range
  * of possible uses.
  *
- * @format_string must still point to a valid format string, but it
- * need not be nul-terminated.  Instead, @format_string is updated to
- * point to the first character past the end of the given format
- * string.
+ * @format_string must still point to a valid format string, but it only
+ * need to be nul-terminated if @endptr is %NULL.  If @endptr is
+ * non-%NULL then it is updated to point to the first character past the
+ * end of the format string.
  *
  * @app is a pointer to a #va_list.  The arguments, according to
- * @format_string, are collected from this #va_list and the list is
- * left pointing to the argument following the last.
+ * @format_string, are collected from this #va_list and the list is left
+ * pointing to the argument following the last.
  *
  * These two generalisations allow mixing of multiple calls to
  * g_variant_new_va() and g_variant_get_va() within a single actual
@@ -1330,22 +1340,26 @@ g_variant_get (GVariant    *value,
 void
 g_variant_get_va (GVariant     *value,
                   gpointer      must_be_null,
-                  const gchar **format_string,
+                  const gchar  *format_string,
+                  const gchar **endptr,
                   va_list      *app)
 {
-  GVariantType *type;
-  const gchar *fmt;
+  g_return_if_fail (format_string != NULL);
+  g_return_if_fail (must_be_null == NULL);
+  g_return_if_fail (value != NULL);
+  g_return_if_fail (app != NULL);
 
-  g_assert (must_be_null == NULL);
-  g_assert (value != NULL);
+  {
+    GVariantType *type;
 
-  fmt = *format_string;
-  type = g_variant_format_string_scan_type (fmt, NULL, &fmt);
-  g_assert (g_variant_matches (value, type));
-  g_variant_type_free (type);
+    type = g_variant_format_string_scan_type (format_string, NULL, endptr);
+    g_return_if_fail (type != NULL);
+    g_return_if_fail (g_variant_matches (value, type));
+    g_variant_type_free (type);
+  }
 
   g_variant_flatten (value);
-  g_variant_valist_get (value, FALSE, format_string, app);
+  g_variant_valist_get (value, FALSE, &format_string, app);
 }
 
 /**
@@ -1450,9 +1464,7 @@ g_variant_builder_add (GVariantBuilder *builder,
   va_list ap;
 
   va_start (ap, format_string);
-  variant = g_variant_new_va (NULL, &format_string, &ap);
-  if (*format_string != '\0')
-    g_error ("Unhandled format string args: %s", format_string);
+  variant = g_variant_new_va (NULL, format_string, NULL, &ap);
   va_end (ap);
 
   g_variant_builder_add_value (builder, variant);
@@ -1481,8 +1493,9 @@ g_variant_get_child (GVariant    *value,
 
   g_variant_flatten (value);
   child = g_variant_get_child_value (value, index);
+
   va_start (ap, format_string);
-  g_variant_get_va (child, NULL, &format_string, &ap);
+  g_variant_get_va (child, NULL, format_string, NULL, &ap);
   va_end (ap);
 
   g_variant_unref (child);
@@ -1528,7 +1541,7 @@ g_variant_lookup (GVariant    *dictionary,
   if (format_string)
     {
       va_start (ap, format_string);
-      g_variant_get_va (child, NULL, &format_string, &ap);
+      g_variant_get_va (child, NULL, format_string, NULL, &ap);
       va_end (ap);
     }
 
diff --git a/glib/gvariant.h b/glib/gvariant.h
index 71d5b9e..e4129bb 100644
--- a/glib/gvariant.h
+++ b/glib/gvariant.h
@@ -52,11 +52,13 @@ gboolean                        g_variant_format_string_scan            (const g
                                                                          const gchar          *end,
                                                                          const gchar         **endptr);
 GVariant                       *g_variant_new_va                        (gpointer              must_be_null,
-                                                                         const gchar         **format_string,
+                                                                         const gchar          *format_string,
+                                                                         const gchar         **endptr,
                                                                          va_list              *app);
 void                            g_variant_get_va                        (GVariant             *value,
                                                                          gpointer              must_be_null,
-                                                                         const gchar         **format_string,
+                                                                         const gchar          *format_string,
+                                                                         const gchar         **endptr,
                                                                          va_list              *app);
 
 /* constructors */



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