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): a new empty #GHashTable
62 soup_value_hash_new (void)
64 return g_hash_table_new_full (g_str_hash, g_str_equal,
65 g_free, soup_value_hash_value_free);
69 soup_value_hash_insert_valist (GHashTable *hash, const char *first_key,
78 type = va_arg (args, GType);
79 SOUP_VALUE_SETV (&value, type, args);
81 soup_value_hash_insert_value (hash, key, &value);
82 key = va_arg (args, const char *);
87 * soup_value_hash_new_with_vals:
88 * @first_key: the key for the first value
89 * @...: the type of @first_key, followed by the value, followed
90 * by additional key/type/value triplets, terminated by %NULL
92 * Creates a #GHashTable whose keys are strings and whose values
93 * are #GValue, and initializes it with the provided data. As
94 * with soup_value_hash_insert(), the keys and values are copied
95 * rather than being inserted directly.
97 * Return value: (element-type utf8 GValue): a new #GHashTable, initialized with the given values
100 soup_value_hash_new_with_vals (const char *first_key, ...)
102 GHashTable *hash = soup_value_hash_new ();
105 va_start (args, first_key);
106 soup_value_hash_insert_valist (hash, first_key, args);
113 * soup_value_hash_insert_value:
114 * @hash: (element-type utf8 GValue): a value hash
118 * Inserts @value into @hash. (Unlike with g_hash_table_insert(), both
119 * the key and the value are copied).
122 soup_value_hash_insert_value (GHashTable *hash, const char *key, GValue *value)
124 GValue *copy = g_new0 (GValue, 1);
126 g_value_init (copy, G_VALUE_TYPE (value));
127 g_value_copy (value, copy);
128 g_hash_table_insert (hash, g_strdup (key), copy);
132 * soup_value_hash_insert:
133 * @hash: (element-type utf8 GValue): a value hash
136 * @...: a value of type @type
138 * Inserts the provided value of type @type into @hash. (Unlike with
139 * g_hash_table_insert(), both the key and the value are copied).
142 soup_value_hash_insert (GHashTable *hash, const char *key, GType type, ...)
147 va_start (args, type);
148 SOUP_VALUE_SETV (&val, type, args);
150 soup_value_hash_insert_value (hash, key, &val);
154 * soup_value_hash_insert_vals:
155 * @hash: (element-type utf8 GValue): a value hash
156 * @first_key: the key for the first value
157 * @...: the type of @first_key, followed by the value, followed
158 * by additional key/type/value triplets, terminated by %NULL
160 * Inserts the given data into @hash. As with
161 * soup_value_hash_insert(), the keys and values are copied rather
162 * than being inserted directly.
165 soup_value_hash_insert_vals (GHashTable *hash, const char *first_key, ...)
169 va_start (args, first_key);
170 soup_value_hash_insert_valist (hash, first_key, args);
175 * soup_value_hash_lookup:
176 * @hash: (element-type utf8 GValue): a value hash
177 * @key: the key to look up
179 * @...: a value of type pointer-to-@type
181 * Looks up @key in @hash and stores its value into the provided
184 * Return value: %TRUE if @hash contained a value with key @key and
185 * type @type, %FALSE if not.
188 soup_value_hash_lookup (GHashTable *hash, const char *key, GType type, ...)
193 value = g_hash_table_lookup (hash, key);
194 if (!value || !G_VALUE_HOLDS (value, type))
197 va_start (args, type);
198 SOUP_VALUE_GETV (value, type, args);
205 * soup_value_hash_lookup_vals:
206 * @hash: (element-type utf8 GValue): a value hash
207 * @first_key: the first key to look up
208 * @...: the type of @first_key, a pointer to that type, and
209 * then additional key/type/pointer triplets, terminated
212 * Looks up a number of keys in @hash and returns their values.
214 * Return value: %TRUE if all of the keys were found, %FALSE
215 * if any were missing; note that you will generally need to
216 * initialize each destination variable to a reasonable default
217 * value, since there is no way to tell which keys were found
218 * and which were not.
221 soup_value_hash_lookup_vals (GHashTable *hash, const char *first_key, ...)
227 gboolean found_all = TRUE;
229 va_start (args, first_key);
232 type = va_arg (args, GType);
234 value = g_hash_table_lookup (hash, key);
235 if (!value || !G_VALUE_HOLDS (value, type)) {
238 va_arg (args, gpointer);
240 SOUP_VALUE_GETV (value, type, args);
242 key = va_arg (args, const char *);
251 * soup_value_array_from_args:
252 * @args: arguments to create a #GValueArray from
254 * Creates a #GValueArray from the provided arguments, which must
255 * consist of pairs of a #GType and a value of that type, terminated
256 * by %G_TYPE_INVALID. (The array will contain copies of the provided
257 * data rather than pointing to the passed-in data directly.)
259 * Return value: a new #GValueArray, or %NULL if an error occurred.
262 soup_value_array_from_args (va_list args)
268 array = g_value_array_new (1);
269 while ((type = va_arg (args, GType)) != G_TYPE_INVALID) {
270 SOUP_VALUE_SETV (&val, type, args);
271 g_value_array_append (array, &val);
277 * soup_value_array_to_args:
278 * @array: a #GValueArray
279 * @args: arguments to extract @array into
281 * Extracts a #GValueArray into the provided arguments, which must
282 * consist of pairs of a #GType and a value of pointer-to-that-type,
283 * terminated by %G_TYPE_INVALID. The returned values will point to the
284 * same memory as the values in the array.
286 * Return value: success or failure
289 soup_value_array_to_args (GValueArray *array, va_list args)
295 for (i = 0; i < array->n_values; i++) {
296 type = va_arg (args, GType);
297 if (type == G_TYPE_INVALID)
299 value = g_value_array_get_nth (array, i);
300 if (!G_VALUE_HOLDS (value, type))
302 SOUP_VALUE_GETV (value, type, args);
308 * soup_value_array_new:
310 * Creates a new %GValueArray. (This is just a wrapper around
311 * g_value_array_new(), for naming consistency purposes.)
313 * Return value: a new %GValueArray
316 soup_value_array_new (void)
318 return g_value_array_new (1);
322 soup_value_array_append_valist (GValueArray *array,
323 GType first_type, va_list args)
329 while (type != G_TYPE_INVALID) {
330 SOUP_VALUE_SETV (&value, type, args);
332 g_value_array_append (array, &value);
333 type = va_arg (args, GType);
338 * soup_value_array_new_with_vals:
339 * @first_type: the type of the first value to add
340 * @...: the first value to add, followed by other type/value
341 * pairs, terminated by %G_TYPE_INVALID
343 * Creates a new %GValueArray and copies the provided values
346 * Return value: a new %GValueArray
349 soup_value_array_new_with_vals (GType first_type, ...)
351 GValueArray *array = soup_value_array_new ();
354 va_start (args, first_type);
355 soup_value_array_append_valist (array, first_type, args);
362 * soup_value_array_insert:
363 * @array: a #GValueArray
364 * @index_: the index to insert at
366 * @...: a value of type @type
368 * Inserts the provided value of type @type into @array as with
369 * g_value_array_insert(). (The provided data is copied rather than
370 * being inserted directly.)
373 soup_value_array_insert (GValueArray *array, guint index_, GType type, ...)
378 va_start (args, type);
379 SOUP_VALUE_SETV (&val, type, args);
381 g_value_array_insert (array, index_, &val);
385 * soup_value_array_append:
386 * @array: a #GValueArray
388 * @...: a value of type @type
390 * Appends the provided value of type @type to @array as with
391 * g_value_array_append(). (The provided data is copied rather than
392 * being inserted directly.)
395 soup_value_array_append (GValueArray *array, GType type, ...)
400 va_start (args, type);
401 SOUP_VALUE_SETV (&val, type, args);
403 g_value_array_append (array, &val);
407 * soup_value_array_append_vals:
408 * @array: a #GValueArray
409 * @first_type: the type of the first value to add
410 * @...: the first value to add, followed by other type/value
411 * pairs, terminated by %G_TYPE_INVALID
413 * Appends the provided values into @array as with
414 * g_value_array_append(). (The provided data is copied rather than
415 * being inserted directly.)
418 soup_value_array_append_vals (GValueArray *array, GType first_type, ...)
422 va_start (args, first_type);
423 soup_value_array_append_valist (array, first_type, args);
428 * soup_value_array_get_nth:
429 * @array: a #GValueArray
430 * @index_: the index to look up
432 * @...: a value of type pointer-to-@type
434 * Gets the @index_ element of @array and stores its value into the
437 * Return value: %TRUE if @array contained a value with index @index_
438 * and type @type, %FALSE if not.
441 soup_value_array_get_nth (GValueArray *array, guint index_, GType type, ...)
446 value = g_value_array_get_nth (array, index_);
447 if (!value || !G_VALUE_HOLDS (value, type))
450 va_start (args, type);
451 SOUP_VALUE_GETV (value, type, args);
458 soup_byte_array_copy (GByteArray *ba)
462 copy = g_byte_array_sized_new (ba->len);
463 g_byte_array_append (copy, ba->data, ba->len);
468 soup_byte_array_free (GByteArray *ba)
470 g_byte_array_free (ba, TRUE);
474 * SOUP_TYPE_BYTE_ARRAY:
476 * glib does not define a #GType for #GByteArray, so libsoup
477 * defines this one itself.
480 soup_byte_array_get_type (void)
482 static volatile gsize type_volatile = 0;
484 if (g_once_init_enter (&type_volatile)) {
485 GType type = g_boxed_type_register_static (
486 g_intern_static_string ("SoupByteArray"),
487 (GBoxedCopyFunc) soup_byte_array_copy,
488 (GBoxedFreeFunc) soup_byte_array_free);
489 g_once_init_leave (&type_volatile, type);
491 return type_volatile;