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