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