[glib] GVariant: better support for object path arrays



commit 19878998bc386db78614f1c92ff8524a81479c7b
Author: Ryan Lortie <desrt desrt ca>
Date:   Wed Jul 20 13:11:19 2011 +0200

    GVariant: better support for object path arrays
    
    Add G_VARIANT_TYPE_OBJECT_PATH_ARRAY along with accessor functions
    g_variant_new_objv, g_variant_get_objv and g_variant_dup_objv.  Also add
    support for '^ao' and '^a&o' format strings for g_variant_new() and
    g_variant_get().
    
    https://bugzilla.gnome.org/show_bug.cgi?id=654955

 docs/reference/glib/glib-sections.txt    |    4 +
 docs/reference/glib/gvariant-varargs.xml |   39 +++++++-
 glib/glib.symbols                        |    3 +
 glib/gvariant.c                          |  168 ++++++++++++++++++++++++++++--
 glib/gvariant.h                          |    6 +
 glib/gvarianttype.h                      |    7 ++
 glib/tests/gvariant.c                    |   53 ++++++++++
 7 files changed, 270 insertions(+), 10 deletions(-)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index 3a0160d..0c581d2 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -2940,6 +2940,7 @@ G_VARIANT_TYPE_UNIT
 G_VARIANT_TYPE_DICT_ENTRY
 G_VARIANT_TYPE_DICTIONARY
 G_VARIANT_TYPE_STRING_ARRAY
+G_VARIANT_TYPE_OBJECT_PATH_ARRAY
 G_VARIANT_TYPE_BYTESTRING
 G_VARIANT_TYPE_BYTESTRING_ARRAY
 G_VARIANT_TYPE_VARDICT
@@ -3030,6 +3031,7 @@ g_variant_new_signature
 g_variant_is_signature
 g_variant_new_variant
 g_variant_new_strv
+g_variant_new_objv
 g_variant_new_bytestring
 g_variant_new_bytestring_array
 
@@ -3049,6 +3051,8 @@ g_variant_dup_string
 g_variant_get_variant
 g_variant_get_strv
 g_variant_dup_strv
+g_variant_get_objv
+g_variant_dup_objv
 g_variant_get_bytestring
 g_variant_dup_bytestring
 g_variant_get_bytestring_array
diff --git a/docs/reference/glib/gvariant-varargs.xml b/docs/reference/glib/gvariant-varargs.xml
index 2aac40b..1b15156 100644
--- a/docs/reference/glib/gvariant-varargs.xml
+++ b/docs/reference/glib/gvariant-varargs.xml
@@ -46,8 +46,8 @@
    <listitem>
     <para>
      '<literal>&amp;s</literal>' '<literal>&amp;o</literal>', '<literal>&amp;g</literal>', '<literal>^as</literal>',
-     '<literal>^a&amp;s</literal>', '<literal>^ay</literal>', '<literal>^&amp;ay</literal>', '<literal>^aay</literal>'
-     or '<literal>^a&amp;ay</literal>'.
+     '<literal>^a&amp;s</literal>', '<literal>^ao</literal>', '<literal>^a&amp;o</literal>','<literal>^ay</literal>',
+     '<literal>^&amp;ay</literal>', '<literal>^aay</literal>' or '<literal>^a&amp;ay</literal>'.
     </para>
    </listitem>
    <listitem>
@@ -1022,6 +1022,41 @@ value2 = g_variant_new ("(@(iii)*)", value1, g_variant_new_string ("foo"));
        <entry colsep='1' rowsep='1'>
         <para>
          <emphasis role='strong'>
+          <literal>^ao</literal>
+         </emphasis>
+        </para>
+       </entry>
+       <entry colsep='1' rowsep='1' morerows='1'>
+        <para>
+         equivalent to <link linkend='g-variant-new-objv'><function>g_variant_new_objv()</function></link>
+        </para>
+       </entry>
+       <entry colsep='1' rowsep='1'>
+        <para>
+         equivalent to <link linkend='g-variant-dup-objv'><function>g_variant_dup_objv()</function></link>
+        </para>
+       </entry>
+      </row>
+
+      <row rowsep='1'>
+       <entry colsep='1' rowsep='1'>
+        <para>
+         <emphasis role='strong'>
+          <literal>^a&amp;o</literal>
+         </emphasis>
+        </para>
+       </entry>
+       <entry colsep='1' rowsep='1'>
+        <para>
+         equivalent to <link linkend='g-variant-get-objv'><function>g_variant_get_objv()</function></link>
+        </para>
+       </entry>
+      </row>
+
+      <row rowsep='1'>
+       <entry colsep='1' rowsep='1'>
+        <para>
+         <emphasis role='strong'>
           <literal>^ay</literal>
          </emphasis>
         </para>
diff --git a/glib/glib.symbols b/glib/glib.symbols
index df978ec..dfb6748 100644
--- a/glib/glib.symbols
+++ b/glib/glib.symbols
@@ -1447,6 +1447,7 @@ g_variant_new_signature
 g_variant_is_signature
 g_variant_new_variant
 g_variant_new_strv
+g_variant_new_objv
 g_variant_new_bytestring
 g_variant_new_bytestring_array
 g_variant_get_boolean
@@ -1464,6 +1465,8 @@ g_variant_dup_string
 g_variant_get_variant
 g_variant_get_strv
 g_variant_dup_strv
+g_variant_get_objv
+g_variant_dup_objv
 g_variant_get_bytestring
 g_variant_dup_bytestring
 g_variant_get_bytestring_array
diff --git a/glib/gvariant.c b/glib/gvariant.c
index 26fa949..d7e9daf 100644
--- a/glib/gvariant.c
+++ b/glib/gvariant.c
@@ -1453,6 +1453,141 @@ g_variant_dup_strv (GVariant *value,
 }
 
 /**
+ * g_variant_new_objv:
+ * @strv: (array length=length) (element-type utf8): an array of strings
+ * @length: the length of @strv, or -1
+ * @returns: (transfer none): a new floating #GVariant instance
+ *
+ * Constructs an array of object paths #GVariant from the given array of
+ * strings.
+ *
+ * Each string must be a valid #GVariant object path; see
+ * g_variant_is_object_path().
+ *
+ * If @length is -1 then @strv is %NULL-terminated.
+ *
+ * Since: 2.30
+ **/
+GVariant *
+g_variant_new_objv (const gchar * const *strv,
+                    gssize               length)
+{
+  GVariant **strings;
+  gsize i;
+
+  g_return_val_if_fail (length == 0 || strv != NULL, NULL);
+
+  if (length < 0)
+    length = g_strv_length ((gchar **) strv);
+
+  strings = g_new (GVariant *, length);
+  for (i = 0; i < length; i++)
+    strings[i] = g_variant_ref_sink (g_variant_new_object_path (strv[i]));
+
+  return g_variant_new_from_children (G_VARIANT_TYPE_OBJECT_PATH_ARRAY,
+                                      strings, length, TRUE);
+}
+
+/**
+ * g_variant_get_objv:
+ * @value: an array of object paths #GVariant
+ * @length: (out) (allow-none): the length of the result, or %NULL
+ * @returns: (array length=length zero-terminated=1) (transfer container): an array of constant
+ * strings
+ *
+ * Gets the contents of an array of object paths #GVariant.  This call
+ * makes a shallow copy; the return result should be released with
+ * g_free(), but the individual strings must not be modified.
+ *
+ * If @length is non-%NULL then the number of elements in the result
+ * is stored there.  In any case, the resulting array will be
+ * %NULL-terminated.
+ *
+ * For an empty array, @length will be set to 0 and a pointer to a
+ * %NULL pointer will be returned.
+ *
+ * Since: 2.30
+ **/
+const gchar **
+g_variant_get_objv (GVariant *value,
+                    gsize    *length)
+{
+  const gchar **strv;
+  gsize n;
+  gsize i;
+
+  TYPE_CHECK (value, G_VARIANT_TYPE_OBJECT_PATH_ARRAY, NULL);
+
+  g_variant_get_data (value);
+  n = g_variant_n_children (value);
+  strv = g_new (const gchar *, n + 1);
+
+  for (i = 0; i < n; i++)
+    {
+      GVariant *string;
+
+      string = g_variant_get_child_value (value, i);
+      strv[i] = g_variant_get_string (string, NULL);
+      g_variant_unref (string);
+    }
+  strv[i] = NULL;
+
+  if (length)
+    *length = n;
+
+  return strv;
+}
+
+/**
+ * g_variant_dup_objv:
+ * @value: an array of object paths #GVariant
+ * @length: (out) (allow-none): the length of the result, or %NULL
+ * @returns: (array length=length zero-terminated=1) (transfer full): an array of strings
+ *
+ * Gets the contents of an array of object paths #GVariant.  This call
+ * makes a deep copy; the return result should be released with
+ * g_strfreev().
+ *
+ * If @length is non-%NULL then the number of elements in the result
+ * is stored there.  In any case, the resulting array will be
+ * %NULL-terminated.
+ *
+ * For an empty array, @length will be set to 0 and a pointer to a
+ * %NULL pointer will be returned.
+ *
+ * Since: 2.30
+ **/
+gchar **
+g_variant_dup_objv (GVariant *value,
+                    gsize    *length)
+{
+  gchar **strv;
+  gsize n;
+  gsize i;
+
+  TYPE_CHECK (value, G_VARIANT_TYPE_OBJECT_PATH_ARRAY, NULL);
+
+  n = g_variant_n_children (value);
+  strv = g_new (gchar *, n + 1);
+
+  for (i = 0; i < n; i++)
+    {
+      GVariant *string;
+
+      string = g_variant_get_child_value (value, i);
+      strv[i] = g_variant_dup_string (string, NULL);
+      g_variant_unref (string);
+    }
+  strv[i] = NULL;
+
+  if (length)
+    *length = n;
+
+  return strv;
+}
+
+
+/**
  * g_variant_new_bytestring:
  * @string: (array zero-terminated=1): a normal nul-terminated string in no particular encoding
  * @returns: (transfer none): a floating reference to a new bytestring #GVariant instance
@@ -3373,8 +3508,8 @@ g_variant_format_string_scan (const gchar  *string,
                     break;      /* '^a&ay' */
                 }
 
-              else if (c == 's')
-                break;          /* '^a&s' */
+              else if (c == 's' || c == 'o')
+                break;          /* '^a&s', '^a&o' */
             }
 
           else if (c == 'a')
@@ -3383,8 +3518,8 @@ g_variant_format_string_scan (const gchar  *string,
                 break;          /* '^aay' */
             }
 
-          else if (c == 's')
-            break;              /* '^as' */
+          else if (c == 's' || c == 'o')
+            break;              /* '^as', '^ao' */
 
           else if (c == 'y')
             break;              /* '^ay' */
@@ -3586,9 +3721,9 @@ g_variant_valist_free_nnp (const gchar *str,
       break;
 
     case '^':
-      if (str[2] != '&')        /* '^as' */
+      if (str[2] != '&')        /* '^as', '^ao' */
         g_strfreev (ptr);
-      else                      /* '^a&s' */
+      else                      /* '^a&s', '^a&o' */
         g_free (ptr);
       break;
 
@@ -3709,10 +3844,16 @@ g_variant_valist_new_nnp (const gchar **str,
       {
         gboolean constant;
         guint arrays;
+        gchar type;
+
+        type = g_variant_scan_convenience (str, &constant, &arrays);
 
-        if (g_variant_scan_convenience (str, &constant, &arrays) == 's')
+        if (type == 's')
           return g_variant_new_strv (ptr, -1);
 
+        if (type == 'o')
+          return g_variant_new_objv (ptr, -1);
+
         if (arrays > 1)
           return g_variant_new_bytestring_array (ptr, -1);
 
@@ -3780,8 +3921,11 @@ g_variant_valist_get_nnp (const gchar **str,
       {
         gboolean constant;
         guint arrays;
+        gchar type;
+
+        type = g_variant_scan_convenience (str, &constant, &arrays);
 
-        if (g_variant_scan_convenience (str, &constant, &arrays) == 's')
+        if (type == 's')
           {
             if (constant)
               return g_variant_get_strv (value, NULL);
@@ -3789,6 +3933,14 @@ g_variant_valist_get_nnp (const gchar **str,
               return g_variant_dup_strv (value, NULL);
           }
 
+        else if (type == 'o')
+          {
+            if (constant)
+              return g_variant_get_objv (value, NULL);
+            else
+              return g_variant_dup_objv (value, NULL);
+          }
+
         else if (arrays > 1)
           {
             if (constant)
diff --git a/glib/gvariant.h b/glib/gvariant.h
index f4f49bc..7f3af98 100644
--- a/glib/gvariant.h
+++ b/glib/gvariant.h
@@ -86,6 +86,8 @@ gboolean                        g_variant_is_signature                  (const g
 GVariant *                      g_variant_new_variant                   (GVariant             *value);
 GVariant *                      g_variant_new_strv                      (const gchar * const  *strv,
                                                                          gssize                length);
+GVariant *                      g_variant_new_objv                      (const gchar * const  *strv,
+                                                                         gssize                length);
 GVariant *                      g_variant_new_bytestring                (const gchar          *string);
 GVariant *                      g_variant_new_bytestring_array          (const gchar * const  *strv,
                                                                          gssize                length);
@@ -109,6 +111,10 @@ const gchar **                  g_variant_get_strv                      (GVarian
                                                                          gsize                *length);
 gchar **                        g_variant_dup_strv                      (GVariant             *value,
                                                                          gsize                *length);
+const gchar **                  g_variant_get_objv                      (GVariant             *value,
+                                                                         gsize                *length);
+gchar **                        g_variant_dup_objv                      (GVariant             *value,
+                                                                         gsize                *length);
 const gchar *                   g_variant_get_bytestring                (GVariant             *value);
 gchar *                         g_variant_dup_bytestring                (GVariant             *value,
                                                                          gsize                *length);
diff --git a/glib/gvarianttype.h b/glib/gvarianttype.h
index 5c686dd..be9555e 100644
--- a/glib/gvarianttype.h
+++ b/glib/gvarianttype.h
@@ -239,6 +239,13 @@ typedef struct _GVariantType GVariantType;
 #define G_VARIANT_TYPE_STRING_ARRAY         ((const GVariantType *) "as")
 
 /**
+ * G_VARIANT_TYPE_OBJECT_PATH_ARRAY:
+ *
+ * The type of an array of object paths.
+ **/
+#define G_VARIANT_TYPE_OBJECT_PATH_ARRAY    ((const GVariantType *) "ao")
+
+/**
  * G_VARIANT_TYPE_BYTESTRING:
  *
  * The type of an array of bytes.  This type is commonly used to pass
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
index 3d30a89..e943bb2 100644
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -3023,6 +3023,59 @@ test_varargs (void)
   }
 
   {
+    const gchar *strvector[] = {"/hello", "/world", NULL};
+    const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
+    GVariantBuilder builder;
+    GVariantIter *array;
+    GVariantIter tuple;
+    const gchar **strv;
+    gchar **my_strv;
+    GVariant *value;
+    gchar *str;
+    gint i;
+
+    g_variant_builder_init (&builder, G_VARIANT_TYPE_OBJECT_PATH_ARRAY);
+    g_variant_builder_add (&builder, "o", "/foo");
+    g_variant_builder_add (&builder, "o", "/bar");
+    g_variant_builder_add (&builder, "o", "/baz");
+    value = g_variant_new("(ao^ao^a&o)", &builder, strvector, strvector);
+    g_variant_iter_init (&tuple, value);
+    g_variant_iter_next (&tuple, "ao", &array);
+
+    i = 0;
+    while (g_variant_iter_loop (array, "o", &str))
+      g_assert_cmpstr (str, ==, test_strs[i++]);
+    g_assert (i == 3);
+
+    g_variant_iter_free (array);
+
+    /* start over */
+    g_variant_iter_init (&tuple, value);
+    g_variant_iter_next (&tuple, "ao", &array);
+
+    i = 0;
+    while (g_variant_iter_loop (array, "&o", &str))
+      g_assert_cmpstr (str, ==, test_strs[i++]);
+    g_assert (i == 3);
+
+    g_variant_iter_free (array);
+
+    g_variant_iter_next (&tuple, "^a&o", &strv);
+    g_variant_iter_next (&tuple, "^ao", &my_strv);
+
+    g_assert_cmpstr (strv[0], ==, "/hello");
+    g_assert_cmpstr (strv[1], ==, "/world");
+    g_assert (strv[2] == NULL);
+    g_assert_cmpstr (my_strv[0], ==, "/hello");
+    g_assert_cmpstr (my_strv[1], ==, "/world");
+    g_assert (my_strv[2] == NULL);
+
+    g_variant_unref (value);
+    g_strfreev (my_strv);
+    g_free (strv);
+  }
+
+  {
     const gchar *strvector[] = { "i", "ii", "iii", "iv", "v", "vi", NULL };
     GVariantBuilder builder;
     GVariantIter iter;



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