[glib] Add g_variant_lookup() and tests
- From: Ryan Lortie <ryanl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] Add g_variant_lookup() and tests
- Date: Sat, 6 Nov 2010 01:34:39 +0000 (UTC)
commit 7fc6f8a1596b18a23e1570fc6716b34a137b76c6
Author: Ryan Lortie <desrt desrt ca>
Date: Fri Nov 5 21:33:06 2010 -0400
Add g_variant_lookup() and tests
Convenience API for doing lookups in dictionaries where the key is a
string or object path.
docs/reference/glib/glib-sections.txt | 2 +
glib/glib.symbols | 2 +
glib/gvariant.c | 144 +++++++++++++++++++++++++++++++++
glib/gvariant.h | 7 ++
glib/tests/gvariant.c | 74 +++++++++++++++++
5 files changed, 229 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index d2f7422..dca0a98 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -3015,6 +3015,8 @@ g_variant_get_maybe
g_variant_n_children
g_variant_get_child_value
g_variant_get_child
+g_variant_lookup_value
+g_variant_lookup
g_variant_get_fixed_array
<SUBSECTION>
diff --git a/glib/glib.symbols b/glib/glib.symbols
index 232e12a..73ec856 100644
--- a/glib/glib.symbols
+++ b/glib/glib.symbols
@@ -1880,6 +1880,8 @@ g_variant_get
g_variant_builder_add
g_variant_get_child
+g_variant_lookup_value
+g_variant_lookup
g_variant_iter_next
g_variant_iter_loop
diff --git a/glib/gvariant.c b/glib/gvariant.c
index e333597..5c8737f 100644
--- a/glib/gvariant.c
+++ b/glib/gvariant.c
@@ -899,6 +899,150 @@ g_variant_new_dict_entry (GVariant *key,
}
/**
+ * g_variant_lookup:
+ * @dictionary: a dictionary #GVariant
+ * @key: the key to lookup in the dictionary
+ * @format_string: a GVariant format string
+ * @...: the arguments to unpack the value into
+ *
+ * Looks up a value in a dictionary #GVariant.
+ *
+ * This function is a wrapper around g_variant_lookup_value() and
+ * g_variant_get(). In the case that %NULL would have been returned,
+ * this function returns %FALSE. Otherwise, it unpacks the returned
+ * value and returns %TRUE.
+ *
+ * See g_variant_get() for information about @format_string.
+ *
+ * Returns: %TRUE if a value was unpacked
+ *
+ * Since: 2.28
+ */
+gboolean
+g_variant_lookup (GVariant *dictionary,
+ const gchar *key,
+ const gchar *format_string,
+ ...)
+{
+ GVariantType *type;
+ GVariant *value;
+
+ /* flatten */
+ g_variant_get_data (dictionary);
+
+ type = g_variant_format_string_scan_type (format_string, NULL, NULL);
+ value = g_variant_lookup_value (dictionary, key, type);
+ g_variant_type_free (type);
+
+ if (value)
+ {
+ va_list ap;
+
+ va_start (ap, format_string);
+ g_variant_get_va (value, format_string, NULL, &ap);
+ g_variant_unref (value);
+ va_end (ap);
+
+ return TRUE;
+ }
+
+ else
+ return FALSE;
+}
+
+/**
+ * g_variant_lookup:
+ * @dictionary: a dictionary #GVariant
+ * @key: the key to lookup in the dictionary
+ * @expected_type: a #GVariantType, or %NULL
+ *
+ * Looks up a value in a dictionary #GVariant.
+ *
+ * This function works with dictionaries of the type
+ * <literal>a{s*}</literal> (and equally well with type
+ * <literal>a{o*}</literal>, but we only further discuss the string case
+ * for sake of clarity).
+ *
+ * In the event that @dictionary has the type <literal>a{sv}</literal>,
+ * the @expected_type string specifies what type of value is expected to
+ * be inside of the variant. If the value inside the variant has a
+ * different type then %NULL is returned. In the event that @dictionary
+ * has a value type other than <literal>v</literal> then @expected_type
+ * must directly match the key type and it is used to unpack the value
+ * directly or an error occurs.
+ *
+ * In either case, if @key is not found in @dictionary, %NULL is
+ * returned.
+ *
+ * If the key is found and the value has the correct type, it is
+ * returned. If @expected_type was specified then any non-%NULL return
+ * value will have this type.
+ *
+ * Returns: the value of the dictionary key, or %NULL
+ *
+ * Since: 2.28
+ */
+GVariant *
+g_variant_lookup_value (GVariant *dictionary,
+ const gchar *key,
+ const GVariantType *expected_type)
+{
+ GVariantIter iter;
+ GVariant *entry;
+ GVariant *value;
+
+ g_return_val_if_fail (g_variant_is_of_type (dictionary,
+ G_VARIANT_TYPE ("a{s*}")) ||
+ g_variant_is_of_type (dictionary,
+ G_VARIANT_TYPE ("a{o*}")),
+ NULL);
+
+ g_variant_iter_init (&iter, dictionary);
+
+ while ((entry = g_variant_iter_next_value (&iter)))
+ {
+ GVariant *entry_key;
+ gboolean matches;
+
+ entry_key = g_variant_get_child_value (entry, 0);
+ matches = strcmp (g_variant_get_string (entry_key, NULL), key) == 0;
+ g_variant_unref (entry_key);
+
+ if (matches)
+ break;
+
+ g_variant_unref (entry);
+ }
+
+ if (entry == NULL)
+ return NULL;
+
+ value = g_variant_get_child_value (entry, 1);
+ g_variant_unref (entry);
+
+ if (g_variant_is_of_type (value, G_VARIANT_TYPE_VARIANT))
+ {
+ GVariant *tmp;
+
+ tmp = g_variant_get_variant (value);
+ g_variant_unref (value);
+
+ if (expected_type && !g_variant_is_of_type (tmp, expected_type))
+ {
+ g_variant_unref (tmp);
+ tmp = NULL;
+ }
+
+ value = tmp;
+ }
+
+ g_return_val_if_fail (expected_type == NULL || value == NULL ||
+ g_variant_is_of_type (value, expected_type), NULL);
+
+ return value;
+}
+
+/**
* g_variant_get_fixed_array:
* @value: a #GVariant array with fixed-sized elements
* @n_elements: a pointer to the location to store the number of items
diff --git a/glib/gvariant.h b/glib/gvariant.h
index 528492b..9491c99 100644
--- a/glib/gvariant.h
+++ b/glib/gvariant.h
@@ -134,6 +134,13 @@ void g_variant_get_child (GVarian
...);
GVariant * g_variant_get_child_value (GVariant *value,
gsize index_);
+gboolean g_variant_lookup (GVariant *value,
+ const gchar *key,
+ const gchar *format_string,
+ ...);
+GVariant * g_variant_lookup_value (GVariant *value,
+ const gchar *key,
+ const GVariantType *type);
gconstpointer g_variant_get_fixed_array (GVariant *value,
gsize *n_elements,
gsize element_size);
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
index 2c3c048..afbafd4 100644
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -3897,6 +3897,78 @@ test_bytestring (void)
g_variant_unref (untrusted_empty);
}
+static void
+test_lookup_value (void)
+{
+ struct {
+ const gchar *dict, *key, *value;
+ } cases[] = {
+ { "@a{ss} {'x': 'y'}", "x", "'y'" },
+ { "@a{ss} {'x': 'y'}", "y" },
+ { "@a{os} {'/x': 'y'}", "/x", "'y'" },
+ { "@a{os} {'/x': 'y'}", "/y" },
+ { "@a{sv} {'x': <'y'>}", "x", "'y'" },
+ { "@a{sv} {'x': <5>}", "x", "5" },
+ { "@a{sv} {'x': <'y'>}", "y" }
+ };
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (cases); i++)
+ {
+ GVariant *dictionary;
+ GVariant *value;
+ gchar *p;
+
+ dictionary = g_variant_parse (NULL, cases[i].dict, NULL, NULL, NULL);
+ value = g_variant_lookup_value (dictionary, cases[i].key, NULL);
+ g_variant_unref (dictionary);
+
+ if (value == NULL && cases[i].value == NULL)
+ continue;
+
+ g_assert (value && cases[i].value);
+ p = g_variant_print (value, FALSE);
+ g_assert_cmpstr (cases[i].value, ==, p);
+ g_variant_unref (value);
+ g_free (p);
+ }
+}
+
+static void
+test_lookup (void)
+{
+ const gchar *str;
+ GVariant *dict;
+ gboolean ok;
+ gint num;
+
+ dict = g_variant_parse (NULL,
+ "{'a': <5>, 'b': <'c'>}",
+ NULL, NULL, NULL);
+
+ ok = g_variant_lookup (dict, "a", "i", &num);
+ g_assert (ok);
+ g_assert_cmpint (num, ==, 5);
+
+ ok = g_variant_lookup (dict, "a", "&s", &str);
+ g_assert (!ok);
+
+ ok = g_variant_lookup (dict, "q", "&s", &str);
+ g_assert (!ok);
+
+ ok = g_variant_lookup (dict, "b", "i", &num);
+ g_assert (!ok);
+
+ ok = g_variant_lookup (dict, "b", "&s", &str);
+ g_assert (ok);
+ g_assert_cmpstr (str, ==, "c");
+
+ ok = g_variant_lookup (dict, "q", "&s", &str);
+ g_assert (!ok);
+
+ g_variant_unref (dict);
+}
+
int
main (int argc, char **argv)
{
@@ -3937,6 +4009,8 @@ main (int argc, char **argv)
g_test_add_func ("/gvariant/parse-positional", test_parse_positional);
g_test_add_func ("/gvariant/floating", test_floating);
g_test_add_func ("/gvariant/bytestring", test_bytestring);
+ g_test_add_func ("/gvariant/lookup-value", test_lookup_value);
+ g_test_add_func ("/gvariant/lookup", test_lookup);
return g_test_run ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]