[glib/gvariantiter] GVariantIter
- From: Ryan Lortie <ryanl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/gvariantiter] GVariantIter
- Date: Fri, 19 Feb 2010 16:07:31 +0000 (UTC)
commit 3a930ceb4f24f6cd8c05c68ccf809029df352ec8
Author: Ryan Lortie <desrt desrt ca>
Date: Fri Feb 19 10:36:07 2010 -0500
GVariantIter
docs/reference/glib/glib-sections.txt | 10 +
docs/reference/glib/tmpl/glib-unused.sgml | 67 ------
docs/reference/glib/tmpl/macros_misc.sgml | 5 +-
docs/reference/glib/tmpl/version.sgml | 68 ++++++
glib/glib.symbols | 9 +
glib/gvariant.c | 350 +++++++++++++++++++++++++++++
glib/gvariant.h | 20 ++
7 files changed, 460 insertions(+), 69 deletions(-)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index dcb245a..65a02e0 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -2847,6 +2847,16 @@ g_variant_store
<SUBSECTION>
g_variant_hash
g_variant_equal
+
+<SUBSECTION>
+g_variant_iter_copy
+g_variant_iter_free
+g_variant_iter_init
+g_variant_iter_n_children
+g_variant_iter_new
+g_variant_iter_next
+g_variant_iter_next_nofree
+g_variant_iter_next_value
</SECTION>
<SECTION>
diff --git a/docs/reference/glib/tmpl/glib-unused.sgml b/docs/reference/glib/tmpl/glib-unused.sgml
index 139c500..ca73e16 100644
--- a/docs/reference/glib/tmpl/glib-unused.sgml
+++ b/docs/reference/glib/tmpl/glib-unused.sgml
@@ -900,73 +900,6 @@ Turns the argument into a string literal by using the '#' stringizing operator.
</para>
-<!-- ##### VARIABLE glib_binary_age ##### -->
-<para>
-This is the binary age passed to <application>libtool</application>. If
-<application>libtool</application> means nothing to you, don't worry
-about it. ;-)
-</para>
-
-
-<!-- ##### FUNCTION glib_check_version ##### -->
-<para>
-
-</para>
-
- required_major:
- required_minor:
- required_micro:
- Returns:
-
-<!-- ##### VARIABLE glib_interface_age ##### -->
-<para>
-This is the interface age passed to <application>libtool</application>. If
-<application>libtool</application> means nothing to you, don't worry
-about it. ;-)
-</para>
-
-
-<!-- ##### VARIABLE glib_major_version ##### -->
-<para>
-The major version number of the GLib library.
-(e.g. in GLib version 1.2.5 this is 1.)
-</para>
-
-<para>
-This variable is in the library, so represents the
-GLib library you have linked against. Contrast with the
-#GLIB_MAJOR_VERSION macro, which represents the major version of the
-GLib headers you have included.
-</para>
-
-
-<!-- ##### VARIABLE glib_micro_version ##### -->
-<para>
-The micro version number of the GLib library.
-(e.g. in GLib version 1.2.5 this is 5.)
-</para>
-
-<para>
-This variable is in the library, so represents the GLib library you
-have linked against. Contrast with the #GLIB_MICRO_VERSION macro, which
-represents the micro version of the GLib headers you have included.
-</para>
-
-
-<!-- ##### VARIABLE glib_minor_version ##### -->
-<para>
-The minor version number of the GLib library.
-(e.g. in GLib version 1.2.5 this is 2.)
-</para>
-
-<para>
-This variable is in the library, so represents the
-GLib library you have linked against. Contrast with the
-#GLIB_MINOR_VERSION macro, which represents the minor version of the
-GLib headers you have included.
-</para>
-
-
<!-- ##### MACRO lseek ##### -->
<para>
diff --git a/docs/reference/glib/tmpl/macros_misc.sgml b/docs/reference/glib/tmpl/macros_misc.sgml
index 29ad670..7ce3ff3 100644
--- a/docs/reference/glib/tmpl/macros_misc.sgml
+++ b/docs/reference/glib/tmpl/macros_misc.sgml
@@ -403,7 +403,7 @@ Since: 2.14
-<!-- ##### MACRO G_LIKELY ##### -->
+<!-- ##### FUNCTION G_LIKELY ##### -->
<para>
Hints the compiler that the expression is likely to evaluate to a true
value. The compiler may use this information for optimizations.
@@ -413,9 +413,10 @@ if (G_LIKELY (random () != 1))
g_print ("not one");
</programlisting></informalexample>
- expr: the expression
@Returns: the value of @expr
@Since: 2.2
+<!-- # Unused Parameters # -->
+ expr: the expression
<!-- ##### MACRO G_UNLIKELY ##### -->
diff --git a/docs/reference/glib/tmpl/version.sgml b/docs/reference/glib/tmpl/version.sgml
index b1cf0bb..f46c1e1 100644
--- a/docs/reference/glib/tmpl/version.sgml
+++ b/docs/reference/glib/tmpl/version.sgml
@@ -19,6 +19,74 @@ typically use the features described here.
<!-- ##### SECTION Stability_Level ##### -->
+<!-- ##### VARIABLE glib_major_version ##### -->
+<para>
+The major version number of the GLib library.
+(e.g. in GLib version 1.2.5 this is 1.)
+</para>
+
+<para>
+This variable is in the library, so represents the
+GLib library you have linked against. Contrast with the
+#GLIB_MAJOR_VERSION macro, which represents the major version of the
+GLib headers you have included.
+</para>
+
+
+<!-- ##### VARIABLE glib_minor_version ##### -->
+<para>
+The minor version number of the GLib library.
+(e.g. in GLib version 1.2.5 this is 2.)
+</para>
+
+<para>
+This variable is in the library, so represents the
+GLib library you have linked against. Contrast with the
+#GLIB_MINOR_VERSION macro, which represents the minor version of the
+GLib headers you have included.
+</para>
+
+
+<!-- ##### VARIABLE glib_micro_version ##### -->
+<para>
+The micro version number of the GLib library.
+(e.g. in GLib version 1.2.5 this is 5.)
+</para>
+
+<para>
+This variable is in the library, so represents the GLib library you
+have linked against. Contrast with the #GLIB_MICRO_VERSION macro, which
+represents the micro version of the GLib headers you have included.
+</para>
+
+
+<!-- ##### VARIABLE glib_binary_age ##### -->
+<para>
+This is the binary age passed to <application>libtool</application>. If
+<application>libtool</application> means nothing to you, don't worry
+about it. ;-)
+</para>
+
+
+<!-- ##### VARIABLE glib_interface_age ##### -->
+<para>
+This is the interface age passed to <application>libtool</application>. If
+<application>libtool</application> means nothing to you, don't worry
+about it. ;-)
+</para>
+
+
+<!-- ##### FUNCTION glib_check_version ##### -->
+<para>
+
+</para>
+
+ required_major:
+ required_minor:
+ required_micro:
+ Returns:
+
+
<!-- ##### MACRO GLIB_MAJOR_VERSION ##### -->
<para>
The major version number of the GLib library.
diff --git a/glib/glib.symbols b/glib/glib.symbols
index 8222b2b..970bf16 100644
--- a/glib/glib.symbols
+++ b/glib/glib.symbols
@@ -1754,6 +1754,15 @@ g_variant_print_string
g_variant_hash
g_variant_equal
+
+g_variant_iter_copy
+g_variant_iter_free
+g_variant_iter_init
+g_variant_iter_n_children
+g_variant_iter_new
+g_variant_iter_next
+g_variant_iter_next_nofree
+g_variant_iter_next_value
#endif
#endif
diff --git a/glib/gvariant.c b/glib/gvariant.c
index 6ed560d..e1a0c60 100644
--- a/glib/gvariant.c
+++ b/glib/gvariant.c
@@ -1854,5 +1854,355 @@ g_variant_equal (gconstpointer one,
return equal;
}
+/**
+ * GVariantIter:
+ *
+ * #GVariantIter is an opaque data structure and can only be accessed
+ * using the following functions.
+ **/
+struct stack_iter
+{
+ GVariant *value;
+ gssize n, i;
+ gsize magic;
+};
+
+struct heap_iter
+{
+ struct stack_iter iter;
+
+ GVariant *value_ref;
+ gsize magic;
+};
+
+#define GVSI(i) ((struct stack_iter *) (i))
+#define GVHI(i) ((struct heap_iter *) (i))
+#define GVSI_MAGIC ((gsize) 3579507750u)
+#define GVHI_MAGIC ((gsize) 1450270775u)
+#define is_valid_iter(i) (GVSI(i)->magic == GVSI_MAGIC)
+#define is_valid_heap_iter(i) (GVHI(i)->magic == GVHI_MAGIC && \
+ is_valid_iter(i))
+
+/**
+ * g_variant_iter_new:
+ * @value: a container #GVariant
+ * @returns: a new heap-allocated #GVariantIter
+ *
+ * Creates a heap-allocated #GVariantIter for iterating over the items
+ * in @value.
+ *
+ * It is appropriate to call g_variant_iter_free() on the return value
+ * of this function.
+ *
+ * A reference is taken to @value and will be released only when
+ * g_variant_iter_free() is called.
+ *
+ * Since: 2.24
+ **/
+GVariantIter *
+g_variant_iter_new (GVariant *value)
+{
+ GVariantIter *iter;
+
+ iter = (GVariantIter *) g_slice_new (struct heap_iter);
+ GVHI(iter)->value_ref = g_variant_ref (value);
+ GVHI(iter)->magic = GVHI_MAGIC;
+
+ g_variant_iter_init (iter, value);
+
+ return iter;
+}
+
+/**
+ * g_variant_iter_init:
+ * @iter: a pointer to a #GVariantIter
+ * @value: a container #GVariant
+ * @returns: the number of items in @value
+ *
+ * Initialises (without allocating) a #GVariantIter. @iter may be
+ * completely uninitialised prior to this call; its old value is
+ * ignored.
+ *
+ * The iterator remains valid for as long as @value exists, and need not
+ * be freed in any way.
+ *
+ * Since: 2.24
+ **/
+gsize
+g_variant_iter_init (GVariantIter *iter,
+ GVariant *value)
+{
+ g_assert (sizeof (GVariantIter) == sizeof (struct stack_iter));
+
+ GVSI(iter)->magic = GVSI_MAGIC;
+ GVSI(iter)->value = value;
+ GVSI(iter)->n = g_variant_n_children (value);
+ GVSI(iter)->i = -1;
+
+ return GVSI(iter)->n;
+}
+
+/**
+ * g_variant_iter_copy:
+ * @iter: a #GVariantIter
+ * @returns: a new heap-allocated #GVariantIter
+ *
+ * Creates a new heap-allocated #GVariantIter to iterate over the
+ * container that was being iterated over by @iter. The iterator is
+ * rewound and starts at the beginning.
+ *
+ * It is appropriate to call g_variant_iter_free() on the return value
+ * of this function.
+ *
+ * Since: 2.24
+ **/
+GVariantIter *
+g_variant_iter_copy (GVariantIter *iter)
+{
+ g_return_val_if_fail (is_valid_iter (iter), 0);
+
+ return g_variant_iter_new (GVSI(iter)->value);
+}
+
+/**
+ * g_variant_iter_n_children:
+ * @iter: a #GVariantIter
+ * @returns: the number of children in the container
+ *
+ * Queries the number of child items in the container that we are
+ * iterating over. This is the total number of items -- not the number
+ * of items remaining.
+ *
+ * This function might be useful for preallocation of arrays.
+ *
+ * Since: 2.24
+ **/
+gsize
+g_variant_iter_n_children (GVariantIter *iter)
+{
+ g_return_val_if_fail (is_valid_iter (iter), 0);
+
+ return GVSI(iter)->n;
+}
+
+/**
+ * g_variant_iter_free:
+ * @iter: a heap-allocated #GVariantIter
+ *
+ * Frees a heap-allocated #GVariantIter. Only call this function on
+ * iterators that were returned by g_variant_iter_new() or
+ * g_variant_iter_copy().
+ *
+ * Since: 2.24
+ **/
+void
+g_variant_iter_free (GVariantIter *iter)
+{
+ g_return_if_fail (is_valid_heap_iter (iter));
+
+ g_variant_unref (GVHI(iter)->value_ref);
+ GVHI(iter)->magic = 0;
+
+ g_slice_free (struct heap_iter, GVHI(iter));
+}
+
+/**
+ * g_variant_iter_next_value:
+ * @iter: a #GVariantIter
+ * @returns: a #GVariant, or %NULL
+ *
+ * Gets the next item in the container. If no more items remain then
+ * %NULL is returned.
+ *
+ * It is appropriate to call g_variant_unref() on the return value of
+ * this function.
+ *
+ * <example>
+ * <title>Iterating with g_variant_iter_next_value()</title>
+ * <programlisting>
+ * /<!-- -->* recursively iterate a container *<!-- -->/
+ * void
+ * iterate_container_recursive (GVariant *container)
+ * {
+ * GVariantIter iter;
+ * GVariant *child;
+ *
+ * g_variant_iter_init (&iter, dictionary);
+ * while ((child = g_variant_iter_next_value (&iter)))
+ * {
+ * g_print ("type '%s'\n", g_variant_get_type_string (child));
+ *
+ * if (g_variant_is_container (child))
+ * iterate_container_recursive (child);
+ *
+ * g_variant_unref (child);
+ * }
+ * }
+ * </programlisting>
+ * </example>
+ *
+ * Since: 2.24
+ **/
+GVariant *
+g_variant_iter_next_value (GVariantIter *iter)
+{
+ g_return_val_if_fail (is_valid_iter (iter), FALSE);
+
+ if G_UNLIKELY (GVSI(iter)->i >= GVSI(iter)->n)
+ {
+ g_critical ("g_variant_iter_get: must not be called again "
+ "after NULL has already been returned.");
+ return NULL;
+ }
+
+ GVSI(iter)->i++;
+
+ if (GVSI(iter)->i < GVSI(iter)->n)
+ return g_variant_get_child_value (GVSI(iter)->value, GVSI(iter)->i);
+
+ return NULL;
+}
+
+/**
+ * g_variant_iter_next:
+ * @iter: a #GVariantIter
+ * @format_string: a GVariant format string
+ * @...: the arguments to unpack the value into
+ * @returns: %TRUE if a value was unpacked, or %FALSE if there as no
+ * value
+ *
+ * Gets the next item in the container and unpacks it into the variable
+ * argument list according to @format_string, returning %TRUE.
+ *
+ * If no more items remain then %FALSE is returned.
+ *
+ * On the first call to this function, the pointers appearing on the
+ * variable argument list are assumed to point at uninitialised memory.
+ * On the second and later calls, it is assumed that the same pointers
+ * will be given and that they will point to the memory as set by the
+ * previous call to this function. This allows the previous values to
+ * be freed, as appropriate.
+ *
+ * <example>
+ * <title>Memory management with g_variant_iter_next()</title>
+ * <programlisting>
+ * /<!-- -->* Iterates a dictionary of type 'a{sv}' *<!-- -->/
+ * void
+ * iterate_dictionary (GVariant *dictionary)
+ * {
+ * GVariantIter iter;
+ * GVariant *value;
+ * gchar *key;
+ *
+ * g_variant_iter_init (&iter, dictionary);
+ * while (g_variant_iter_next (&iter, "{sv}", &key, &value))
+ * {
+ * g_print ("Item '%s' has type '%s'\n", key,
+ * g_variant_get_type_string (value));
+ *
+ * /<!-- -->* no need to free 'key' and 'value' here *<!-- -->/
+ * }
+ * }
+ * </programlisting>
+ * </example>
+ *
+ * If you want a slightly less magical alternative that requires more
+ * typing, see g_variant_iter_next_nofree().
+ *
+ * Since: 2.24
+ **/
+gboolean
+g_variant_iter_next (GVariantIter *iter,
+ const gchar *format_string,
+ ...)
+{
+ GVariant *value;
+
+ value = g_variant_iter_next_value (iter);
+
+ if (value != NULL)
+ {
+ va_list ap;
+
+ va_start (ap, format_string);
+ /* varargs get stuff */
+ va_end (ap);
+
+ g_variant_unref (value);
+ }
+
+ return FALSE;
+}
+
+/**
+ * @iter: a #GVariantIter
+ * @format_string: a GVariant format string
+ * @...: the arguments to unpack the value into
+ * @returns: %TRUE if a value was unpacked, or %FALSE if there as no
+ * value
+ *
+ * Gets the next item in the container and unpacks it into the variable
+ * argument list according to @format_string, returning %TRUE.
+ *
+ * If no more items remain then %FALSE is returned.
+ *
+ * All of the pointers given on the varaible arguments list of this
+ * function are assumed to point at uninitialised memory. It is the
+ * responsibility of the caller to free all of the values returned by
+ * the unpacking process.
+ *
+ * <example>
+ * <title>Memory management with g_variant_iter_next_nofree()</title>
+ * <programlisting>
+ * /<!-- -->* Iterates a dictionary of type 'a{sv}' *<!-- -->/
+ * void
+ * iterate_dictionary (GVariant *dictionary)
+ * {
+ * GVariantIter iter;
+ * GVariant *value;
+ * gchar *key;
+ *
+ * g_variant_iter_init (&iter, dictionary);
+ * while (g_variant_iter_next_nofree (&iter, "{sv}", &key, &value))
+ * {
+ * g_print ("Item '%s' has type '%s'\n", key,
+ * g_variant_get_type_string (value));
+ *
+ * /<!-- -->* must free data for ourselves *<!-- -->/
+ * g_variant_unref (value);
+ * g_free (key);
+ * }
+ * }
+ * </programlisting>
+ * </example>
+ *
+ * For a solution that is likely to be more convenient to C programmers,
+ * see g_variant_iter_next().
+ *
+ * Since: 2.24
+ **/
+gboolean
+g_variant_iter_next_nofree (GVariantIter *iter,
+ const gchar *format_string,
+ ...)
+{
+ GVariant *value;
+
+ value = g_variant_iter_next_value (iter);
+
+ if (value != NULL)
+ {
+ va_list ap;
+
+ va_start (ap, format_string);
+ /* varargs get stuff */
+ va_end (ap);
+
+ g_variant_unref (value);
+ }
+
+ return FALSE;
+}
+
#define __G_VARIANT_C__
#include "galiasdef.c"
diff --git a/glib/gvariant.h b/glib/gvariant.h
index 1860bc2..847ed7e 100644
--- a/glib/gvariant.h
+++ b/glib/gvariant.h
@@ -135,6 +135,26 @@ guint g_variant_hash (gconstp
gboolean g_variant_equal (gconstpointer one,
gconstpointer two);
+typedef struct _GVariantIter GVariantIter;
+struct _GVariantIter {
+ /*< private >*/
+ gsize x[4];
+};
+
+GVariantIter * g_variant_iter_new (GVariant *value);
+gsize g_variant_iter_init (GVariantIter *iter,
+ GVariant *value);
+GVariantIter * g_variant_iter_copy (GVariantIter *iter);
+gsize g_variant_iter_n_children (GVariantIter *iter);
+void g_variant_iter_free (GVariantIter *iter);
+GVariant * g_variant_iter_next_value (GVariantIter *iter);
+gboolean g_variant_iter_next (GVariantIter *iter,
+ const gchar *format_string,
+ ...);
+gboolean g_variant_iter_next_nofree (GVariantIter *iter,
+ const gchar *format_string,
+ ...);
+
G_END_DECLS
#endif /* __G_VARIANT_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]