mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 11:26:16 +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_get_child_value
|
||||
g_variant_get_child
|
||||
g_variant_lookup_value
|
||||
g_variant_lookup
|
||||
g_variant_get_fixed_array
|
||||
|
||||
<SUBSECTION>
|
||||
|
@ -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
|
||||
|
||||
|
144
glib/gvariant.c
144
glib/gvariant.c
@ -898,6 +898,150 @@ g_variant_new_dict_entry (GVariant *key,
|
||||
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:
|
||||
* @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,
|
||||
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);
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user