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 *);
253 * soup_value_array_from_args:
254 * @args: arguments to create a #GValueArray from
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.)
261 * Return value: a new #GValueArray, or %NULL if an error occurred.
264 soup_value_array_from_args (va_list args)
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);
279 * soup_value_array_to_args:
280 * @array: a #GValueArray
281 * @args: arguments to extract @array into
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.
288 * Return value: success or failure
291 soup_value_array_to_args (GValueArray *array, va_list args)
297 for (i = 0; i < array->n_values; i++) {
298 type = va_arg (args, GType);
299 if (type == G_TYPE_INVALID)
301 value = g_value_array_get_nth (array, i);
302 if (!G_VALUE_HOLDS (value, type))
304 SOUP_VALUE_GETV (value, type, args);
310 * soup_value_array_new:
312 * Creates a new %GValueArray. (This is just a wrapper around
313 * g_value_array_new(), for naming consistency purposes.)
315 * Return value: a new %GValueArray
318 soup_value_array_new (void)
320 return g_value_array_new (1);
324 soup_value_array_append_valist (GValueArray *array,
325 GType first_type, va_list args)
331 while (type != G_TYPE_INVALID) {
332 SOUP_VALUE_SETV (&value, type, args);
334 g_value_array_append (array, &value);
335 type = va_arg (args, GType);
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
345 * Creates a new %GValueArray and copies the provided values
348 * Return value: a new %GValueArray
351 soup_value_array_new_with_vals (GType first_type, ...)
353 GValueArray *array = soup_value_array_new ();
356 va_start (args, first_type);
357 soup_value_array_append_valist (array, first_type, args);
364 * soup_value_array_insert:
365 * @array: a #GValueArray
366 * @index_: the index to insert at
368 * @...: a value of type @type
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.)
375 soup_value_array_insert (GValueArray *array, guint index_, GType type, ...)
380 va_start (args, type);
381 SOUP_VALUE_SETV (&val, type, args);
383 g_value_array_insert (array, index_, &val);
387 * soup_value_array_append:
388 * @array: a #GValueArray
390 * @...: a value of type @type
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.)
397 soup_value_array_append (GValueArray *array, GType type, ...)
402 va_start (args, type);
403 SOUP_VALUE_SETV (&val, type, args);
405 g_value_array_append (array, &val);
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
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.)
420 soup_value_array_append_vals (GValueArray *array, GType first_type, ...)
424 va_start (args, first_type);
425 soup_value_array_append_valist (array, first_type, args);
430 * soup_value_array_get_nth:
431 * @array: a #GValueArray
432 * @index_: the index to look up
434 * @...: a value of type pointer-to-@type
436 * Gets the @index_ element of @array and stores its value into the
439 * Return value: %TRUE if @array contained a value with index @index_
440 * and type @type, %FALSE if not.
443 soup_value_array_get_nth (GValueArray *array, guint index_, GType type, ...)
448 value = g_value_array_get_nth (array, index_);
449 if (!value || !G_VALUE_HOLDS (value, type))
452 va_start (args, type);
453 SOUP_VALUE_GETV (value, type, args);
460 soup_byte_array_copy (GByteArray *ba)
464 copy = g_byte_array_sized_new (ba->len);
465 g_byte_array_append (copy, ba->data, ba->len);
470 soup_byte_array_free (GByteArray *ba)
472 g_byte_array_free (ba, TRUE);
476 * SOUP_TYPE_BYTE_ARRAY:
478 * glib does not define a #GType for #GByteArray, so libsoup
479 * defines this one itself.
482 soup_byte_array_get_type (void)
484 static volatile gsize type_volatile = 0;
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);
493 return type_volatile;