Git init
[profile/ivi/libsoup2.4.git] / libsoup / soup-value-utils.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-type-utils.c: GValue and GType-related utilities
4  *
5  * Copyright (C) 2007 Red Hat, Inc.
6  */
7
8 #include "soup-value-utils.h"
9
10 #include <string.h>
11
12 /**
13  * SECTION:soup-value-utils
14  * @short_description: #GValue utilities
15  *
16  * These methods are useful for manipulating #GValue<!-- -->s, and in
17  * particular, arrays and hash tables of #GValue<!-- -->s, in a
18  * slightly nicer way than the standard #GValue API.
19  *
20  * They are written for use with soup-xmlrpc, but they also work with
21  * types not used by XML-RPC.
22  **/
23
24 /**
25  * SOUP_VALUE_SETV:
26  * @val: a #GValue
27  * @type: a #GType
28  * @args: #va_list pointing to a value of type @type
29  *
30  * Copies an argument of type @type from @args into @val. @val will
31  * point directly to the value in @args rather than copying it, so you
32  * must g_value_copy() it if you want it to remain valid.
33  **/
34
35 /**
36  * SOUP_VALUE_GETV:
37  * @val: a #GValue
38  * @type: a #GType
39  * @args: #va_list pointing to a value of type pointer-to-@type
40  *
41  * Extracts a value of type @type from @val into @args. The return
42  * value will point to the same data as @val rather than being a copy
43  * of it.
44  **/
45
46 static void
47 soup_value_hash_value_free (gpointer val)
48 {
49         g_value_unset (val);
50         g_free (val);
51 }
52
53 /**
54  * soup_value_hash_new:
55  *
56  * Creates a #GHashTable whose keys are strings and whose values
57  * are #GValue.
58  *
59  * Return value: (element-type utf8 GValue) (transfer full): a new
60  * empty #GHashTable
61  **/
62 GHashTable *
63 soup_value_hash_new (void)
64 {
65         return g_hash_table_new_full (g_str_hash, g_str_equal,
66                                       g_free, soup_value_hash_value_free);
67 }
68
69 static void
70 soup_value_hash_insert_valist (GHashTable *hash, const char *first_key,
71                                va_list args)
72 {
73         const char *key;
74         GType type;
75         GValue value;
76
77         key = first_key;
78         while (key) {
79                 type = va_arg (args, GType);
80                 SOUP_VALUE_SETV (&value, type, args);
81
82                 soup_value_hash_insert_value (hash, key, &value);
83                 key = va_arg (args, const char *);
84         }
85 }
86
87 /**
88  * soup_value_hash_new_with_vals:
89  * @first_key: the key for the first value
90  * @...: the type of @first_key, followed by the value, followed
91  * by additional key/type/value triplets, terminated by %NULL
92  *
93  * Creates a #GHashTable whose keys are strings and whose values
94  * are #GValue, and initializes it with the provided data. As
95  * with soup_value_hash_insert(), the keys and values are copied
96  * rather than being inserted directly.
97  *
98  * Return value: (element-type utf8 GValue) (transfer full): a new
99  * #GHashTable, initialized with the given values
100  **/
101 GHashTable *
102 soup_value_hash_new_with_vals (const char *first_key, ...)
103 {
104         GHashTable *hash = soup_value_hash_new ();
105         va_list args;
106
107         va_start (args, first_key);
108         soup_value_hash_insert_valist (hash, first_key, args);
109         va_end (args);
110
111         return hash;
112 }
113
114 /**
115  * soup_value_hash_insert_value:
116  * @hash: (element-type utf8 GValue): a value hash
117  * @key: the key
118  * @value: a value
119  *
120  * Inserts @value into @hash. (Unlike with g_hash_table_insert(), both
121  * the key and the value are copied).
122  **/
123 void
124 soup_value_hash_insert_value (GHashTable *hash, const char *key, GValue *value)
125 {
126         GValue *copy = g_new0 (GValue, 1);
127
128         g_value_init (copy, G_VALUE_TYPE (value));
129         g_value_copy (value, copy);
130         g_hash_table_insert (hash, g_strdup (key), copy);
131 }
132
133 /**
134  * soup_value_hash_insert:
135  * @hash: (element-type utf8 GValue): a value hash
136  * @key: the key
137  * @type: a #GType
138  * @...: a value of type @type
139  *
140  * Inserts the provided value of type @type into @hash. (Unlike with
141  * g_hash_table_insert(), both the key and the value are copied).
142  **/
143 void
144 soup_value_hash_insert (GHashTable *hash, const char *key, GType type, ...)
145 {
146         va_list args;
147         GValue val;
148
149         va_start (args, type);
150         SOUP_VALUE_SETV (&val, type, args);
151         va_end (args);
152         soup_value_hash_insert_value (hash, key, &val);
153 }
154
155 /**
156  * soup_value_hash_insert_vals:
157  * @hash: (element-type utf8 GValue): a value hash
158  * @first_key: the key for the first value
159  * @...: the type of @first_key, followed by the value, followed
160  * by additional key/type/value triplets, terminated by %NULL
161  *
162  * Inserts the given data into @hash. As with
163  * soup_value_hash_insert(), the keys and values are copied rather
164  * than being inserted directly.
165  **/
166 void
167 soup_value_hash_insert_vals (GHashTable *hash, const char *first_key, ...)
168 {
169         va_list args;
170
171         va_start (args, first_key);
172         soup_value_hash_insert_valist (hash, first_key, args);
173         va_end (args);
174 }
175
176 /**
177  * soup_value_hash_lookup:
178  * @hash: (element-type utf8 GValue): a value hash
179  * @key: the key to look up
180  * @type: a #GType
181  * @...: a value of type pointer-to-@type
182  *
183  * Looks up @key in @hash and stores its value into the provided
184  * location.
185  *
186  * Return value: %TRUE if @hash contained a value with key @key and
187  * type @type, %FALSE if not.
188  **/
189 gboolean
190 soup_value_hash_lookup (GHashTable *hash, const char *key, GType type, ...)
191 {
192         va_list args;
193         GValue *value;
194
195         value = g_hash_table_lookup (hash, key);
196         if (!value || !G_VALUE_HOLDS (value, type))
197                 return FALSE;
198
199         va_start (args, type);
200         SOUP_VALUE_GETV (value, type, args);
201         va_end (args);
202
203         return TRUE;
204 }
205
206 /**
207  * soup_value_hash_lookup_vals:
208  * @hash: (element-type utf8 GValue): a value hash
209  * @first_key: the first key to look up
210  * @...: the type of @first_key, a pointer to that type, and
211  * then additional key/type/pointer triplets, terminated
212  * by %NULL.
213  *
214  * Looks up a number of keys in @hash and returns their values.
215  *
216  * Return value: %TRUE if all of the keys were found, %FALSE
217  * if any were missing; note that you will generally need to
218  * initialize each destination variable to a reasonable default
219  * value, since there is no way to tell which keys were found
220  * and which were not.
221  **/
222 gboolean
223 soup_value_hash_lookup_vals (GHashTable *hash, const char *first_key, ...)
224 {
225         va_list args;
226         GValue *value;
227         const char *key;
228         GType type;
229         gboolean found_all = TRUE;
230
231         va_start (args, first_key);
232         key = first_key;
233         while (key) {
234                 type = va_arg (args, GType);
235
236                 value = g_hash_table_lookup (hash, key);
237                 if (!value || !G_VALUE_HOLDS (value, type)) {
238                         found_all = FALSE;
239                         /* skip a pointer */
240                         va_arg (args, gpointer);
241                 } else
242                         SOUP_VALUE_GETV (value, type, args);
243
244                 key = va_arg (args, const char *);
245         }
246         va_end (args);
247
248         return found_all;
249 }
250
251
252 /**
253  * soup_value_array_from_args:
254  * @args: arguments to create a #GValueArray from
255  *
256  * Creates a #GValueArray from the provided arguments, which must
257  * consist of pairs of a #GType and a value of that type, terminated
258  * by %G_TYPE_INVALID. (The array will contain copies of the provided
259  * data rather than pointing to the passed-in data directly.)
260  *
261  * Return value: a new #GValueArray, or %NULL if an error occurred.
262  **/
263 GValueArray *
264 soup_value_array_from_args (va_list args)
265 {
266         GValueArray *array;
267         GType type;
268         GValue val;
269
270         array = g_value_array_new (1);
271         while ((type = va_arg (args, GType)) != G_TYPE_INVALID) {
272                 SOUP_VALUE_SETV (&val, type, args);
273                 g_value_array_append (array, &val);
274         }
275         return array;
276 }
277
278 /**
279  * soup_value_array_to_args:
280  * @array: a #GValueArray
281  * @args: arguments to extract @array into
282  *
283  * Extracts a #GValueArray into the provided arguments, which must
284  * consist of pairs of a #GType and a value of pointer-to-that-type,
285  * terminated by %G_TYPE_INVALID. The returned values will point to the
286  * same memory as the values in the array.
287  *
288  * Return value: success or failure
289  **/
290 gboolean
291 soup_value_array_to_args (GValueArray *array, va_list args)
292 {
293         GType type;
294         GValue *value;
295         int i;
296
297         for (i = 0; i < array->n_values; i++) {
298                 type = va_arg (args, GType);
299                 if (type == G_TYPE_INVALID)
300                         return FALSE;
301                 value = g_value_array_get_nth (array, i);
302                 if (!G_VALUE_HOLDS (value, type))
303                         return FALSE;
304                 SOUP_VALUE_GETV (value, type, args);
305         }
306         return TRUE;
307 }
308
309 /**
310  * soup_value_array_new:
311  *
312  * Creates a new %GValueArray. (This is just a wrapper around
313  * g_value_array_new(), for naming consistency purposes.)
314  *
315  * Return value: a new %GValueArray
316  **/
317 GValueArray *
318 soup_value_array_new (void)
319 {
320         return g_value_array_new (1);
321 }
322
323 static void
324 soup_value_array_append_valist (GValueArray *array,
325                                 GType first_type, va_list args)
326 {
327         GType type;
328         GValue value;
329
330         type = first_type;
331         while (type != G_TYPE_INVALID) {
332                 SOUP_VALUE_SETV (&value, type, args);
333
334                 g_value_array_append (array, &value);
335                 type = va_arg (args, GType);
336         }
337 }
338
339 /**
340  * soup_value_array_new_with_vals:
341  * @first_type: the type of the first value to add
342  * @...: the first value to add, followed by other type/value
343  * pairs, terminated by %G_TYPE_INVALID
344  *
345  * Creates a new %GValueArray and copies the provided values
346  * into it.
347  *
348  * Return value: a new %GValueArray
349  **/
350 GValueArray *
351 soup_value_array_new_with_vals (GType first_type, ...)
352 {
353         GValueArray *array = soup_value_array_new ();
354         va_list args;
355
356         va_start (args, first_type);
357         soup_value_array_append_valist (array, first_type, args);
358         va_end (args);
359
360         return array;
361 }
362
363 /**
364  * soup_value_array_insert:
365  * @array: a #GValueArray
366  * @index_: the index to insert at
367  * @type: a #GType
368  * @...: a value of type @type
369  *
370  * Inserts the provided value of type @type into @array as with
371  * g_value_array_insert(). (The provided data is copied rather than
372  * being inserted directly.)
373  **/
374 void
375 soup_value_array_insert (GValueArray *array, guint index_, GType type, ...)
376 {
377         va_list args;
378         GValue val;
379
380         va_start (args, type);
381         SOUP_VALUE_SETV (&val, type, args);
382         va_end (args);
383         g_value_array_insert (array, index_, &val);
384 }
385
386 /**
387  * soup_value_array_append:
388  * @array: a #GValueArray
389  * @type: a #GType
390  * @...: a value of type @type
391  *
392  * Appends the provided value of type @type to @array as with
393  * g_value_array_append(). (The provided data is copied rather than
394  * being inserted directly.)
395  **/
396 void
397 soup_value_array_append (GValueArray *array, GType type, ...)
398 {
399         va_list args;
400         GValue val;
401
402         va_start (args, type);
403         SOUP_VALUE_SETV (&val, type, args);
404         va_end (args);
405         g_value_array_append (array, &val);
406 }
407
408 /**
409  * soup_value_array_append_vals:
410  * @array: a #GValueArray
411  * @first_type: the type of the first value to add
412  * @...: the first value to add, followed by other type/value
413  * pairs, terminated by %G_TYPE_INVALID
414  *
415  * Appends the provided values into @array as with
416  * g_value_array_append(). (The provided data is copied rather than
417  * being inserted directly.)
418  **/
419 void
420 soup_value_array_append_vals (GValueArray *array, GType first_type, ...)
421 {
422         va_list args;
423
424         va_start (args, first_type);
425         soup_value_array_append_valist (array, first_type, args);
426         va_end (args);
427 }
428
429 /**
430  * soup_value_array_get_nth:
431  * @array: a #GValueArray
432  * @index_: the index to look up
433  * @type: a #GType
434  * @...: a value of type pointer-to-@type
435  *
436  * Gets the @index_ element of @array and stores its value into the
437  * provided location.
438  *
439  * Return value: %TRUE if @array contained a value with index @index_
440  * and type @type, %FALSE if not.
441  **/
442 gboolean
443 soup_value_array_get_nth (GValueArray *array, guint index_, GType type, ...)
444 {
445         GValue *value;
446         va_list args;
447
448         value = g_value_array_get_nth (array, index_);
449         if (!value || !G_VALUE_HOLDS (value, type))
450                 return FALSE;
451
452         va_start (args, type);
453         SOUP_VALUE_GETV (value, type, args);
454         va_end (args);
455         return TRUE;
456 }
457
458
459 static GByteArray *
460 soup_byte_array_copy (GByteArray *ba)
461 {
462         GByteArray *copy;
463
464         copy = g_byte_array_sized_new (ba->len);
465         g_byte_array_append (copy, ba->data, ba->len);
466         return copy;
467 }
468
469 static void
470 soup_byte_array_free (GByteArray *ba)
471 {
472         g_byte_array_free (ba, TRUE);
473 }
474
475 /**
476  * SOUP_TYPE_BYTE_ARRAY:
477  *
478  * glib does not define a #GType for #GByteArray, so libsoup
479  * defines this one itself.
480  **/
481 GType
482 soup_byte_array_get_type (void)
483 {
484         static volatile gsize type_volatile = 0;
485
486         if (g_once_init_enter (&type_volatile)) {
487                 GType type = g_boxed_type_register_static (
488                         g_intern_static_string ("SoupByteArray"),
489                         (GBoxedCopyFunc) soup_byte_array_copy,
490                         (GBoxedFreeFunc) soup_byte_array_free);
491                 g_once_init_leave (&type_volatile, type);
492         }
493         return type_volatile;
494 }