After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 771968 - Problem specifying a gschema key/type for a dictionary with variant (array) data.
Problem specifying a gschema key/type for a dictionary with variant (array) d...
Status: RESOLVED INCOMPLETE
Product: glib
Classification: Platform
Component: gsettings
2.50.x
Other Linux
: Normal normal
: ---
Assigned To: Allison Karlitskaya (desrt)
gtkdev
Depends on:
Blocks:
 
 
Reported: 2016-09-26 02:07 UTC by Percy
Modified: 2016-09-28 23:20 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Percy 2016-09-26 02:07:43 UTC
I have a problem, kind of exclusive:
Either I can not located key in a dictionary in my gschema if I store it with type "a{sau}" what I actually want. Resulting in "key not found".
Or I can not specify the type "a{sv}"  or to be precise "a{s@au}" for the schema file. Resulting in glib-compile error / wrong type.

I created a test variant (not using the gschema) of a similar type and can confirm, key not found.

Then I created a test variant using a type "a{sv}" to build a test variant from "{'AC': <[1, 2, 3, 4, 5, 6, 7, 8]>, ..." and then I can located the key and access the data/array. But now I was not able to figure out how to specify the array type "au" and always get the default "ai" -- or how do I do this???

Now I assume I some how have to "enclose or box" my array within a variant for the dictionary data part, bu how to I specify this in my gschema xml file?
I tried type="a{sv}" -- glib-compile error "wrong type".
I tried type="a{s@au}" -- glib-compile error "wrong type".
Not possible?
What would be the proper syntax here? I read over and over the documentations, but can not find a hint.

Thanks for any hints in advance.

Below is some test code, I added a lot of checking to identify the issue.


void DSPControl::get_tab_settings (const gchar *tab_key, gint &option_flags, gint &auto_flags, gint glock_data[6]) {

        g_print ("DSPControl::get_tab_settings -- Looking for key '%s' in probe-tab-options.\n", tab_key);

        /* in ...gschema.xml file and installed key. Looking OK in dconf-editor. But thus fails finding I the keys.

   <key name="probe-tab-options" type="a{sau}">
     <default>{
      "AC": [0,0, 0,0,0,0,0,0],
      "IV": [0,0, 0,0,0,0,0,0],
      "FZ": [0,0, 0,0,0,0,0,0],
      "PL": [0,0, 0,0,0,0,0,0],
      "LP": [0,0, 0,0,0,0,0,0],
      "SP": [0,0, 0,0,0,0,0,0],
      "TS": [0,0, 0,0,0,0,0,0],
      "LM": [0,0, 0,0,0,0,0,0],
      "TK": [0,0, 0,0,0,0,0,0],
      "AX": [0,0, 0,0,0,0,0,0],
      "AB": [0,0, 0,0,0,0,0,0]}
      </default>
      <summary>
	dictionary for probe tabs (AC, ...)
        containing a array of [STS,.. option-flags, auto-flags, glock-data[6]]]
      </summary>
      <description>
	data
      </description>
    </key>

        */

        // THIS IS WHAT I NEED TO READ AND MANAGE/STORE
        // GVariantDict *dict = g_variant_dict_new (g_settings_get_value (hwi_settings, "probe-tab-options")); // --> does not work, no key found. But returns non zero dict.
        
        
        // GVariant *v = g_variant_new_parsed ("[{'AC', [0, 0, 0, 0, 0, 0, 0, 0]}, {'IV', [0, 0, 0, 0, 0, 0, 0, 0]}, {'FZ', [0, 0, 0, 0, 0, 0, 0, 0]}, {'PL', [0, 0, 0, 0, 0, 0, 0, 0]}, {'LP', [0, 0, 0, 0, 0, 0, 0, 0]}, {'SP', [0, 0, 0, 0, 0, 0, 0, 0]}, {'TS', [0, 0, 0, 0, 0, 0, 0, 0]}, {'LM', [0, 0, 0, 0, 0, 0, 0, 0]}, {'TK', [0, 0, 0, 0, 0, 0, 0, 0]}, {'AX', [0, 0, 0, 0, 0, 0, 0, 0]}, {'AB', [0, 0, 0, 0, 0, 0, 0, 0]}]"); // --> does not work, no key found.
        
        // GVariant *v = g_variant_new_parsed ("@a{sau} {'AC': [0, 0, 0, 0, 0, 0, 0, 0], 'IV': [0, 0, 0, 0, 0, 0, 0, 0], 'FZ': [0, 0, 0, 0, 0, 0, 0, 0], 'PL': [0, 0, 0, 0, 0, 0, 0, 0]}"); // --> this does not work, no key found

        GVariant *v = g_variant_new_parsed ("@a{sv} {'AC': <[1, 2, 3, 4, 5, 6, 7, 8]>, 'IV': <[2, 4, 8, 16, 32, 64, 128, 256]>, 'FZ': <[0, 1, 0, 1, 0, 1, 0, 99]>, 'PL': <[0, 0, 0, 0, 0, 0, 0, 0]>}"); // --> only this works, but how to specify data to be 'au' and NOT 'ai' ??

        g_print ("Type is '%s'\n", g_variant_get_type (v));
                    
        g_print ("DSPControl::get_tab_settings -- creating test dict instead of 'probe-tab-options' from schema\n");
        GVariantDict *dict = g_variant_dict_new (v);

        if (!dict){
                g_print ("ERROR: DSPControl::get_tab_settings -- can't read dictionary 'probe-tab-options' a{sai}.\n");
                return;
        }
        if (!g_variant_dict_contains (dict, tab_key)){
                g_print ("ERROR: DSPControl::get_tab_settings -- can't find key '%s' in dict 'probe-tab-options'.\n", tab_key);
                return;
        }
        g_print ("DSPControl::get_tab_settings -- key '%s' found in dict 'probe-tab-options' :)\n", tab_key);

        GVariant *value = g_variant_dict_lookup_value (dict, tab_key, ((const GVariantType *) "au"));
        if (!value){
                g_print ("ERROR: DSPControl::get_tab_settings -- can't get array 'au' data from key '%s' in 'probe-tab-options' dictionary.\n", tab_key);
                
                value = g_variant_dict_lookup_value (dict, tab_key, ((const GVariantType *) "ai"));
                if (!value){
                        g_print ("ERROR: DSPControl::get_tab_settings -- can't get array 'ai' data from key '%s' in 'probe-tab-options' dictionary.\n", tab_key);

                        g_print ("DSPControl::get_tab_settings -- trying to unbox variant first...\n");

                        GVariant *variant = g_variant_dict_lookup_value (dict, tab_key, G_VARIANT_TYPE_VARIANT);
                        if (!variant){
                                g_print ("ERROR: DSPControl::get_tab_settings -- can't unbox variant from key '%s' in 'probe-tab-options' dictionary.\n", tab_key);
                                g_variant_dict_unref (dict);
                                g_print ("ERROR: DSPControl::get_tab_settings -- all unpack attempts for '%s' failed.\n", tab_key);
                                return;
                        } else g_print ("DSPControl::get_tab_settings -- key '%s' found variant box :)\n", tab_key);
                        value = g_variant_get_variant (variant);
                        if (value) g_print ("DSPControl::get_tab_settings -- key '%s' unboxed variant from box :)\n", tab_key);
                } else g_print ("DSPControl::get_tab_settings -- key '%s' found array 'ai' :)\n", tab_key);
        } else g_print ("DSPControl::get_tab_settings -- key '%s' found array 'au' :)\n", tab_key);
        
        if (value){
                guint32  *ai = NULL;
                gsize   ni;
                
                ai = (guint32*) g_variant_get_fixed_array (value, &ni, sizeof (guint32));
                g_assert_cmpint (ni, ==, 8);

                g_print ("[");
                for (int i=0; i<ni; ++i)
                        g_print ("%u, ", ai[i]);
                g_print ("]\n");

                option_flags = ai[0];
                auto_flags = ai[1];
      
                for (int i=0; i<6; ++i)
                        glock_data [i] = ai[i+2];

                // must free data for ourselves
                g_variant_unref (value);
        } else {
                g_print ("ERROR: DSPControl::get_tab_settings -- cant get array 'au' from key '%s' in 'probe-tab-options' dictionary.\n", tab_key);
        }

        GVariant *vto = g_variant_dict_end (dict);

        // testing storing
        if (vto)
                g_print ("DSPControl::get_tab_settings -- stored tab-setings dict to variant OK.\n");
        else
                g_print ("ERROR DSPControl::get_tab_settings -- store tab-setings dict to variant failed.\n");
        
        if (g_settings_is_writable (hwi_settings, "probe-tab-options"))
                g_print ("DSPControl::get_tab_settings -- is writable\n");
        else
                g_print ("WARNING/ERROR DSPControl::get_tab_settings -- is NOT writable\n"); // this fails here, but because the type is not matching I assume
        
        if (g_settings_set_value (hwi_settings, "probe-tab-options", vto))
                g_print ("DSPControl::get_tab_settings -- update probe-tab-options dict OK\n");
        else
                g_print ("ERROR DSPControl::get_tab_settings -- update probe-tab-options dict failed.\n");
        
        g_variant_dict_unref (dict);
        g_variant_unref (vto);
}
Comment 1 Matthias Clasen 2016-09-26 10:28:42 UTC
Your problem is that GVariantDict only works with a{sv}. Your key has type a{asau}, which is different.

You should see a warning like this when running your code:

GLib-CRITICAL **: the GVariant format string '{sv}' has a type of '{sv}' but the given value has a type of '{sau}'
Comment 2 Percy 2016-09-26 12:14:21 UTC
Yes, thank you, I must have missed the warning but figured that already via try and error.

I have this in my schema

<key name="probe-tab-options" type="a{sau}">
     <default>{
      "AC": [0,0, 0,0,0,0,0,0],
   ...
</key>

and would need some thing like (where v is of type au) to make GVariantDict happy.

<key name="probe-tab-options" type="a{sv}">  
     <default>{
      "AC": <[0,0, 0,0,0,0,0,0]>,
   ...
</key>


I tried that, not accepted by glib compile. I tried also type="a{s@au}". No luck and very hard to find details about. IF you have a solution on how I make be able to make sue of the GVariantDic utilities that I would very much appreciate. Else I's have to write my own code to do pretty much the same job.
Comment 3 Percy 2016-09-28 23:19:27 UTC
FYI:

The bug or problem is that I only can define a empty default in my gschema like this -- what then works fine with GVariantDict.

<key name="probe-tab-options" type="a{sv}">
     <default>{}</default>
...
</key>

the gschema xml file does not allow (the install/check fails if I try) to define any variant values using in my gschema.xml file -- the <> seam ti interfere with xml parsing?!?!?:

<default>{'AC': <@at [0,0,0,0,0,0,0,0]>,<[...]>,... }</default> 

While I can in my code successfully parse this:

GVariant *v_default = g_variant_new_parsed ("@a{sv} {'AC': <@at [1,2,3,0,0,0,0,18446744073709551615]>,...}");

to first time initialize my values what is not my work around.
And finally store it to my key in gsettings.

best
-Percy