mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-20 17:22:11 +01:00
Add g_variant_lookup() and tests
Convenience API for doing lookups in dictionaries where the key is a string or object path.
This commit is contained in:
parent
57b4b7099f
commit
7fc6f8a159
@ -3015,6 +3015,8 @@ g_variant_get_maybe
|
|||||||
g_variant_n_children
|
g_variant_n_children
|
||||||
g_variant_get_child_value
|
g_variant_get_child_value
|
||||||
g_variant_get_child
|
g_variant_get_child
|
||||||
|
g_variant_lookup_value
|
||||||
|
g_variant_lookup
|
||||||
g_variant_get_fixed_array
|
g_variant_get_fixed_array
|
||||||
|
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
|
@ -1880,6 +1880,8 @@ g_variant_get
|
|||||||
|
|
||||||
g_variant_builder_add
|
g_variant_builder_add
|
||||||
g_variant_get_child
|
g_variant_get_child
|
||||||
|
g_variant_lookup_value
|
||||||
|
g_variant_lookup
|
||||||
g_variant_iter_next
|
g_variant_iter_next
|
||||||
g_variant_iter_loop
|
g_variant_iter_loop
|
||||||
|
|
||||||
|
144
glib/gvariant.c
144
glib/gvariant.c
@ -898,6 +898,150 @@ g_variant_new_dict_entry (GVariant *key,
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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:
|
* g_variant_get_fixed_array:
|
||||||
* @value: a #GVariant array with fixed-sized elements
|
* @value: a #GVariant array with fixed-sized elements
|
||||||
|
@ -134,6 +134,13 @@ void g_variant_get_child (GVarian
|
|||||||
...);
|
...);
|
||||||
GVariant * g_variant_get_child_value (GVariant *value,
|
GVariant * g_variant_get_child_value (GVariant *value,
|
||||||
gsize index_);
|
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,
|
gconstpointer g_variant_get_fixed_array (GVariant *value,
|
||||||
gsize *n_elements,
|
gsize *n_elements,
|
||||||
gsize element_size);
|
gsize element_size);
|
||||||
|
@ -3897,6 +3897,78 @@ test_bytestring (void)
|
|||||||
g_variant_unref (untrusted_empty);
|
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
|
int
|
||||||
main (int argc, char **argv)
|
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/parse-positional", test_parse_positional);
|
||||||
g_test_add_func ("/gvariant/floating", test_floating);
|
g_test_add_func ("/gvariant/floating", test_floating);
|
||||||
g_test_add_func ("/gvariant/bytestring", test_bytestring);
|
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 ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user