make GVariant dictionaries more useful
Submitted by Simon McVittie
Assigned to Allison (desrt)
Link to original bug (#625408)
Description
GVariant dictionaries are currently a straightforward mapping of what appears on D-Bus: an array of DICT_ENTRY, where a DICT_ENTRY is a pair (2-tuple) with the first entry constrained to be a basic type.
However, D-Bus APIs typically use a dictionary as a lookup table/hash table sort of data structure, in which it's useful to do random-access lookups:
- look up a value by a GVariant key, return the corresponding value or NULL
- if there are duplicate keys, this is an error (the D-Bus spec forbids this); silently return either the first or the last, whichever makes more sense (the D-Bus spec allows this)
- should be faster than O(n)
- it's very convenient for C if the value returned is owned by the dict, meaning it doesn't need to be freed as long as the caller owns a ref to the dict
I can see two viable ways to achieve this:
- Put a GHashTable cache inside the GVariant, populate it on first use, and free it at the same time as the GVariant
- Make a GVariantDict object which contains the GVariant and the GHashTable, and give it convenience API
The second is the only one that can be done outside GLib, so I'll start prototyping it; we can turn it into the first later if that's considered better API.
It would also be useful to have a more convenient API than this for some common special cases:
- dict<string, something>, i.e. a{s*} in GVariant notation
- dict<string, variant>, i.e. a{sv}, in which there's as little unboxing boilerplate as possible
- perhaps dict<object path, something>, i.e. a{o*} in GVariant notation, if the string special case doesn't also accept object paths
Some background on a{sv}: telepathy-glib currently has the tp_asv_get_* family of functions, which are a very convenient API to deal with dbus-glib's representation of an a{sv} (a GHashTable<string, GValue>):
GHashTable *asv;
const gchar *badger;
guint mushroom;
gboolean is_valid_integer;
asv = tp_channel_get_properties (channel);
badger = tp_asv_get_string (asv, "com.example.MyExtension.Badger");
mushroom = tp_asv_get_uint32 (asv, "com.example.MyExtension.Mushroom",
&is_valid_integer);
For more, see: http://telepathy.freedesktop.org/doc/telepathy-glib/telepathy-glib-asv.html
Ideally, I'd like to have an API this easy to deal with a GVariant a{sv} in GLib itself. telepathy-glib would then be able to use a GVariant or GVariantDict in places where it currently uses a dbus-glib GHashTable<string,GValue> to give extensible data to Telepathy clients, and those clients would be able to do things like:
GVariantDict *asv;
const gchar *badger;
asv = tp_channel_get_properties (channel);
badger = g_variant_asv_get_string (asv, "com.example.MyExtension.Badger");
Version: 2.27.x