8ec88c38e69ed583669be4b8d2d0dd47c8136246
[profile/ivi/gsignond.git] / src / common / gsignond-dictionary.c
1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4  * This file is part of gsignond
5  *
6  * Copyright (C) 2012-2013 Intel Corporation.
7  *
8  * Contact: Alexander Kanavin <alex.kanavin@gmail.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23  * 02110-1301 USA
24  */
25
26 #include <gsignond/gsignond-dictionary.h>
27 #include <gsignond/gsignond-log.h>
28
29 /**
30  * SECTION:gsignond-dictionary
31  * @short_description: a dictionary container holding string keys and variant values
32  * @title: GSignondDictionary
33  * @include: gsignond/gsignond-dictionary.h
34  *
35  * A #GSignondDictionary is a dictionary data structure that maps string keys to #GVariant values.
36  * It's used in multiple places in gsignond and its public API to pass key-value
37  * data sets.
38  * 
39  * |[    GSignondDictionary* dict = gsignond_dictionary_new();
40  *     gsignond_dictionary_set_string(dict, "name", "John Smith");
41  *     gsignond_dictionary_set_uint32(dict, "age", 32);
42  *
43  *     guint32 age;
44  *     gboolean success = gsignond_dictionary_get_uint32(dict, "age", &age);
45  *     const gchar* name = gsignond_dictionary_get_string(dict, "name");
46  *     gsignond_dictionary_unref(dict);
47  * ]| 
48  */
49
50 /**
51  * GSignondDictionary:
52  * 
53  * #GSignondDictionary is a typedef for #GHashTable, which 
54  * means the developers may also use methods associated with that structure.
55  */
56
57 /**
58  * gsignond_dictionary_new_from_variant:
59  * @variant: instance of #GVariant
60  *
61  * Converts the #GVariant to #GSignondDictionary. This is useful for example if 
62  * the dictionary needs to be deserialized, or if it's contained in another 
63  * #GSignondDictionary and has been retrieved using gsignond_dictionary_get().
64  *
65  * Returns: (transfer full): #GSignondDictionary if successful, NULL otherwise.
66  */
67 GSignondDictionary *
68 gsignond_dictionary_new_from_variant (GVariant *variant)
69 {
70     GSignondDictionary *dict = NULL;
71     GVariantIter iter;
72     gchar *key = NULL;
73     GVariant *value = NULL;
74
75     g_return_val_if_fail (variant != NULL, NULL);
76
77     dict = gsignond_dictionary_new ();
78     g_variant_iter_init (&iter, variant);
79     while (g_variant_iter_next (&iter, "{sv}", &key, &value))
80     {
81         g_hash_table_insert (dict, key, value);
82     }
83
84     return dict;
85 }
86
87 /**
88  * gsignond_dictionary_to_variant:
89  * @dict: instance of #GSignondDictionary
90  *
91  * Converts the #GSignondDictionary to a #GVariant. The result can be serialized
92  * or put into another #GSignondDictionary using gsignond_dictionary_set().
93  *
94  * Returns: (transfer full): #GVariant object if successful, NULL otherwise.
95  */
96 GVariant *
97 gsignond_dictionary_to_variant (GSignondDictionary *dict)
98 {
99     GVariantBuilder builder;
100     GHashTableIter iter;
101     GVariant *vdict = NULL;
102     const gchar *key = NULL;
103     GVariant *value = NULL;
104
105     g_return_val_if_fail (dict != NULL, NULL);
106
107     g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
108     g_hash_table_iter_init (&iter, dict);
109     while (g_hash_table_iter_next (&iter,
110                                    (gpointer)&key,
111                                    (gpointer)&value))
112     {
113         g_variant_builder_add (&builder, "{sv}",
114                                key,
115                                value);
116     }
117     vdict = g_variant_builder_end (&builder);
118     return vdict;
119 }
120
121 /**
122  * gsignond_dictionary_new:
123  *
124  * Creates a new instance of #GSignondDictionary.
125  *
126  * Returns: (transfer full): #GSignondDictionary object if successful,
127  * NULL otherwise.
128  */
129 GSignondDictionary *
130 gsignond_dictionary_new (void)
131 {
132     return g_hash_table_new_full ((GHashFunc)g_str_hash,
133                             (GEqualFunc)g_str_equal,
134                             (GDestroyNotify)g_free,
135                             (GDestroyNotify)g_variant_unref);
136 }
137
138 /**
139  * gsignond_dictionary_ref:
140  * @dict: instance of #GSignondDictionary
141  *
142  * Increments the reference count of the dictionary structure.
143  * 
144  * Returns: the pointer to the passed in #GSignondDictionary
145  */
146 GSignondDictionary*
147 gsignond_dictionary_ref (GSignondDictionary *dict)
148 {
149     g_return_val_if_fail (dict != NULL, NULL);
150
151     return (GSignondDictionary*)g_hash_table_ref (dict);
152 }
153
154 /**
155  * gsignond_dictionary_unref:
156  * @dict: instance of #GSignondDictionary
157  *
158  * Decrements the reference count of the dictionary structure. If the reference
159  * count reaches zero, the structure is deallocated and shouldn't be used.
160  *
161  */
162 void
163 gsignond_dictionary_unref (GSignondDictionary *dict)
164 {
165     if (!dict)
166         return;
167
168     g_hash_table_unref (dict);
169 }
170
171 /**
172  * gsignond_dictionary_get:
173  * @dict: instance of #GSignondDictionary
174  * @key: the key to look up in the dictionary
175  *
176  * Retrieves a #GVariant value from the dictionary. This can be used to retrieve
177  * a value of an arbitrary type, and then convert it manually to a specific type
178  * using #GVariant methods. For most commonly used types, also getters that
179  * return the specific type directly are provided (gsignond_dictionary_get_string()
180  * and similar).
181  *
182  * Returns: (transfer none): the value; NULL is returned in case of failure (for 
183  * example if the entry corresponding to the supplied key doesn't exist).
184  */
185 GVariant *
186 gsignond_dictionary_get (GSignondDictionary *dict, const gchar *key)
187 {
188     g_return_val_if_fail (dict != NULL, NULL);
189     g_return_val_if_fail (key != NULL, NULL);
190
191     return g_hash_table_lookup (dict, key);
192 }
193
194 /**
195  * gsignond_dictionary_set:
196  * @dict: instance of #GSignondDictionary
197  * @key: (transfer none): key to be set
198  * @value: (transfer full): value to be set
199  *
200  * Adds or replaces key-value pair in the dictionary. This allows to set a value
201  * of an arbitrary type: it first needs to be converted to a #GVariant. For most
202  * commonly used types also type-specific setters are provided.
203  *
204  * Returns: TRUE if successful, FALSE otherwise.
205  */
206 gboolean
207 gsignond_dictionary_set (GSignondDictionary *dict, 
208     const gchar *key, GVariant *value)
209 {
210     g_return_val_if_fail (dict != NULL, FALSE);
211     g_return_val_if_fail (key != NULL, FALSE);
212     g_return_val_if_fail (value != NULL, FALSE);
213
214     g_variant_ref_sink(value);
215     g_hash_table_replace (
216             dict,
217             g_strdup(key),
218             value);
219
220     return TRUE;
221 }
222
223 /**
224  * gsignond_dictionary_get_boolean:
225  * @dict: instance of #GSignondDictionary
226  * @key: (transfer none): key to look up
227  * @value: points to the location where the value should be set
228  *
229  * Retrieves a gboolean value.
230  *
231  * Returns: TRUE if the value was retrieved successfully, FALSE otherwise.
232  */
233 gboolean
234 gsignond_dictionary_get_boolean (GSignondDictionary *dict, const gchar *key,
235                                  gboolean *value)
236 {
237     GVariant *variant = gsignond_dictionary_get (dict, key);
238
239     if (variant == NULL)
240         return FALSE;
241
242     if (value)
243         *value = g_variant_get_boolean (variant);
244     return TRUE;
245 }
246
247 /**
248  * gsignond_dictionary_set_boolean:
249  * @dict: instance of #GSignondDictionary
250  * @key: (transfer none): key to set
251  * @value: value to set
252  *
253  * Sets or replaces a gboolean value in the dictionary.
254  * 
255  * Returns: TRUE if the value was set or replaced successfully, FALSE otherwise.
256  */
257 gboolean
258 gsignond_dictionary_set_boolean (GSignondDictionary *dict, const gchar *key,
259                                  gboolean value)
260 {
261     return gsignond_dictionary_set (dict, key, g_variant_new_boolean (value));
262 }
263
264 /**
265  * gsignond_dictionary_get_int32:
266  * @dict: instance of #GSignondDictionary
267  * @key: (transfer none): key to look up
268  * @value: points to the location where the value should be set
269  *
270  * Retrieves a int32 value.
271  * 
272  * Returns: TRUE if the value was retrieved successfully, FALSE otherwise.
273  */
274 gboolean
275 gsignond_dictionary_get_int32 (GSignondDictionary *dict, const gchar *key,
276                                gint32 *value)
277 {
278     GVariant *variant = gsignond_dictionary_get (dict, key);
279
280     if (variant == NULL)
281         return FALSE;
282
283     if (value)
284         *value = g_variant_get_int32 (variant);
285     return TRUE;
286 }
287
288 /**
289  * gsignond_dictionary_set_int32:
290  * @dict: instance of #GSignondDictionary
291  * @key: (transfer none): key to set
292  * @value: value to set
293  *
294  * Sets or replaces a int32 value in the dictionary.
295  * 
296  * Returns: TRUE if the value was set or replaced successfully, FALSE otherwise.
297  */
298 gboolean
299 gsignond_dictionary_set_int32 (GSignondDictionary *dict, const gchar *key,
300                                gint32 value)
301 {
302     return gsignond_dictionary_set (dict, key, g_variant_new_int32 (value));
303 }
304
305 /**
306  * gsignond_dictionary_get_uint32:
307  * @dict: instance of #GSignondDictionary
308  * @key: (transfer none): key to look up
309  * @value: points to the location where the value should be set
310  *
311  * Retrieves a uint32 value.
312  * 
313  * Returns: TRUE if the value was retrieved successfully, FALSE otherwise.
314  */
315 gboolean
316 gsignond_dictionary_get_uint32 (GSignondDictionary *dict, const gchar *key,
317                                 guint32 *value)
318 {
319     GVariant *variant = gsignond_dictionary_get (dict, key);
320
321     if (variant == NULL)
322         return FALSE;
323
324     if (value)
325         *value = g_variant_get_uint32 (variant);
326     return TRUE;
327 }
328
329 /**
330  * gsignond_dictionary_set_uint32:
331  * @dict: instance of #GSignondDictionary
332  * @key: (transfer none): key to set
333  * @value: value to set
334  *
335  * Sets or replaces a uint32 value in the dictionary.
336  * 
337  * Returns: TRUE if the value was set or replaced successfully, FALSE otherwise.
338  */
339 gboolean
340 gsignond_dictionary_set_uint32 (GSignondDictionary *dict, const gchar *key,
341                                 guint32 value)
342 {
343     return gsignond_dictionary_set (dict, key, g_variant_new_uint32 (value));
344 }
345
346 /**
347  * gsignond_dictionary_get_int64:
348  * @dict: instance of #GSignondDictionary
349  * @key: (transfer none): key to look up
350  * @value: points to the location where the value should be set
351  *
352  * Retrieves a int64 value.
353  * 
354  * Returns: TRUE if the value was retrieved successfully, FALSE otherwise.
355  */
356 gboolean
357 gsignond_dictionary_get_int64 (GSignondDictionary *dict, const gchar *key,
358                                gint64 *value)
359 {
360     GVariant *variant = gsignond_dictionary_get (dict, key);
361
362     if (variant == NULL)
363         return FALSE;
364
365     if (value)
366         *value = g_variant_get_int64 (variant);
367     return TRUE;
368 }
369
370 /**
371  * gsignond_dictionary_set_int64:
372  * @dict: instance of #GSignondDictionary
373  * @key: (transfer none): key to set
374  * @value: value to set
375  *
376  * Sets or replaces a int64 value in the dictionary.
377  * 
378  * Returns: TRUE if the value was set or replaced successfully, FALSE otherwise.
379  */
380 gboolean
381 gsignond_dictionary_set_int64 (GSignondDictionary *dict, const gchar *key,
382                                gint64 value)
383 {
384     return gsignond_dictionary_set (dict, key, g_variant_new_int64 (value));
385 }
386
387 /**
388  * gsignond_dictionary_get_uint64:
389  * @dict: instance of #GSignondDictionary
390  * @key: (transfer none): key to look up
391  * @value: points to the location where the value should be set
392  *
393  * Retrieves a uint64 value.
394  * 
395  * Returns: TRUE if the value was retrieved successfully, FALSE otherwise.
396  */
397 gboolean
398 gsignond_dictionary_get_uint64 (GSignondDictionary *dict, const gchar *key,
399                                 guint64 *value)
400 {
401     GVariant *variant = gsignond_dictionary_get (dict, key);
402
403     if (variant == NULL)
404         return FALSE;
405
406     if (value)
407         *value = g_variant_get_uint64 (variant);
408     return TRUE;
409 }
410
411 /**
412  * gsignond_dictionary_set_uint64:
413  * @dict: instance of #GSignondDictionary
414  * @key: (transfer none): key to set
415  * @value: value to set
416  *
417  * Sets or replaces a uint64 value in the dictionary.
418  * 
419  * Returns: TRUE if the value was set or replaced successfully, FALSE otherwise.
420  */
421 gboolean
422 gsignond_dictionary_set_uint64 (GSignondDictionary *dict, const gchar *key,
423                                 guint64 value)
424 {
425     return gsignond_dictionary_set (dict, key, g_variant_new_uint64 (value));
426 }
427
428
429 /**
430  * gsignond_dictionary_get_string:
431  * @dict: instance of #GSignondDictionary
432  * @key: (transfer none): key to look up
433  *
434  * Retrieves a string value.
435  * 
436  * Returns: (transfer none): the value if it was retrieved successfully, NULL otherwise.
437  */
438 const gchar *
439 gsignond_dictionary_get_string (GSignondDictionary *dict, const gchar *key)
440 {
441     GVariant *variant = gsignond_dictionary_get (dict, key);
442
443     if (variant == NULL)
444         return NULL;
445
446     return g_variant_get_string (variant, NULL);
447 }
448
449 /**
450  * gsignond_dictionary_set_string:
451  * @dict: instance of #GSignondDictionary
452  * @key: (transfer none): key to set
453  * @value: (transfer none): value to set
454  *
455  * Sets or replaces a string value in the dictionary.
456  * 
457  * Returns: TRUE if the value was set or replaced successfully, FALSE otherwise.
458  */
459 gboolean
460 gsignond_dictionary_set_string (GSignondDictionary *dict, const gchar *key,
461                                 const gchar *value)
462 {
463     return gsignond_dictionary_set (dict, key, g_variant_new_string (value));
464 }
465
466 /**
467  * gsignond_dictionary_remove:
468  * @dict: instance of #GSignondDictionary
469  * @key: (transfer none): key which needs to be removed from the dictionary
470  *
471  * Removes key-value pair in the dictionary as per key.
472  *
473  * Returns: TRUE if successful, FALSE otherwise.
474  */
475 gboolean
476 gsignond_dictionary_remove (GSignondDictionary *dict, const gchar *key)
477 {
478     g_return_val_if_fail (dict != NULL, FALSE);
479     g_return_val_if_fail (key != NULL, FALSE);
480
481     return g_hash_table_remove (
482             dict,
483             key);
484 }
485
486 /**
487  * gsignond_dictionary_copy:
488  * @other: instance of #GSignondDictionary
489  *
490  * Creates a copy of the dictionary.
491  *
492  * Returns: (transfer full): #GSignondDictionary object if the copy was successful,
493  * NULL otherwise.
494  */
495 GSignondDictionary *
496 gsignond_dictionary_copy (GSignondDictionary *other)
497 {
498     GSignondDictionary *dict = NULL;
499     GHashTableIter iter;
500     gchar *key = NULL;
501     GVariant *value = NULL;
502
503     g_return_val_if_fail (other != NULL, NULL);
504
505     dict = gsignond_dictionary_new ();
506     
507     g_hash_table_iter_init (&iter, other);
508     while (g_hash_table_iter_next (&iter,
509                                    (gpointer)&key,
510                                    (gpointer)&value))
511     {
512         gsignond_dictionary_set (dict, key, value);
513     }
514     
515
516     return dict;
517 }