Using GVariantBuilder with complex structures



Hi,

I've been trying to figure out how to use GVariantBuilder to build a
complex structure with little success. The type of structure that I
would like to build is meant to partially encode a GtkTreeModel
structure. So, I thought that I could use GVariantBuilder to build a
structure of nested dictionaries.

The structure roughly follows this model:
[
  {
    "id": { "key1": (<int>, <string>, ...), "children": [
                          { "id2" : { "key1" : (<int>, <string>, ...),
"children" : []},
                          { "id3" : { "key1" : (<int>, <string>, ...),
"children" : [
                              { ... }
                              ]}
                          ]}},
  { "id" : ...}
]

This type of encoding can naturally be done with recursion and using
multiple GVariantBuilder's to add to the correct parent. However, I am
having difficulty with getting the formatting strings correct. As it
turns out, GLib insist on every dictionary entry being statically
typed meaning that the values for both "key1" and "children" has to be
of the same type. That seems to leave only 'v' as a valid format. So,
I have the following code (only important parts are pasted, not a
complete program):

struct tree_entry_search {
        uint32_t type;
        const char *term;
};

struct tree_entry {
        const char *id;
        struct tree_entry_search search;
        GList *children;
};

void add_elem(GVariantBuilder *builder, struct tree_entry *elem)
{
        GVariantBuilder *new, *child_builder;
        GVariant *new_dict, *new_array, *search;
        GList *item;

        new = g_variant_builder_new(G_VARIANT_TYPE_DICTIONARY);
        search = g_variant_new("(us)", elem->search.type, elem->search.term);
        g_variant_builder_add(new, "{sv}", "search", search);
        child_builder = g_variant_builder_new(G_VARIANT_TYPE("av"));
        for (item = elem->children; item; item = item->next)
                add_elem(child_builder, item->data);
        new_array = g_variant_builder_end(child_builder);
        g_variant_builder_unref(child_builder);
        g_variant_builder_add(new, "{sv}", "children", new_array);
        new_dict = g_variant_builder_end(new);
        g_variant_builder_unref(new);
        g_variant_builder_add(builder, "{sv}", elem->id, new_dict);
}

int main(void) {
        ...
        /* Build up a fake tree. */
        root.id = g_strdup("uid1");
        root.search.type = 1;
        root.search.term = g_strdup("term1");
        elem = g_new0(struct tree_entry, 1);
        elem->id = g_strdup("uid2");
        elem->search.type = 2;
        elem->search.term = g_strdup("term2");
        root.children = g_list_append(root.children, elem);
        elem = g_new0(struct tree_entry, 1);
        elem->id = g_strdup("uid3");
        elem->search.type = 2;
        elem->search.term = g_strdup("term3");
        root.children = g_list_append(root.children, elem);
        child = g_new0(struct tree_entry, 1);
        child->id = g_strdup("uid4");
        child->search.type = 3;
        child->search.term = g_strdup("term4");
        elem->children = g_list_append(elem->children, child);

        builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
        add_elem(builder, &root);
        dict = g_variant_builder_end(builder);
        dictionary = g_variant_print(dict, TRUE);
        printf("%s\n", dictionary);
        ...
}

But when I compile the above and run it, I get the following errors
when the tree is more than one level deep:

(process:3873): GLib-CRITICAL **: 11:44:03.826:
g_variant_builder_add_value: assertion '!GVSB(builder)->expected_type
|| g_variant_is_of_type (value, GVSB(builder)->expected_type)' failed

(process:3873): GLib-CRITICAL **: 11:44:03.827:
g_variant_builder_add_value: assertion '!GVSB(builder)->expected_type
|| g_variant_is_of_type (value, GVSB(builder)->expected_type)' failed

(process:3873): GLib-CRITICAL **: 11:44:03.827:
g_variant_builder_add_value: assertion '!GVSB(builder)->expected_type
|| g_variant_is_of_type (value, GVSB(builder)->expected_type)' failed

What's the correct way to specify the builder and variant types so I
can build the nested dictionary structure?

Thank you for the help.


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]