Update to upstream 1.0.1
[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_builder:
89  * @dict: instance of #GSignondDictionary
90  *
91  * Converts the #GSignondDictionary to a #GVariantBuilder of type 
92  * G_VARIANT_TYPE_VARDICT.
93  *
94  * Caller should use g_variant_builder_unref() on the return value when it is
95  * no longer needed.
96  *
97  * Returns: (transfer full): #GVariantBuilder if successful, NULL otherwise.
98  */
99 GVariantBuilder *
100 gsignond_dictionary_to_variant_builder (GSignondDictionary *dict)
101 {
102     GVariantBuilder *builder;
103     GHashTableIter iter;
104     const gchar *key = NULL;
105     GVariant *value = NULL;
106
107     g_return_val_if_fail (dict != NULL, NULL);
108
109     builder = g_variant_builder_new (G_VARIANT_TYPE_VARDICT);
110
111     g_hash_table_iter_init (&iter, dict);
112     while (g_hash_table_iter_next (&iter, (gpointer)&key, (gpointer)&value))
113     {
114         g_variant_builder_add (builder, "{sv}", key, value);
115     }
116
117     return builder;
118 }
119
120 /**
121  * gsignond_dictionary_to_variant:
122  * @dict: instance of #GSignondDictionary
123  *
124  * Converts the #GSignondDictionary to a #GVariant. The result can be serialized
125  * or put into another #GSignondDictionary using gsignond_dictionary_set().
126  *
127  * Returns: (transfer full): #GVariant object if successful, NULL otherwise.
128  */
129 GVariant *
130 gsignond_dictionary_to_variant (GSignondDictionary *dict)
131 {
132     GVariantBuilder *builder = NULL;
133     GVariant *vdict = NULL;
134
135     g_return_val_if_fail (dict != NULL, NULL);
136
137     builder = gsignond_dictionary_to_variant_builder (dict);
138     if (!builder) return NULL;
139
140     vdict = g_variant_builder_end (builder);
141
142     g_variant_builder_unref (builder);
143
144     return vdict;
145 }
146
147 /**
148  * gsignond_dictionary_new:
149  *
150  * Creates a new instance of #GSignondDictionary.
151  *
152  * Returns: (transfer full): #GSignondDictionary object if successful,
153  * NULL otherwise.
154  */
155 GSignondDictionary *
156 gsignond_dictionary_new (void)
157 {
158     return g_hash_table_new_full ((GHashFunc)g_str_hash,
159                             (GEqualFunc)g_str_equal,
160                             (GDestroyNotify)g_free,
161                             (GDestroyNotify)g_variant_unref);
162 }
163
164 /**
165  * gsignond_dictionary_ref:
166  * @dict: instance of #GSignondDictionary
167  *
168  * Increments the reference count of the dictionary structure.
169  * 
170  * Returns: the pointer to the passed in #GSignondDictionary
171  */
172 GSignondDictionary*
173 gsignond_dictionary_ref (GSignondDictionary *dict)
174 {
175     g_return_val_if_fail (dict != NULL, NULL);
176
177     return (GSignondDictionary*)g_hash_table_ref (dict);
178 }
179
180 /**
181  * gsignond_dictionary_unref:
182  * @dict: instance of #GSignondDictionary
183  *
184  * Decrements the reference count of the dictionary structure. If the reference
185  * count reaches zero, the structure is deallocated and shouldn't be used.
186  *
187  */
188 void
189 gsignond_dictionary_unref (GSignondDictionary *dict)
190 {
191     if (!dict)
192         return;
193
194     g_hash_table_unref (dict);
195 }
196
197 /**
198  * gsignond_dictionary_get:
199  * @dict: instance of #GSignondDictionary
200  * @key: the key to look up in the dictionary
201  *
202  * Retrieves a #GVariant value from the dictionary. This can be used to retrieve
203  * a value of an arbitrary type, and then convert it manually to a specific type
204  * using #GVariant methods. For most commonly used types, also getters that
205  * return the specific type directly are provided (gsignond_dictionary_get_string()
206  * and similar).
207  *
208  * Returns: (transfer none): the value; NULL is returned in case of failure (for 
209  * example if the entry corresponding to the supplied key doesn't exist).
210  */
211 GVariant *
212 gsignond_dictionary_get (GSignondDictionary *dict, const gchar *key)
213 {
214     g_return_val_if_fail (dict != NULL, NULL);
215     g_return_val_if_fail (key != NULL, NULL);
216
217     return g_hash_table_lookup (dict, key);
218 }
219
220 /**
221  * gsignond_dictionary_set:
222  * @dict: instance of #GSignondDictionary
223  * @key: (transfer none): key to be set
224  * @value: (transfer full): value to be set
225  *
226  * Adds or replaces key-value pair in the dictionary. This allows to set a value
227  * of an arbitrary type: it first needs to be converted to a #GVariant. For most
228  * commonly used types also type-specific setters are provided.
229  *
230  * Returns: TRUE if successful, FALSE otherwise.
231  */
232 gboolean
233 gsignond_dictionary_set (GSignondDictionary *dict, 
234     const gchar *key, GVariant *value)
235 {
236     g_return_val_if_fail (dict != NULL, FALSE);
237     g_return_val_if_fail (key != NULL, FALSE);
238     g_return_val_if_fail (value != NULL, FALSE);
239
240     g_variant_ref_sink(value);
241     g_hash_table_replace (
242             dict,
243             g_strdup(key),
244             value);
245
246     return TRUE;
247 }
248
249 /**
250  * gsignond_dictionary_get_boolean:
251  * @dict: instance of #GSignondDictionary
252  * @key: (transfer none): key to look up
253  * @value: points to the location where the value should be set
254  *
255  * Retrieves a gboolean value.
256  *
257  * Returns: TRUE if the value was retrieved successfully, FALSE otherwise.
258  */
259 gboolean
260 gsignond_dictionary_get_boolean (GSignondDictionary *dict, const gchar *key,
261                                  gboolean *value)
262 {
263     GVariant *variant = gsignond_dictionary_get (dict, key);
264
265     if (variant == NULL)
266         return FALSE;
267
268     if (value)
269         *value = g_variant_get_boolean (variant);
270     return TRUE;
271 }
272
273 /**
274  * gsignond_dictionary_set_boolean:
275  * @dict: instance of #GSignondDictionary
276  * @key: (transfer none): key to set
277  * @value: value to set
278  *
279  * Sets or replaces a gboolean value in the dictionary.
280  * 
281  * Returns: TRUE if the value was set or replaced successfully, FALSE otherwise.
282  */
283 gboolean
284 gsignond_dictionary_set_boolean (GSignondDictionary *dict, const gchar *key,
285                                  gboolean value)
286 {
287     return gsignond_dictionary_set (dict, key, g_variant_new_boolean (value));
288 }
289
290 /**
291  * gsignond_dictionary_get_int32:
292  * @dict: instance of #GSignondDictionary
293  * @key: (transfer none): key to look up
294  * @value: points to the location where the value should be set
295  *
296  * Retrieves a int32 value.
297  * 
298  * Returns: TRUE if the value was retrieved successfully, FALSE otherwise.
299  */
300 gboolean
301 gsignond_dictionary_get_int32 (GSignondDictionary *dict, const gchar *key,
302                                gint32 *value)
303 {
304     GVariant *variant = gsignond_dictionary_get (dict, key);
305
306     if (variant == NULL)
307         return FALSE;
308
309     if (value)
310         *value = g_variant_get_int32 (variant);
311     return TRUE;
312 }
313
314 /**
315  * gsignond_dictionary_set_int32:
316  * @dict: instance of #GSignondDictionary
317  * @key: (transfer none): key to set
318  * @value: value to set
319  *
320  * Sets or replaces a int32 value in the dictionary.
321  * 
322  * Returns: TRUE if the value was set or replaced successfully, FALSE otherwise.
323  */
324 gboolean
325 gsignond_dictionary_set_int32 (GSignondDictionary *dict, const gchar *key,
326                                gint32 value)
327 {
328     return gsignond_dictionary_set (dict, key, g_variant_new_int32 (value));
329 }
330
331 /**
332  * gsignond_dictionary_get_uint32:
333  * @dict: instance of #GSignondDictionary
334  * @key: (transfer none): key to look up
335  * @value: points to the location where the value should be set
336  *
337  * Retrieves a uint32 value.
338  * 
339  * Returns: TRUE if the value was retrieved successfully, FALSE otherwise.
340  */
341 gboolean
342 gsignond_dictionary_get_uint32 (GSignondDictionary *dict, const gchar *key,
343                                 guint32 *value)
344 {
345     GVariant *variant = gsignond_dictionary_get (dict, key);
346
347     if (variant == NULL)
348         return FALSE;
349
350     if (value)
351         *value = g_variant_get_uint32 (variant);
352     return TRUE;
353 }
354
355 /**
356  * gsignond_dictionary_set_uint32:
357  * @dict: instance of #GSignondDictionary
358  * @key: (transfer none): key to set
359  * @value: value to set
360  *
361  * Sets or replaces a uint32 value in the dictionary.
362  * 
363  * Returns: TRUE if the value was set or replaced successfully, FALSE otherwise.
364  */
365 gboolean
366 gsignond_dictionary_set_uint32 (GSignondDictionary *dict, const gchar *key,
367                                 guint32 value)
368 {
369     return gsignond_dictionary_set (dict, key, g_variant_new_uint32 (value));
370 }
371
372 /**
373  * gsignond_dictionary_get_int64:
374  * @dict: instance of #GSignondDictionary
375  * @key: (transfer none): key to look up
376  * @value: points to the location where the value should be set
377  *
378  * Retrieves a int64 value.
379  * 
380  * Returns: TRUE if the value was retrieved successfully, FALSE otherwise.
381  */
382 gboolean
383 gsignond_dictionary_get_int64 (GSignondDictionary *dict, const gchar *key,
384                                gint64 *value)
385 {
386     GVariant *variant = gsignond_dictionary_get (dict, key);
387
388     if (variant == NULL)
389         return FALSE;
390
391     if (value)
392         *value = g_variant_get_int64 (variant);
393     return TRUE;
394 }
395
396 /**
397  * gsignond_dictionary_set_int64:
398  * @dict: instance of #GSignondDictionary
399  * @key: (transfer none): key to set
400  * @value: value to set
401  *
402  * Sets or replaces a int64 value in the dictionary.
403  * 
404  * Returns: TRUE if the value was set or replaced successfully, FALSE otherwise.
405  */
406 gboolean
407 gsignond_dictionary_set_int64 (GSignondDictionary *dict, const gchar *key,
408                                gint64 value)
409 {
410     return gsignond_dictionary_set (dict, key, g_variant_new_int64 (value));
411 }
412
413 /**
414  * gsignond_dictionary_get_uint64:
415  * @dict: instance of #GSignondDictionary
416  * @key: (transfer none): key to look up
417  * @value: points to the location where the value should be set
418  *
419  * Retrieves a uint64 value.
420  * 
421  * Returns: TRUE if the value was retrieved successfully, FALSE otherwise.
422  */
423 gboolean
424 gsignond_dictionary_get_uint64 (GSignondDictionary *dict, const gchar *key,
425                                 guint64 *value)
426 {
427     GVariant *variant = gsignond_dictionary_get (dict, key);
428
429     if (variant == NULL)
430         return FALSE;
431
432     if (value)
433         *value = g_variant_get_uint64 (variant);
434     return TRUE;
435 }
436
437 /**
438  * gsignond_dictionary_set_uint64:
439  * @dict: instance of #GSignondDictionary
440  * @key: (transfer none): key to set
441  * @value: value to set
442  *
443  * Sets or replaces a uint64 value in the dictionary.
444  * 
445  * Returns: TRUE if the value was set or replaced successfully, FALSE otherwise.
446  */
447 gboolean
448 gsignond_dictionary_set_uint64 (GSignondDictionary *dict, const gchar *key,
449                                 guint64 value)
450 {
451     return gsignond_dictionary_set (dict, key, g_variant_new_uint64 (value));
452 }
453
454
455 /**
456  * gsignond_dictionary_get_string:
457  * @dict: instance of #GSignondDictionary
458  * @key: (transfer none): key to look up
459  *
460  * Retrieves a string value.
461  * 
462  * Returns: (transfer none): the value if it was retrieved successfully, NULL otherwise.
463  */
464 const gchar *
465 gsignond_dictionary_get_string (GSignondDictionary *dict, const gchar *key)
466 {
467     GVariant *variant = gsignond_dictionary_get (dict, key);
468
469     if (variant == NULL)
470         return NULL;
471
472     return g_variant_get_string (variant, NULL);
473 }
474
475 /**
476  * gsignond_dictionary_set_string:
477  * @dict: instance of #GSignondDictionary
478  * @key: (transfer none): key to set
479  * @value: (transfer none): value to set
480  *
481  * Sets or replaces a string value in the dictionary.
482  * 
483  * Returns: TRUE if the value was set or replaced successfully, FALSE otherwise.
484  */
485 gboolean
486 gsignond_dictionary_set_string (GSignondDictionary *dict, const gchar *key,
487                                 const gchar *value)
488 {
489     return gsignond_dictionary_set (dict, key, g_variant_new_string (value));
490 }
491
492 /**
493  * gsignond_dictionary_remove:
494  * @dict: instance of #GSignondDictionary
495  * @key: (transfer none): key which needs to be removed from the dictionary
496  *
497  * Removes key-value pair in the dictionary as per key.
498  *
499  * Returns: TRUE if successful, FALSE otherwise.
500  */
501 gboolean
502 gsignond_dictionary_remove (GSignondDictionary *dict, const gchar *key)
503 {
504     g_return_val_if_fail (dict != NULL, FALSE);
505     g_return_val_if_fail (key != NULL, FALSE);
506
507     return g_hash_table_remove (
508             dict,
509             key);
510 }
511
512 /**
513  * gsignond_dictionary_copy:
514  * @other: instance of #GSignondDictionary
515  *
516  * Creates a copy of the dictionary.
517  *
518  * Returns: (transfer full): #GSignondDictionary object if the copy was successful,
519  * NULL otherwise.
520  */
521 GSignondDictionary *
522 gsignond_dictionary_copy (GSignondDictionary *other)
523 {
524     GSignondDictionary *dict = NULL;
525     GHashTableIter iter;
526     gchar *key = NULL;
527     GVariant *value = NULL;
528
529     g_return_val_if_fail (other != NULL, NULL);
530
531     dict = gsignond_dictionary_new ();
532     
533     g_hash_table_iter_init (&iter, other);
534     while (g_hash_table_iter_next (&iter,
535                                    (gpointer)&key,
536                                    (gpointer)&value))
537     {
538         gsignond_dictionary_set (dict, key, value);
539     }
540     
541
542     return dict;
543 }
544
545 /**
546  * gsignond_dictionary_contains:
547  * @dict: instance of #GSignondDictionary
548  * @key: (transfer none): key to check
549  *
550  * Checks if the @dict contains @key.
551  *
552  * Returns: TRUE if found, FALSE otherwise.
553  */
554 gboolean
555 gsignond_dictionary_contains (GSignondDictionary *dict,
556                               const gchar *key)
557 {
558     g_return_val_if_fail (dict != NULL, FALSE);
559     g_return_val_if_fail (key != NULL, FALSE);
560
561     return g_hash_table_contains (dict, key);
562 }
563