1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * soup-type-utils.c: GValue and GType-related utilities
5 * Copyright (C) 2007 Red Hat, Inc.
8 #include "soup-value-utils.h"
13 * SECTION:soup-value-utils
14 * @short_description: #GValue utilities
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.
20 * They are written for use with soup-xmlrpc, but they also work with
21 * types not used by XML-RPC.
28 * @args: #va_list pointing to a value of type @type
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.
39 * @args: #va_list pointing to a value of type pointer-to-@type
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
47 soup_value_hash_value_free (gpointer val)
54 * soup_value_hash_new:
56 * Creates a #GHashTable whose keys are strings and whose values
59 * Return value: (element-type utf8 GValue) (transfer full): a new
63 soup_value_hash_new (void)
65 return g_hash_table_new_full (g_str_hash, g_str_equal,
66 g_free, soup_value_hash_value_free);
70 soup_value_hash_insert_valist (GHashTable *hash, const char *first_key,
79 type = va_arg (args, GType);
80 SOUP_VALUE_SETV (&value, type, args);
82 soup_value_hash_insert_value (hash, key, &value);
83 key = va_arg (args, const char *);
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
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.
98 * Return value: (element-type utf8 GValue) (transfer full): a new
99 * #GHashTable, initialized with the given values
102 soup_value_hash_new_with_vals (const char *first_key, ...)
104 GHashTable *hash = soup_value_hash_new ();
107 va_start (args, first_key);
108 soup_value_hash_insert_valist (hash, first_key, args);
115 * soup_value_hash_insert_value:
116 * @hash: (element-type utf8 GValue): a value hash
120 * Inserts @value into @hash. (Unlike with g_hash_table_insert(), both
121 * the key and the value are copied).
124 soup_value_hash_insert_value (GHashTable *hash, const char *key, GValue *value)
126 GValue *copy = g_new0 (GValue, 1);
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);
134 * soup_value_hash_insert:
135 * @hash: (element-type utf8 GValue): a value hash
138 * @...: a value of type @type
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).
144 soup_value_hash_insert (GHashTable *hash, const char *key, GType type, ...)
149 va_start (args, type);
150 SOUP_VALUE_SETV (&val, type, args);
152 soup_value_hash_insert_value (hash, key, &val);
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
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.
167 soup_value_hash_insert_vals (GHashTable *hash, const char *first_key, ...)
171 va_start (args, first_key);
172 soup_value_hash_insert_valist (hash, first_key, args);
177 * soup_value_hash_lookup:
178 * @hash: (element-type utf8 GValue): a value hash
179 * @key: the key to look up
181 * @...: a value of type pointer-to-@type
183 * Looks up @key in @hash and stores its value into the provided
186 * Return value: %TRUE if @hash contained a value with key @key and
187 * type @type, %FALSE if not.
190 soup_value_hash_lookup (GHashTable *hash, const char *key, GType type, ...)
195 value = g_hash_table_lookup (hash, key);
196 if (!value || !G_VALUE_HOLDS (value, type))
199 va_start (args, type);
200 SOUP_VALUE_GETV (value, type, args);
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
214 * Looks up a number of keys in @hash and returns their values.
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.
223 soup_value_hash_lookup_vals (GHashTable *hash, const char *first_key, ...)
229 gboolean found_all = TRUE;
231 va_start (args, first_key);
234 type = va_arg (args, GType);
236 value = g_hash_table_lookup (hash, key);
237 if (!value || !G_VALUE_HOLDS (value, type)) {
240 va_arg (args, gpointer);
242 SOUP_VALUE_GETV (value, type, args);
244 key = va_arg (args, const char *);
252 #ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
253 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
257 * soup_value_array_from_args:
258 * @args: arguments to create a #GValueArray from
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.)
265 * Return value: a new #GValueArray, or %NULL if an error occurred.
268 soup_value_array_from_args (va_list args)
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);
283 * soup_value_array_to_args:
284 * @array: a #GValueArray
285 * @args: arguments to extract @array into
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.
292 * Return value: success or failure
295 soup_value_array_to_args (GValueArray *array, va_list args)
301 for (i = 0; i < array->n_values; i++) {
302 type = va_arg (args, GType);
303 if (type == G_TYPE_INVALID)
305 value = g_value_array_get_nth (array, i);
306 if (!G_VALUE_HOLDS (value, type))
308 SOUP_VALUE_GETV (value, type, args);
314 * soup_value_array_new:
316 * Creates a new %GValueArray. (This is just a wrapper around
317 * g_value_array_new(), for naming consistency purposes.)
319 * Return value: a new %GValueArray
322 soup_value_array_new (void)
324 return g_value_array_new (1);
328 soup_value_array_append_valist (GValueArray *array,
329 GType first_type, va_list args)
335 while (type != G_TYPE_INVALID) {
336 SOUP_VALUE_SETV (&value, type, args);
338 g_value_array_append (array, &value);
339 type = va_arg (args, GType);
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
349 * Creates a new %GValueArray and copies the provided values
352 * Return value: a new %GValueArray
355 soup_value_array_new_with_vals (GType first_type, ...)
357 GValueArray *array = soup_value_array_new ();
360 va_start (args, first_type);
361 soup_value_array_append_valist (array, first_type, args);
368 * soup_value_array_insert:
369 * @array: a #GValueArray
370 * @index_: the index to insert at
372 * @...: a value of type @type
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.)
379 soup_value_array_insert (GValueArray *array, guint index_, GType type, ...)
384 va_start (args, type);
385 SOUP_VALUE_SETV (&val, type, args);
387 g_value_array_insert (array, index_, &val);
391 * soup_value_array_append:
392 * @array: a #GValueArray
394 * @...: a value of type @type
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.)
401 soup_value_array_append (GValueArray *array, GType type, ...)
406 va_start (args, type);
407 SOUP_VALUE_SETV (&val, type, args);
409 g_value_array_append (array, &val);
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
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.)
424 soup_value_array_append_vals (GValueArray *array, GType first_type, ...)
428 va_start (args, first_type);
429 soup_value_array_append_valist (array, first_type, args);
434 * soup_value_array_get_nth:
435 * @array: a #GValueArray
436 * @index_: the index to look up
438 * @...: a value of type pointer-to-@type
440 * Gets the @index_ element of @array and stores its value into the
443 * Return value: %TRUE if @array contained a value with index @index_
444 * and type @type, %FALSE if not.
447 soup_value_array_get_nth (GValueArray *array, guint index_, GType type, ...)
452 value = g_value_array_get_nth (array, index_);
453 if (!value || !G_VALUE_HOLDS (value, type))
456 va_start (args, type);
457 SOUP_VALUE_GETV (value, type, args);
462 #ifdef G_GNUC_END_IGNORE_DEPRECATIONS
463 G_GNUC_END_IGNORE_DEPRECATIONS
467 soup_byte_array_copy (GByteArray *ba)
471 copy = g_byte_array_sized_new (ba->len);
472 g_byte_array_append (copy, ba->data, ba->len);
477 soup_byte_array_free (GByteArray *ba)
479 g_byte_array_free (ba, TRUE);
483 * SOUP_TYPE_BYTE_ARRAY:
485 * glib does not define a #GType for #GByteArray, so libsoup
486 * defines this one itself.
489 soup_byte_array_get_type (void)
491 static volatile gsize type_volatile = 0;
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);
500 return type_volatile;