hook gvariant vectors up to kdbus
[platform/upstream/glib.git] / gio / gsettings-mapping.c
1 /*
2  * Copyright © 2010 Novell, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the licence, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16  *
17  * Author: Vincent Untz <vuntz@gnome.org>
18  */
19
20 #include "config.h"
21
22 #include "gsettings-mapping.h"
23
24 static GVariant *
25 g_settings_set_mapping_int (const GValue       *value,
26                             const GVariantType *expected_type)
27 {
28   GVariant *variant = NULL;
29   gint64 l;
30
31   if (G_VALUE_HOLDS_INT (value))
32     l = g_value_get_int (value);
33   else if (G_VALUE_HOLDS_INT64 (value))
34     l = g_value_get_int64 (value);
35   else
36     return NULL;
37
38   if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT16))
39     {
40       if (G_MININT16 <= l && l <= G_MAXINT16)
41         variant = g_variant_new_int16 ((gint16) l);
42     }
43   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT16))
44     {
45       if (0 <= l && l <= G_MAXUINT16)
46         variant = g_variant_new_uint16 ((guint16) l);
47     }
48   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT32))
49     {
50       if (G_MININT32 <= l && l <= G_MAXINT32)
51         variant = g_variant_new_int32 ((gint) l);
52     }
53   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT32))
54     {
55       if (0 <= l && l <= G_MAXUINT32)
56         variant = g_variant_new_uint32 ((guint) l);
57     }
58   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT64))
59     {
60       if (G_MININT64 <= l && l <= G_MAXINT64)
61         variant = g_variant_new_int64 ((gint64) l);
62     }
63   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64))
64     {
65       if (0 <= l && l <= G_MAXUINT64)
66         variant = g_variant_new_uint64 ((guint64) l);
67     }
68   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE))
69     {
70       if (0 <= l && l <= G_MAXUINT32)
71         variant = g_variant_new_handle ((guint) l);
72     }
73   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE))
74     variant = g_variant_new_double ((gdouble) l);
75
76   return variant;
77 }
78
79 static GVariant *
80 g_settings_set_mapping_float (const GValue       *value,
81                               const GVariantType *expected_type)
82 {
83   GVariant *variant = NULL;
84   gdouble d;
85   gint64 l;
86
87   if (G_VALUE_HOLDS_DOUBLE (value))
88     d = g_value_get_double (value);
89   else
90     return NULL;
91
92   l = (gint64) d;
93   if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT16))
94     {
95       if (G_MININT16 <= l && l <= G_MAXINT16)
96         variant = g_variant_new_int16 ((gint16) l);
97     }
98   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT16))
99     {
100       if (0 <= l && l <= G_MAXUINT16)
101         variant = g_variant_new_uint16 ((guint16) l);
102     }
103   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT32))
104     {
105       if (G_MININT32 <= l && l <= G_MAXINT32)
106         variant = g_variant_new_int32 ((gint) l);
107     }
108   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT32))
109     {
110       if (0 <= l && l <= G_MAXUINT32)
111         variant = g_variant_new_uint32 ((guint) l);
112     }
113   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT64))
114     {
115       if (G_MININT64 <= l && l <= G_MAXINT64)
116         variant = g_variant_new_int64 ((gint64) l);
117     }
118   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64))
119     {
120       if (0 <= l && l <= G_MAXUINT64)
121         variant = g_variant_new_uint64 ((guint64) l);
122     }
123   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE))
124     {
125       if (0 <= l && l <= G_MAXUINT32)
126         variant = g_variant_new_handle ((guint) l);
127     }
128   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE))
129     variant = g_variant_new_double ((gdouble) d);
130
131   return variant;
132 }
133 static GVariant *
134 g_settings_set_mapping_unsigned_int (const GValue       *value,
135                                      const GVariantType *expected_type)
136 {
137   GVariant *variant = NULL;
138   guint64 u;
139
140   if (G_VALUE_HOLDS_UINT (value))
141     u = g_value_get_uint (value);
142   else if (G_VALUE_HOLDS_UINT64 (value))
143     u = g_value_get_uint64 (value);
144   else
145     return NULL;
146
147   if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT16))
148     {
149       if (u <= G_MAXINT16)
150         variant = g_variant_new_int16 ((gint16) u);
151     }
152   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT16))
153     {
154       if (u <= G_MAXUINT16)
155         variant = g_variant_new_uint16 ((guint16) u);
156     }
157   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT32))
158     {
159       if (u <= G_MAXINT32)
160         variant = g_variant_new_int32 ((gint) u);
161     }
162   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT32))
163     {
164       if (u <= G_MAXUINT32)
165         variant = g_variant_new_uint32 ((guint) u);
166     }
167   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT64))
168     {
169       if (u <= G_MAXINT64)
170         variant = g_variant_new_int64 ((gint64) u);
171     }
172   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64))
173     {
174       if (u <= G_MAXUINT64)
175         variant = g_variant_new_uint64 ((guint64) u);
176     }
177   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE))
178     {
179       if (u <= G_MAXUINT32)
180         variant = g_variant_new_handle ((guint) u);
181     }
182   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE))
183     variant = g_variant_new_double ((gdouble) u);
184
185   return variant;
186 }
187
188 static gboolean
189 g_settings_get_mapping_int (GValue   *value,
190                             GVariant *variant)
191 {
192   const GVariantType *type;
193   gint64 l;
194
195   type = g_variant_get_type (variant);
196
197   if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
198     l = g_variant_get_int16 (variant);
199   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
200     l = g_variant_get_int32 (variant);
201   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
202     l = g_variant_get_int64 (variant);
203   else
204     return FALSE;
205
206   if (G_VALUE_HOLDS_INT (value))
207     {
208       g_value_set_int (value, l);
209       return (G_MININT32 <= l && l <= G_MAXINT32);
210     }
211   else if (G_VALUE_HOLDS_UINT (value))
212     {
213       g_value_set_uint (value, l);
214       return (0 <= l && l <= G_MAXUINT32);
215     }
216   else if (G_VALUE_HOLDS_INT64 (value))
217     {
218       g_value_set_int64 (value, l);
219       return (G_MININT64 <= l && l <= G_MAXINT64);
220     }
221   else if (G_VALUE_HOLDS_UINT64 (value))
222     {
223       g_value_set_uint64 (value, l);
224       return (0 <= l && l <= G_MAXUINT64);
225     }
226   else if (G_VALUE_HOLDS_DOUBLE (value))
227     {
228       g_value_set_double (value, l);
229       return TRUE;
230     }
231
232   return FALSE;
233 }
234
235 static gboolean
236 g_settings_get_mapping_float (GValue   *value,
237                               GVariant *variant)
238 {
239   const GVariantType *type;
240   gdouble d;
241   gint64 l;
242
243   type = g_variant_get_type (variant);
244
245   if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
246     d = g_variant_get_double (variant);
247   else
248     return FALSE;
249
250   l = (gint64)d;
251   if (G_VALUE_HOLDS_INT (value))
252     {
253       g_value_set_int (value, l);
254       return (G_MININT32 <= l && l <= G_MAXINT32);
255     }
256   else if (G_VALUE_HOLDS_UINT (value))
257     {
258       g_value_set_uint (value, l);
259       return (0 <= l && l <= G_MAXUINT32);
260     }
261   else if (G_VALUE_HOLDS_INT64 (value))
262     {
263       g_value_set_int64 (value, l);
264       return (G_MININT64 <= l && l <= G_MAXINT64);
265     }
266   else if (G_VALUE_HOLDS_UINT64 (value))
267     {
268       g_value_set_uint64 (value, l);
269       return (0 <= l && l <= G_MAXUINT64);
270     }
271   else if (G_VALUE_HOLDS_DOUBLE (value))
272     {
273       g_value_set_double (value, d);
274       return TRUE;
275     }
276
277   return FALSE;
278 }
279 static gboolean
280 g_settings_get_mapping_unsigned_int (GValue   *value,
281                                      GVariant *variant)
282 {
283   const GVariantType *type;
284   guint64 u;
285
286   type = g_variant_get_type (variant);
287
288   if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
289     u = g_variant_get_uint16 (variant);
290   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
291     u = g_variant_get_uint32 (variant);
292   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
293     u = g_variant_get_uint64 (variant);
294   else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
295     u = g_variant_get_handle (variant);
296   else
297     return FALSE;
298
299   if (G_VALUE_HOLDS_INT (value))
300     {
301       g_value_set_int (value, u);
302       return (u <= G_MAXINT32);
303     }
304   else if (G_VALUE_HOLDS_UINT (value))
305     {
306       g_value_set_uint (value, u);
307       return (u <= G_MAXUINT32);
308     }
309   else if (G_VALUE_HOLDS_INT64 (value))
310     {
311       g_value_set_int64 (value, u);
312       return (u <= G_MAXINT64);
313     }
314   else if (G_VALUE_HOLDS_UINT64 (value))
315     {
316       g_value_set_uint64 (value, u);
317       return (u <= G_MAXUINT64);
318     }
319   else if (G_VALUE_HOLDS_DOUBLE (value))
320     {
321       g_value_set_double (value, u);
322       return TRUE;
323     }
324
325   return FALSE;
326 }
327
328 GVariant *
329 g_settings_set_mapping (const GValue       *value,
330                         const GVariantType *expected_type,
331                         gpointer            user_data)
332 {
333   gchar *type_string;
334
335   if (G_VALUE_HOLDS_BOOLEAN (value))
336     {
337       if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BOOLEAN))
338         return g_variant_new_boolean (g_value_get_boolean (value));
339     }
340
341   else if (G_VALUE_HOLDS_CHAR (value)  ||
342            G_VALUE_HOLDS_UCHAR (value))
343     {
344       if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BYTE))
345         {
346           if (G_VALUE_HOLDS_CHAR (value))
347             return g_variant_new_byte (g_value_get_schar (value));
348           else
349             return g_variant_new_byte (g_value_get_uchar (value));
350         }
351     }
352
353   else if (G_VALUE_HOLDS_INT (value)   ||
354            G_VALUE_HOLDS_INT64 (value))
355     return g_settings_set_mapping_int (value, expected_type);
356
357   else if (G_VALUE_HOLDS_DOUBLE (value))
358     return g_settings_set_mapping_float (value, expected_type);
359
360   else if (G_VALUE_HOLDS_UINT (value)  ||
361            G_VALUE_HOLDS_UINT64 (value))
362     return g_settings_set_mapping_unsigned_int (value, expected_type);
363
364   else if (G_VALUE_HOLDS_STRING (value))
365     {
366       if (g_value_get_string (value) == NULL)
367         return NULL;
368       else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_STRING))
369         return g_variant_new_string (g_value_get_string (value));
370       else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BYTESTRING))
371         return g_variant_new_bytestring (g_value_get_string (value));
372       else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_OBJECT_PATH))
373         return g_variant_new_object_path (g_value_get_string (value));
374       else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_SIGNATURE))
375         return g_variant_new_signature (g_value_get_string (value));
376     }
377
378   else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
379     {
380       if (g_value_get_boxed (value) == NULL)
381         return NULL;
382       return g_variant_new_strv ((const gchar **) g_value_get_boxed (value),
383                                  -1);
384     }
385
386   else if (G_VALUE_HOLDS_ENUM (value))
387     {
388       GEnumValue *enumval;
389       GEnumClass *eclass;
390
391       /* GParamSpecEnum holds a ref on the class so we just peek... */
392       eclass = g_type_class_peek (G_VALUE_TYPE (value));
393       enumval = g_enum_get_value (eclass, g_value_get_enum (value));
394
395       if (enumval)
396         return g_variant_new_string (enumval->value_nick);
397       else
398         return NULL;
399     }
400
401   else if (G_VALUE_HOLDS_FLAGS (value))
402     {
403       GVariantBuilder builder;
404       GFlagsValue *flagsval;
405       GFlagsClass *fclass;
406       guint flags;
407
408       fclass = g_type_class_peek (G_VALUE_TYPE (value));
409       flags = g_value_get_flags (value);
410
411       g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
412       while (flags)
413         {
414           flagsval = g_flags_get_first_value (fclass, flags);
415
416           if (flagsval == NULL)
417             {
418               g_variant_builder_clear (&builder);
419               return NULL;
420             }
421
422           g_variant_builder_add (&builder, "s", flagsval->value_nick);
423           flags &= ~flagsval->value;
424         }
425
426       return g_variant_builder_end (&builder);
427     }
428
429   type_string = g_variant_type_dup_string (expected_type);
430   g_critical ("No GSettings bind handler for type \"%s\".", type_string);
431   g_free (type_string);
432
433   return NULL;
434 }
435
436 gboolean
437 g_settings_get_mapping (GValue   *value,
438                         GVariant *variant,
439                         gpointer  user_data)
440 {
441   if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN))
442     {
443       if (!G_VALUE_HOLDS_BOOLEAN (value))
444         return FALSE;
445       g_value_set_boolean (value, g_variant_get_boolean (variant));
446       return TRUE;
447     }
448
449   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BYTE))
450     {
451       if (G_VALUE_HOLDS_UCHAR (value))
452         g_value_set_uchar (value, g_variant_get_byte (variant));
453       else if (G_VALUE_HOLDS_CHAR (value))
454         g_value_set_schar (value, (gint8)g_variant_get_byte (variant));
455       else
456         return FALSE;
457       return TRUE;
458     }
459
460   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT16)  ||
461            g_variant_is_of_type (variant, G_VARIANT_TYPE_INT32)  ||
462            g_variant_is_of_type (variant, G_VARIANT_TYPE_INT64))
463     return g_settings_get_mapping_int (value, variant);
464
465   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_DOUBLE))
466     return g_settings_get_mapping_float (value, variant);
467
468   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT16) ||
469            g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32) ||
470            g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT64) ||
471            g_variant_is_of_type (variant, G_VARIANT_TYPE_HANDLE))
472     return g_settings_get_mapping_unsigned_int (value, variant);
473
474   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)      ||
475            g_variant_is_of_type (variant, G_VARIANT_TYPE_OBJECT_PATH) ||
476            g_variant_is_of_type (variant, G_VARIANT_TYPE_SIGNATURE))
477     {
478       if (G_VALUE_HOLDS_STRING (value))
479         {
480           g_value_set_string (value, g_variant_get_string (variant, NULL));
481           return TRUE;
482         }
483
484       else if (G_VALUE_HOLDS_ENUM (value))
485         {
486           GEnumClass *eclass;
487           GEnumValue *evalue;
488           const gchar *nick;
489
490           /* GParamSpecEnum holds a ref on the class so we just peek... */
491           eclass = g_type_class_peek (G_VALUE_TYPE (value));
492           nick = g_variant_get_string (variant, NULL);
493           evalue = g_enum_get_value_by_nick (eclass, nick);
494
495           if (evalue)
496             {
497              g_value_set_enum (value, evalue->value);
498              return TRUE;
499             }
500
501           g_warning ("Unable to lookup enum nick '%s' via GType\n", nick);
502           return FALSE;
503         }
504     }
505   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE ("as")))
506     {
507       if (G_VALUE_HOLDS (value, G_TYPE_STRV))
508         {
509           g_value_take_boxed (value, g_variant_dup_strv (variant, NULL));
510           return TRUE;
511         }
512
513       else if (G_VALUE_HOLDS_FLAGS (value))
514         {
515           GFlagsClass *fclass;
516           GFlagsValue *fvalue;
517           const gchar *nick;
518           GVariantIter iter;
519           guint flags = 0;
520
521           fclass = g_type_class_peek (G_VALUE_TYPE (value));
522
523           g_variant_iter_init (&iter, variant);
524           while (g_variant_iter_next (&iter, "&s", &nick))
525             {
526               fvalue = g_flags_get_value_by_nick (fclass, nick);
527
528               if (fvalue)
529                 flags |= fvalue->value;
530
531               else
532                 {
533                   g_warning ("Unable to lookup flags nick '%s' via GType\n",
534                              nick);
535                   return FALSE;
536                 }
537             }
538
539           g_value_set_flags (value, flags);
540           return TRUE;
541         }
542     }
543   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BYTESTRING))
544     {
545       g_value_set_string (value, g_variant_get_bytestring (variant));
546       return TRUE;
547     }
548
549   g_critical ("No GSettings bind handler for type \"%s\".",
550               g_variant_get_type_string (variant));
551
552   return FALSE;
553 }
554
555 gboolean
556 g_settings_mapping_is_compatible (GType               gvalue_type,
557                                   const GVariantType *variant_type)
558 {
559   gboolean ok = FALSE;
560
561   if (gvalue_type == G_TYPE_BOOLEAN)
562     ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_BOOLEAN);
563   else if (gvalue_type == G_TYPE_CHAR  ||
564            gvalue_type == G_TYPE_UCHAR)
565     ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_BYTE);
566   else if (gvalue_type == G_TYPE_INT    ||
567            gvalue_type == G_TYPE_UINT   ||
568            gvalue_type == G_TYPE_INT64  ||
569            gvalue_type == G_TYPE_UINT64 ||
570            gvalue_type == G_TYPE_DOUBLE)
571     ok = (g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT16)  ||
572           g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT16) ||
573           g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT32)  ||
574           g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT32) ||
575           g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT64)  ||
576           g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT64) ||
577           g_variant_type_equal (variant_type, G_VARIANT_TYPE_HANDLE) ||
578           g_variant_type_equal (variant_type, G_VARIANT_TYPE_DOUBLE));
579   else if (gvalue_type == G_TYPE_STRING)
580     ok = (g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING)      ||
581           g_variant_type_equal (variant_type, G_VARIANT_TYPE ("ay")) ||
582           g_variant_type_equal (variant_type, G_VARIANT_TYPE_OBJECT_PATH) ||
583           g_variant_type_equal (variant_type, G_VARIANT_TYPE_SIGNATURE));
584   else if (gvalue_type == G_TYPE_STRV)
585     ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE ("as"));
586   else if (G_TYPE_IS_ENUM (gvalue_type))
587     ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING);
588   else if (G_TYPE_IS_FLAGS (gvalue_type))
589     ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE ("as"));
590
591   return ok;
592 }