Merge GSettings tests
[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_numeric (const GValue       *value,
28                                 const GVariantType *expected_type)
29 {
30   GVariant *variant = NULL;
31   glong 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 if (G_VALUE_HOLDS_DOUBLE (value))
38     l = g_value_get_double (value);
39   else
40     return NULL;
41
42   if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT16))
43     {
44       if (G_MININT16 <= l && l <= G_MAXINT16)
45         variant = g_variant_new_int16 ((gint16) l);
46     }
47   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT16))
48     {
49       if (0 <= l && l <= G_MAXUINT16)
50         variant = g_variant_new_uint16 ((guint16) l);
51     }
52   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT32))
53     {
54       if (G_MININT32 <= l && l <= G_MAXINT32)
55         variant = g_variant_new_int32 ((gint) l);
56     }
57   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT32))
58     {
59       if (0 <= l && l <= G_MAXUINT32)
60         variant = g_variant_new_uint32 ((guint) l);
61     }
62   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT64))
63     {
64       if (G_MININT64 <= l && l <= G_MAXINT64)
65         variant = g_variant_new_int64 ((gint64) l);
66     }
67   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64))
68     {
69       if (0 <= l && l <= G_MAXUINT64)
70         variant = g_variant_new_uint64 ((guint64) l);
71     }
72   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE))
73     {
74       if (0 <= l && l <= G_MAXUINT32)
75         variant = g_variant_new_handle ((guint) l);
76     }
77   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE))
78     variant = g_variant_new_double ((double) l);
79
80   return variant;
81 }
82
83 static GVariant *
84 g_settings_set_mapping_unsigned_numeric (const GValue       *value,
85                                          const GVariantType *expected_type)
86 {
87   GVariant *variant = NULL;
88   gulong u;
89
90   if (G_VALUE_HOLDS_UINT (value))
91     u = g_value_get_uint (value);
92   else if (G_VALUE_HOLDS_UINT64 (value))
93     u = g_value_get_uint64 (value);
94   else
95     return NULL;
96
97   if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT16))
98     {
99       if (u <= G_MAXINT16)
100         variant = g_variant_new_int16 ((gint16) u);
101     }
102   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT16))
103     {
104       if (u <= G_MAXUINT16)
105         variant = g_variant_new_uint16 ((guint16) u);
106     }
107   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT32))
108     {
109       if (u <= G_MAXINT32)
110         variant = g_variant_new_int32 ((gint) u);
111     }
112   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT32))
113     {
114       if (u <= G_MAXUINT32)
115         variant = g_variant_new_uint32 ((guint) u);
116     }
117   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT64))
118     {
119       if (u <= G_MAXINT64)
120         variant = g_variant_new_int64 ((gint64) u);
121     }
122   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64))
123     {
124       if (u <= G_MAXUINT64)
125         variant = g_variant_new_uint64 ((guint64) u);
126     }
127   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE))
128     {
129       if (u <= G_MAXUINT32)
130         variant = g_variant_new_handle ((guint) u);
131     }
132   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE))
133     variant = g_variant_new_double ((double) u);
134
135   return variant;
136 }
137
138 static gboolean
139 g_settings_get_mapping_numeric (GValue   *value,
140                                 GVariant *variant)
141 {
142   const GVariantType *type;
143   glong l;
144
145   type = g_variant_get_type (variant);
146
147   if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
148     l = g_variant_get_int16 (variant);
149   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
150     l = g_variant_get_int32 (variant);
151   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
152     l = g_variant_get_int64 (variant);
153   else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
154     l = g_variant_get_double (variant);
155   else
156     return FALSE;
157
158   if (G_VALUE_HOLDS_INT (value))
159     {
160       g_value_set_int (value, l);
161       return (G_MININT32 <= l && l <= G_MAXINT32);
162     }
163   else if (G_VALUE_HOLDS_UINT (value))
164     {
165       g_value_set_uint (value, l);
166       return (0 <= l && l <= G_MAXUINT32);
167     }
168   else if (G_VALUE_HOLDS_INT64 (value))
169     {
170       g_value_set_int64 (value, l);
171       return (G_MININT64 <= l && l <= G_MAXINT64);
172     }
173   else if (G_VALUE_HOLDS_UINT64 (value))
174     {
175       g_value_set_uint64 (value, l);
176       return (0 <= l && l <= G_MAXUINT64);
177     }
178   else if (G_VALUE_HOLDS_DOUBLE (value))
179     {
180       g_value_set_double (value, l);
181       return TRUE;
182     }
183
184   return FALSE;
185 }
186
187 static gboolean
188 g_settings_get_mapping_unsigned_numeric (GValue   *value,
189                                          GVariant *variant)
190 {
191   const GVariantType *type;
192   gulong u;
193
194   type = g_variant_get_type (variant);
195
196   if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
197     u = g_variant_get_uint16 (variant);
198   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
199     u = g_variant_get_uint32 (variant);
200   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
201     u = g_variant_get_uint64 (variant);
202   else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
203     u = g_variant_get_handle (variant);
204   else
205     return FALSE;
206
207   if (G_VALUE_HOLDS_INT (value))
208     {
209       g_value_set_int (value, u);
210       return (u <= G_MAXINT32);
211     }
212   else if (G_VALUE_HOLDS_UINT (value))
213     {
214       g_value_set_uint (value, u);
215       return (u <= G_MAXUINT32);
216     }
217   else if (G_VALUE_HOLDS_INT64 (value))
218     {
219       g_value_set_int64 (value, u);
220       return (u <= G_MAXINT64);
221     }
222   else if (G_VALUE_HOLDS_UINT64 (value))
223     {
224       g_value_set_uint64 (value, u);
225       return (u <= G_MAXUINT64);
226     }
227   else if (G_VALUE_HOLDS_DOUBLE (value))
228     {
229       g_value_set_double (value, u);
230       return TRUE;
231     }
232
233   return FALSE;
234 }
235
236 GVariant *
237 g_settings_set_mapping (const GValue       *value,
238                         const GVariantType *expected_type,
239                         gpointer            user_data)
240 {
241   gchar *type_string;
242
243   if (G_VALUE_HOLDS_BOOLEAN (value))
244     {
245       if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BOOLEAN))
246         return g_variant_new_boolean (g_value_get_boolean (value));
247     }
248
249   else if (G_VALUE_HOLDS_CHAR (value)  ||
250            G_VALUE_HOLDS_UCHAR (value))
251     {
252       if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BYTE))
253         {
254           if (G_VALUE_HOLDS_CHAR (value))
255             return g_variant_new_byte (g_value_get_char (value));
256           else
257             return g_variant_new_byte (g_value_get_uchar (value));
258         }
259     }
260
261   else if (G_VALUE_HOLDS_INT (value)   ||
262            G_VALUE_HOLDS_INT64 (value) ||
263            G_VALUE_HOLDS_DOUBLE (value))
264     return g_settings_set_mapping_numeric (value, expected_type);
265
266   else if (G_VALUE_HOLDS_UINT (value)  ||
267            G_VALUE_HOLDS_UINT64 (value))
268     return g_settings_set_mapping_unsigned_numeric (value, expected_type);
269
270   else if (G_VALUE_HOLDS_STRING (value))
271     {
272       if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_STRING))
273         return g_variant_new_string (g_value_get_string (value));
274       else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_OBJECT_PATH))
275         return g_variant_new_object_path (g_value_get_string (value));
276       else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_SIGNATURE))
277         return g_variant_new_signature (g_value_get_string (value));
278     }
279
280   type_string = g_variant_type_dup_string (expected_type);
281   g_critical ("No GSettings bind handler for type \"%s\".", type_string);
282   g_free (type_string);
283
284   return NULL;
285 }
286
287 gboolean
288 g_settings_get_mapping (GValue   *value,
289                         GVariant *variant,
290                         gpointer  user_data)
291 {
292   if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN))
293     {
294       if (!G_VALUE_HOLDS_BOOLEAN (value))
295         return FALSE;
296       g_value_set_boolean (value, g_variant_get_boolean (variant));
297       return TRUE;
298     }
299
300   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BYTE))
301     {
302       if (G_VALUE_HOLDS_UCHAR (value))
303         g_value_set_uchar (value, g_variant_get_byte (variant));
304       else if (G_VALUE_HOLDS_CHAR (value))
305         g_value_set_char (value, (gchar) g_variant_get_byte (variant));
306       else
307         return FALSE;
308       return TRUE;
309     }
310
311   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT16)  ||
312            g_variant_is_of_type (variant, G_VARIANT_TYPE_INT32)  ||
313            g_variant_is_of_type (variant, G_VARIANT_TYPE_INT64)  ||
314            g_variant_is_of_type (variant, G_VARIANT_TYPE_DOUBLE))
315     return g_settings_get_mapping_numeric (value, variant);
316
317   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT16) ||
318            g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32) ||
319            g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT64) ||
320            g_variant_is_of_type (variant, G_VARIANT_TYPE_HANDLE))
321     return g_settings_get_mapping_unsigned_numeric (value, variant);
322
323   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)      ||
324            g_variant_is_of_type (variant, G_VARIANT_TYPE_OBJECT_PATH) ||
325            g_variant_is_of_type (variant, G_VARIANT_TYPE_SIGNATURE))
326     {
327       g_value_set_string (value, g_variant_get_string (variant, NULL));
328       return TRUE;
329     }
330
331   g_critical ("No GSettings bind handler for type \"%s\".",
332               g_variant_get_type_string (variant));
333
334   return FALSE;
335 }
336
337 gboolean
338 g_settings_mapping_is_compatible (GType               gvalue_type,
339                                   const GVariantType *variant_type)
340 {
341   gboolean ok = FALSE;
342
343   if (gvalue_type == G_TYPE_BOOLEAN)
344     ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_BOOLEAN);
345   else if (gvalue_type == G_TYPE_CHAR  ||
346            gvalue_type == G_TYPE_UCHAR)
347     ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_BYTE);
348   else if (gvalue_type == G_TYPE_INT    ||
349            gvalue_type == G_TYPE_UINT   ||
350            gvalue_type == G_TYPE_INT64  ||
351            gvalue_type == G_TYPE_UINT64 ||
352            gvalue_type == G_TYPE_DOUBLE)
353     ok = (g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT16)  ||
354           g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT16) ||
355           g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT32)  ||
356           g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT32) ||
357           g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT64)  ||
358           g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT64) ||
359           g_variant_type_equal (variant_type, G_VARIANT_TYPE_HANDLE) ||
360           g_variant_type_equal (variant_type, G_VARIANT_TYPE_DOUBLE));
361   else if (gvalue_type == G_TYPE_STRING)
362     ok = (g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING)      ||
363           g_variant_type_equal (variant_type, G_VARIANT_TYPE_OBJECT_PATH) ||
364           g_variant_type_equal (variant_type, G_VARIANT_TYPE_SIGNATURE));
365
366   return ok;
367 }