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