Reapplying patch to disable attempts to use gtk-doc
[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 #ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
253 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
254 #endif
255
256 /**
257  * soup_value_array_from_args:
258  * @args: arguments to create a #GValueArray from
259  *
260  * Creates a #GValueArray from the provided arguments, which must
261  * consist of pairs of a #GType and a value of that type, terminated
262  * by %G_TYPE_INVALID. (The array will contain copies of the provided
263  * data rather than pointing to the passed-in data directly.)
264  *
265  * Return value: a new #GValueArray, or %NULL if an error occurred.
266  **/
267 GValueArray *
268 soup_value_array_from_args (va_list args)
269 {
270         GValueArray *array;
271         GType type;
272         GValue val;
273
274         array = g_value_array_new (1);
275         while ((type = va_arg (args, GType)) != G_TYPE_INVALID) {
276                 SOUP_VALUE_SETV (&val, type, args);
277                 g_value_array_append (array, &val);
278         }
279         return array;
280 }
281
282 /**
283  * soup_value_array_to_args:
284  * @array: a #GValueArray
285  * @args: arguments to extract @array into
286  *
287  * Extracts a #GValueArray into the provided arguments, which must
288  * consist of pairs of a #GType and a value of pointer-to-that-type,
289  * terminated by %G_TYPE_INVALID. The returned values will point to the
290  * same memory as the values in the array.
291  *
292  * Return value: success or failure
293  **/
294 gboolean
295 soup_value_array_to_args (GValueArray *array, va_list args)
296 {
297         GType type;
298         GValue *value;
299         int i;
300
301         for (i = 0; i < array->n_values; i++) {
302                 type = va_arg (args, GType);
303                 if (type == G_TYPE_INVALID)
304                         return FALSE;
305                 value = g_value_array_get_nth (array, i);
306                 if (!G_VALUE_HOLDS (value, type))
307                         return FALSE;
308                 SOUP_VALUE_GETV (value, type, args);
309         }
310         return TRUE;
311 }
312
313 /**
314  * soup_value_array_new:
315  *
316  * Creates a new %GValueArray. (This is just a wrapper around
317  * g_value_array_new(), for naming consistency purposes.)
318  *
319  * Return value: a new %GValueArray
320  **/
321 GValueArray *
322 soup_value_array_new (void)
323 {
324         return g_value_array_new (1);
325 }
326
327 static void
328 soup_value_array_append_valist (GValueArray *array,
329                                 GType first_type, va_list args)
330 {
331         GType type;
332         GValue value;
333
334         type = first_type;
335         while (type != G_TYPE_INVALID) {
336                 SOUP_VALUE_SETV (&value, type, args);
337
338                 g_value_array_append (array, &value);
339                 type = va_arg (args, GType);
340         }
341 }
342
343 /**
344  * soup_value_array_new_with_vals:
345  * @first_type: the type of the first value to add
346  * @...: the first value to add, followed by other type/value
347  * pairs, terminated by %G_TYPE_INVALID
348  *
349  * Creates a new %GValueArray and copies the provided values
350  * into it.
351  *
352  * Return value: a new %GValueArray
353  **/
354 GValueArray *
355 soup_value_array_new_with_vals (GType first_type, ...)
356 {
357         GValueArray *array = soup_value_array_new ();
358         va_list args;
359
360         va_start (args, first_type);
361         soup_value_array_append_valist (array, first_type, args);
362         va_end (args);
363
364         return array;
365 }
366
367 /**
368  * soup_value_array_insert:
369  * @array: a #GValueArray
370  * @index_: the index to insert at
371  * @type: a #GType
372  * @...: a value of type @type
373  *
374  * Inserts the provided value of type @type into @array as with
375  * g_value_array_insert(). (The provided data is copied rather than
376  * being inserted directly.)
377  **/
378 void
379 soup_value_array_insert (GValueArray *array, guint index_, GType type, ...)
380 {
381         va_list args;
382         GValue val;
383
384         va_start (args, type);
385         SOUP_VALUE_SETV (&val, type, args);
386         va_end (args);
387         g_value_array_insert (array, index_, &val);
388 }
389
390 /**
391  * soup_value_array_append:
392  * @array: a #GValueArray
393  * @type: a #GType
394  * @...: a value of type @type
395  *
396  * Appends the provided value of type @type to @array as with
397  * g_value_array_append(). (The provided data is copied rather than
398  * being inserted directly.)
399  **/
400 void
401 soup_value_array_append (GValueArray *array, GType type, ...)
402 {
403         va_list args;
404         GValue val;
405
406         va_start (args, type);
407         SOUP_VALUE_SETV (&val, type, args);
408         va_end (args);
409         g_value_array_append (array, &val);
410 }
411
412 /**
413  * soup_value_array_append_vals:
414  * @array: a #GValueArray
415  * @first_type: the type of the first value to add
416  * @...: the first value to add, followed by other type/value
417  * pairs, terminated by %G_TYPE_INVALID
418  *
419  * Appends the provided values into @array as with
420  * g_value_array_append(). (The provided data is copied rather than
421  * being inserted directly.)
422  **/
423 void
424 soup_value_array_append_vals (GValueArray *array, GType first_type, ...)
425 {
426         va_list args;
427
428         va_start (args, first_type);
429         soup_value_array_append_valist (array, first_type, args);
430         va_end (args);
431 }
432
433 /**
434  * soup_value_array_get_nth:
435  * @array: a #GValueArray
436  * @index_: the index to look up
437  * @type: a #GType
438  * @...: a value of type pointer-to-@type
439  *
440  * Gets the @index_ element of @array and stores its value into the
441  * provided location.
442  *
443  * Return value: %TRUE if @array contained a value with index @index_
444  * and type @type, %FALSE if not.
445  **/
446 gboolean
447 soup_value_array_get_nth (GValueArray *array, guint index_, GType type, ...)
448 {
449         GValue *value;
450         va_list args;
451
452         value = g_value_array_get_nth (array, index_);
453         if (!value || !G_VALUE_HOLDS (value, type))
454                 return FALSE;
455
456         va_start (args, type);
457         SOUP_VALUE_GETV (value, type, args);
458         va_end (args);
459         return TRUE;
460 }
461
462 #ifdef G_GNUC_END_IGNORE_DEPRECATIONS
463 G_GNUC_END_IGNORE_DEPRECATIONS
464 #endif
465
466 static GByteArray *
467 soup_byte_array_copy (GByteArray *ba)
468 {
469         GByteArray *copy;
470
471         copy = g_byte_array_sized_new (ba->len);
472         g_byte_array_append (copy, ba->data, ba->len);
473         return copy;
474 }
475
476 static void
477 soup_byte_array_free (GByteArray *ba)
478 {
479         g_byte_array_free (ba, TRUE);
480 }
481
482 /**
483  * SOUP_TYPE_BYTE_ARRAY:
484  *
485  * glib does not define a #GType for #GByteArray, so libsoup
486  * defines this one itself.
487  **/
488 GType
489 soup_byte_array_get_type (void)
490 {
491         static volatile gsize type_volatile = 0;
492
493         if (g_once_init_enter (&type_volatile)) {
494                 GType type = g_boxed_type_register_static (
495                         g_intern_static_string ("SoupByteArray"),
496                         (GBoxedCopyFunc) soup_byte_array_copy,
497                         (GBoxedFreeFunc) soup_byte_array_free);
498                 g_once_init_leave (&type_volatile, type);
499         }
500         return type_volatile;
501 }