52a9b218fd51965b9e124d99bf073ced8e6e21cd
[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 ("ay")))
373         return g_variant_new_byte_array (g_value_get_string (value), -1);
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   type_string = g_variant_type_dup_string (expected_type);
396   g_critical ("No GSettings bind handler for type \"%s\".", type_string);
397   g_free (type_string);
398
399   return NULL;
400 }
401
402 gboolean
403 g_settings_get_mapping (GValue   *value,
404                         GVariant *variant,
405                         gpointer  user_data)
406 {
407   if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN))
408     {
409       if (!G_VALUE_HOLDS_BOOLEAN (value))
410         return FALSE;
411       g_value_set_boolean (value, g_variant_get_boolean (variant));
412       return TRUE;
413     }
414
415   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BYTE))
416     {
417       if (G_VALUE_HOLDS_UCHAR (value))
418         g_value_set_uchar (value, g_variant_get_byte (variant));
419       else if (G_VALUE_HOLDS_CHAR (value))
420         g_value_set_char (value, (gchar) g_variant_get_byte (variant));
421       else
422         return FALSE;
423       return TRUE;
424     }
425
426   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT16)  ||
427            g_variant_is_of_type (variant, G_VARIANT_TYPE_INT32)  ||
428            g_variant_is_of_type (variant, G_VARIANT_TYPE_INT64))
429     return g_settings_get_mapping_int (value, variant);
430
431   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_DOUBLE))
432     return g_settings_get_mapping_float (value, variant);
433
434   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT16) ||
435            g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32) ||
436            g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT64) ||
437            g_variant_is_of_type (variant, G_VARIANT_TYPE_HANDLE))
438     return g_settings_get_mapping_unsigned_int (value, variant);
439
440   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)      ||
441            g_variant_is_of_type (variant, G_VARIANT_TYPE_OBJECT_PATH) ||
442            g_variant_is_of_type (variant, G_VARIANT_TYPE_SIGNATURE))
443     {
444       if (G_VALUE_HOLDS_STRING (value))
445         {
446           g_value_set_string (value, g_variant_get_string (variant, NULL));
447           return TRUE;
448         }
449
450       else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING) &&
451                G_VALUE_HOLDS_ENUM (value))
452         {
453           GEnumClass *eclass;
454           GEnumValue *evalue;
455           const gchar *nick;
456
457           /* GParamSpecEnum holds a ref on the class so we just peek... */
458           eclass = g_type_class_peek (G_VALUE_TYPE (value));
459           nick = g_variant_get_string (variant, NULL);
460           evalue = g_enum_get_value_by_nick (eclass, nick);
461
462           if (evalue)
463             {
464              g_value_set_enum (value, evalue->value);
465              return TRUE;
466             }
467
468           g_warning ("Unable to lookup enum nick '%s' via GType\n", nick);
469           return FALSE;
470         }
471     }
472   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE ("ay")))
473     {
474       g_value_set_string (value, g_variant_get_byte_array (variant, NULL));
475       return TRUE;
476     }
477
478   g_critical ("No GSettings bind handler for type \"%s\".",
479               g_variant_get_type_string (variant));
480
481   return FALSE;
482 }
483
484 gboolean
485 g_settings_mapping_is_compatible (GType               gvalue_type,
486                                   const GVariantType *variant_type)
487 {
488   gboolean ok = FALSE;
489
490   if (gvalue_type == G_TYPE_BOOLEAN)
491     ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_BOOLEAN);
492   else if (gvalue_type == G_TYPE_CHAR  ||
493            gvalue_type == G_TYPE_UCHAR)
494     ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_BYTE);
495   else if (gvalue_type == G_TYPE_INT    ||
496            gvalue_type == G_TYPE_UINT   ||
497            gvalue_type == G_TYPE_INT64  ||
498            gvalue_type == G_TYPE_UINT64 ||
499            gvalue_type == G_TYPE_DOUBLE)
500     ok = (g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT16)  ||
501           g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT16) ||
502           g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT32)  ||
503           g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT32) ||
504           g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT64)  ||
505           g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT64) ||
506           g_variant_type_equal (variant_type, G_VARIANT_TYPE_HANDLE) ||
507           g_variant_type_equal (variant_type, G_VARIANT_TYPE_DOUBLE));
508   else if (gvalue_type == G_TYPE_STRING)
509     ok = (g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING)      ||
510           g_variant_type_equal (variant_type, G_VARIANT_TYPE ("ay")) ||
511           g_variant_type_equal (variant_type, G_VARIANT_TYPE_OBJECT_PATH) ||
512           g_variant_type_equal (variant_type, G_VARIANT_TYPE_SIGNATURE));
513   else if (G_TYPE_IS_ENUM (gvalue_type))
514     ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING);
515
516   return ok;
517 }