1 /*
2 * util.c - Source for telepathy-glib utility functions
3 * Copyright © 2006-2010 Collabora Ltd. <http://www.collabora.co.uk/>
4 * Copyright © 2006-2008 Nokia Corporation
5 * Copyright © 1999 Tom Tromey
6 * Copyright © 2000 Red Hat, Inc.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 /**
24 * SECTION:util
25 * @title: Utilities
26 * @short_description: Non-Telepathy utility functions
27 *
28 * Some utility functions used in telepathy-glib which could have been in
29 * GLib, but aren't.
30 */
31
32 #include "config.h"
33
34 #include <glib/gstdio.h>
35 #include <gobject/gvaluecollector.h>
36
37 #ifdef HAVE_GIO_UNIX
38 #include <gio/gunixsocketaddress.h>
39 #include <gio/gunixconnection.h>
40 #endif /* HAVE_GIO_UNIX */
41
42 #include <telepathy-glib/enums.h>
43 #include <telepathy-glib/errors.h>
44 #include <telepathy-glib/util-internal.h>
45 #include <telepathy-glib/util.h>
46
47 #include <errno.h>
48 #include <stdio.h>
49 #include <string.h>
50
51 #define DEBUG_FLAG TP_DEBUG_MISC
52 #include "debug-internal.h"
53 #include "simple-client-factory-internal.h"
54
55 /**
56 * tp_verify:
57 * @R: a requirement (constant expression) to be checked at compile-time
58 *
59 * Make an assertion at compile time, like C++0x's proposed static_assert
60 * keyword. If @R is determined to be true, there is no overhead at runtime;
61 * if @R is determined to be false, compilation will fail.
62 *
63 * This macro can be used at file scope (it expands to a dummy extern
64 * declaration).
65 *
66 * (This is gnulib's verify macro, written by Paul Eggert, Bruno Haible and
67 * Jim Meyering.)
68 *
69 * This macro will be deprecated in a future telepathy-glib release. Please
70 * use GLib 2.20's G_STATIC_ASSERT() macro in new code.
71 *
72 * Since: 0.7.34
73 */
74
75 /**
76 * tp_verify_true:
77 * @R: a requirement (constant expression) to be checked at compile-time
78 *
79 * Make an assertion at compile time, like C++0x's proposed static_assert
80 * keyword. If @R is determined to be true, there is no overhead at runtime,
81 * and the macro evaluates to 1 as an integer constant expression;
82 * if @R is determined to be false, compilation will fail.
83 *
84 * This macro can be used anywhere that an integer constant expression would
85 * be allowed.
86 *
87 * (This is gnulib's verify_true macro, written by Paul Eggert, Bruno Haible
88 * and Jim Meyering.)
89 *
90 * This macro will be deprecated in a future telepathy-glib release. Please
91 * use GLib 2.20's G_STATIC_ASSERT() macro in new code.
92 *
93 * Returns: 1
94 *
95 * Since: 0.7.34
96 */
97
98 /**
99 * tp_verify_statement:
100 * @R: a requirement (constant expression) to be checked at compile-time
101 *
102 * Make an assertion at compile time, like C++0x's proposed static_assert
103 * keyword. If @R is determined to be true, there is no overhead at runtime;
104 * if @R is determined to be false, compilation will fail.
105 *
106 * This macro can be used anywhere that a statement would be allowed; it
107 * is equivalent to ((void) tp_verify_true (R)).
108 *
109 * This macro will be deprecated in a future telepathy-glib release. Please
110 * use GLib 2.20's G_STATIC_ASSERT() macro in new code.
111 *
112 * Since: 0.7.34
113 */
114
115 /**
116 * tp_g_ptr_array_contains: (skip)
117 * @haystack: The pointer array to be searched
118 * @needle: The pointer to look for
119 *
120 * <!--no further documentation needed-->
121 *
122 * Returns: %TRUE if @needle is one of the elements of @haystack
123 */
124
125 gboolean
tp_g_ptr_array_contains(GPtrArray * haystack,gpointer needle)126 tp_g_ptr_array_contains (GPtrArray *haystack, gpointer needle)
127 {
128 guint i;
129
130 g_return_val_if_fail (haystack != NULL, FALSE);
131
132 for (i = 0; i < haystack->len; i++)
133 {
134 if (g_ptr_array_index (haystack, i) == needle)
135 return TRUE;
136 }
137
138 return FALSE;
139 }
140
141 static void
add_to_array(gpointer data,gpointer user_data)142 add_to_array (gpointer data,
143 gpointer user_data)
144 {
145 g_ptr_array_add (user_data, data);
146 }
147
148 /**
149 * tp_g_ptr_array_extend: (skip)
150 * @target: a #GPtrArray to copy items to
151 * @source: a #GPtrArray to copy items from
152 *
153 * Appends all elements of @source to @target. Note that this only copies the
154 * pointers from @source; any duplication or reference-incrementing must be
155 * performed by the caller.
156 *
157 * After this function has been called, it is safe to call
158 * g_ptr_array_free() on @source and also free the actual pointer array,
159 * as long as doing so does not free the data pointed to by the new
160 * items in @target.
161 *
162 * Since: 0.14.3
163 */
164 void
tp_g_ptr_array_extend(GPtrArray * target,GPtrArray * source)165 tp_g_ptr_array_extend (GPtrArray *target,
166 GPtrArray *source)
167 {
168 g_return_if_fail (source != NULL);
169 g_return_if_fail (target != NULL);
170
171 g_ptr_array_foreach (source, add_to_array, target);
172 }
173
174 /**
175 * tp_g_value_slice_new: (skip)
176 * @type: The type desired for the new GValue
177 *
178 * Slice-allocate an empty #GValue. tp_g_value_slice_new_boolean() and similar
179 * functions are likely to be more convenient to use for the types supported.
180 *
181 * Returns: a newly allocated, newly initialized #GValue, to be freed with
182 * tp_g_value_slice_free() or g_slice_free().
183 * Since: 0.5.14
184 */
185 GValue *
tp_g_value_slice_new(GType type)186 tp_g_value_slice_new (GType type)
187 {
188 GValue *ret = g_slice_new0 (GValue);
189
190 g_value_init (ret, type);
191 return ret;
192 }
193
194 /**
195 * tp_g_value_slice_new_boolean: (skip)
196 * @b: a boolean value
197 *
198 * Slice-allocate and initialize a #GValue. This function is convenient to
199 * use when constructing hash tables from string to #GValue, for example.
200 *
201 * Returns: a #GValue of type %G_TYPE_BOOLEAN with value @b, to be freed with
202 * tp_g_value_slice_free() or g_slice_free()
203 *
204 * Since: 0.7.27
205 */
206 GValue *
tp_g_value_slice_new_boolean(gboolean b)207 tp_g_value_slice_new_boolean (gboolean b)
208 {
209 GValue *v = tp_g_value_slice_new (G_TYPE_BOOLEAN);
210
211 g_value_set_boolean (v, b);
212 return v;
213 }
214
215 /**
216 * tp_g_value_slice_new_int: (skip)
217 * @n: an integer
218 *
219 * Slice-allocate and initialize a #GValue. This function is convenient to
220 * use when constructing hash tables from string to #GValue, for example.
221 *
222 * Returns: a #GValue of type %G_TYPE_INT with value @n, to be freed with
223 * tp_g_value_slice_free() or g_slice_free()
224 *
225 * Since: 0.7.27
226 */
227 GValue *
tp_g_value_slice_new_int(gint n)228 tp_g_value_slice_new_int (gint n)
229 {
230 GValue *v = tp_g_value_slice_new (G_TYPE_INT);
231
232 g_value_set_int (v, n);
233 return v;
234 }
235
236 /**
237 * tp_g_value_slice_new_int64: (skip)
238 * @n: a 64-bit integer
239 *
240 * Slice-allocate and initialize a #GValue. This function is convenient to
241 * use when constructing hash tables from string to #GValue, for example.
242 *
243 * Returns: a #GValue of type %G_TYPE_INT64 with value @n, to be freed with
244 * tp_g_value_slice_free() or g_slice_free()
245 *
246 * Since: 0.7.27
247 */
248 GValue *
tp_g_value_slice_new_int64(gint64 n)249 tp_g_value_slice_new_int64 (gint64 n)
250 {
251 GValue *v = tp_g_value_slice_new (G_TYPE_INT64);
252
253 g_value_set_int64 (v, n);
254 return v;
255 }
256
257 /**
258 * tp_g_value_slice_new_byte: (skip)
259 * @n: an unsigned integer
260 *
261 * Slice-allocate and initialize a #GValue. This function is convenient to
262 * use when constructing hash tables from string to #GValue, for example.
263 *
264 * Returns: a #GValue of type %G_TYPE_UCHAR with value @n, to be freed with
265 * tp_g_value_slice_free() or g_slice_free()
266 *
267 * Since: 0.11.0
268 */
269 GValue *
tp_g_value_slice_new_byte(guchar n)270 tp_g_value_slice_new_byte (guchar n)
271 {
272 GValue *v = tp_g_value_slice_new (G_TYPE_UCHAR);
273
274 g_value_set_uchar (v, n);
275 return v;
276 }
277
278 /**
279 * tp_g_value_slice_new_uint: (skip)
280 * @n: an unsigned integer
281 *
282 * Slice-allocate and initialize a #GValue. This function is convenient to
283 * use when constructing hash tables from string to #GValue, for example.
284 *
285 * Returns: a #GValue of type %G_TYPE_UINT with value @n, to be freed with
286 * tp_g_value_slice_free() or g_slice_free()
287 *
288 * Since: 0.7.27
289 */
290 GValue *
tp_g_value_slice_new_uint(guint n)291 tp_g_value_slice_new_uint (guint n)
292 {
293 GValue *v = tp_g_value_slice_new (G_TYPE_UINT);
294
295 g_value_set_uint (v, n);
296 return v;
297 }
298
299 /**
300 * tp_g_value_slice_new_uint64: (skip)
301 * @n: a 64-bit unsigned integer
302 *
303 * Slice-allocate and initialize a #GValue. This function is convenient to
304 * use when constructing hash tables from string to #GValue, for example.
305 *
306 * Returns: a #GValue of type %G_TYPE_UINT64 with value @n, to be freed with
307 * tp_g_value_slice_free() or g_slice_free()
308 *
309 * Since: 0.7.27
310 */
311 GValue *
tp_g_value_slice_new_uint64(guint64 n)312 tp_g_value_slice_new_uint64 (guint64 n)
313 {
314 GValue *v = tp_g_value_slice_new (G_TYPE_UINT64);
315
316 g_value_set_uint64 (v, n);
317 return v;
318 }
319
320 /**
321 * tp_g_value_slice_new_double: (skip)
322 * @d: a number
323 *
324 * Slice-allocate and initialize a #GValue. This function is convenient to
325 * use when constructing hash tables from string to #GValue, for example.
326 *
327 * Returns: a #GValue of type %G_TYPE_DOUBLE with value @n, to be freed with
328 * tp_g_value_slice_free() or g_slice_free()
329 *
330 * Since: 0.7.27
331 */
332 GValue *
tp_g_value_slice_new_double(double n)333 tp_g_value_slice_new_double (double n)
334 {
335 GValue *v = tp_g_value_slice_new (G_TYPE_DOUBLE);
336
337 g_value_set_double (v, n);
338 return v;
339 }
340
341 /**
342 * tp_g_value_slice_new_string: (skip)
343 * @string: a string to be copied into the value
344 *
345 * Slice-allocate and initialize a #GValue. This function is convenient to
346 * use when constructing hash tables from string to #GValue, for example.
347 *
348 * Returns: a #GValue of type %G_TYPE_STRING whose value is a copy of @string,
349 * to be freed with tp_g_value_slice_free() or g_slice_free()
350 *
351 * Since: 0.7.27
352 */
353 GValue *
tp_g_value_slice_new_string(const gchar * string)354 tp_g_value_slice_new_string (const gchar *string)
355 {
356 GValue *v = tp_g_value_slice_new (G_TYPE_STRING);
357
358 g_value_set_string (v, string);
359 return v;
360 }
361
362 /**
363 * tp_g_value_slice_new_static_string: (skip)
364 * @string: a static string which must remain valid forever, to be pointed to
365 * by the value
366 *
367 * Slice-allocate and initialize a #GValue. This function is convenient to
368 * use when constructing hash tables from string to #GValue, for example.
369 *
370 * Returns: a #GValue of type %G_TYPE_STRING whose value is @string,
371 * to be freed with tp_g_value_slice_free() or g_slice_free()
372 *
373 * Since: 0.7.27
374 */
375 GValue *
tp_g_value_slice_new_static_string(const gchar * string)376 tp_g_value_slice_new_static_string (const gchar *string)
377 {
378 GValue *v = tp_g_value_slice_new (G_TYPE_STRING);
379
380 g_value_set_static_string (v, string);
381 return v;
382 }
383
384 /**
385 * tp_g_value_slice_new_take_string: (skip)
386 * @string: a string which will be freed with g_free() by the returned #GValue
387 * (the caller must own it before calling this function, but no longer owns
388 * it after this function returns)
389 *
390 * Slice-allocate and initialize a #GValue. This function is convenient to
391 * use when constructing hash tables from string to #GValue, for example.
392 *
393 * Returns: a #GValue of type %G_TYPE_STRING whose value is @string,
394 * to be freed with tp_g_value_slice_free() or g_slice_free()
395 *
396 * Since: 0.7.27
397 */
398 GValue *
tp_g_value_slice_new_take_string(gchar * string)399 tp_g_value_slice_new_take_string (gchar *string)
400 {
401 GValue *v = tp_g_value_slice_new (G_TYPE_STRING);
402
403 g_value_take_string (v, string);
404 return v;
405 }
406
407 /**
408 * tp_g_value_slice_new_boxed: (skip)
409 * @type: a boxed type
410 * @p: a pointer of type @type, which will be copied
411 *
412 * Slice-allocate and initialize a #GValue. This function is convenient to
413 * use when constructing hash tables from string to #GValue, for example.
414 *
415 * Returns: a #GValue of type @type whose value is a copy of @p,
416 * to be freed with tp_g_value_slice_free() or g_slice_free()
417 *
418 * Since: 0.7.27
419 */
420 GValue *
tp_g_value_slice_new_boxed(GType type,gconstpointer p)421 tp_g_value_slice_new_boxed (GType type,
422 gconstpointer p)
423 {
424 GValue *v;
425
426 g_return_val_if_fail (G_TYPE_FUNDAMENTAL (type) == G_TYPE_BOXED, NULL);
427 v = tp_g_value_slice_new (type);
428 g_value_set_boxed (v, p);
429 return v;
430 }
431
432 /**
433 * tp_g_value_slice_new_static_boxed: (skip)
434 * @type: a boxed type
435 * @p: a pointer of type @type, which must remain valid forever
436 *
437 * Slice-allocate and initialize a #GValue. This function is convenient to
438 * use when constructing hash tables from string to #GValue, for example.
439 *
440 * Returns: a #GValue of type @type whose value is @p,
441 * to be freed with tp_g_value_slice_free() or g_slice_free()
442 *
443 * Since: 0.7.27
444 */
445 GValue *
tp_g_value_slice_new_static_boxed(GType type,gconstpointer p)446 tp_g_value_slice_new_static_boxed (GType type,
447 gconstpointer p)
448 {
449 GValue *v;
450
451 g_return_val_if_fail (G_TYPE_FUNDAMENTAL (type) == G_TYPE_BOXED, NULL);
452 v = tp_g_value_slice_new (type);
453 g_value_set_static_boxed (v, p);
454 return v;
455 }
456
457 /**
458 * tp_g_value_slice_new_take_boxed: (skip)
459 * @type: a boxed type
460 * @p: a pointer of type @type which will be freed with g_boxed_free() by the
461 * returned #GValue (the caller must own it before calling this function, but
462 * no longer owns it after this function returns)
463 *
464 * Slice-allocate and initialize a #GValue. This function is convenient to
465 * use when constructing hash tables from string to #GValue, for example.
466 *
467 * Returns: a #GValue of type @type whose value is @p,
468 * to be freed with tp_g_value_slice_free() or g_slice_free()
469 *
470 * Since: 0.7.27
471 */
472 GValue *
tp_g_value_slice_new_take_boxed(GType type,gpointer p)473 tp_g_value_slice_new_take_boxed (GType type,
474 gpointer p)
475 {
476 GValue *v;
477
478 g_return_val_if_fail (G_TYPE_FUNDAMENTAL (type) == G_TYPE_BOXED, NULL);
479 v = tp_g_value_slice_new (type);
480 g_value_take_boxed (v, p);
481 return v;
482 }
483
484 /**
485 * tp_g_value_slice_free: (skip)
486 * @value: A GValue which was allocated with the g_slice API
487 *
488 * Unset and free a slice-allocated GValue.
489 *
490 * <literal>(GDestroyNotify) tp_g_value_slice_free</literal> can be used
491 * as a destructor for values in a #GHashTable, for example.
492 */
493
494 void
tp_g_value_slice_free(GValue * value)495 tp_g_value_slice_free (GValue *value)
496 {
497 g_value_unset (value);
498 g_slice_free (GValue, value);
499 }
500
501
502 /**
503 * tp_g_value_slice_dup: (skip)
504 * @value: A GValue
505 *
506 * <!-- 'Returns' says it all -->
507 *
508 * Returns: a newly allocated copy of @value, to be freed with
509 * tp_g_value_slice_free() or g_slice_free().
510 * Since: 0.5.14
511 */
512 GValue *
tp_g_value_slice_dup(const GValue * value)513 tp_g_value_slice_dup (const GValue *value)
514 {
515 GValue *ret = tp_g_value_slice_new (G_VALUE_TYPE (value));
516
517 g_value_copy (value, ret);
518 return ret;
519 }
520
521
522 struct _tp_g_hash_table_update
523 {
524 GHashTable *target;
525 GBoxedCopyFunc key_dup, value_dup;
526 };
527
528 static void
_tp_g_hash_table_update_helper(gpointer key,gpointer value,gpointer user_data)529 _tp_g_hash_table_update_helper (gpointer key,
530 gpointer value,
531 gpointer user_data)
532 {
533 struct _tp_g_hash_table_update *data = user_data;
534 gpointer new_key = (data->key_dup != NULL) ? (data->key_dup) (key) : key;
535 gpointer new_value = (data->value_dup != NULL) ? (data->value_dup) (value)
536 : value;
537
538 g_hash_table_replace (data->target, new_key, new_value);
539 }
540
541 /**
542 * tp_g_hash_table_update: (skip)
543 * @target: The hash table to be updated
544 * @source: The hash table to update it with (read-only)
545 * @key_dup: function to duplicate a key from @source so it can be be stored
546 * in @target. If NULL, the key is not copied, but is used as-is
547 * @value_dup: function to duplicate a value from @source so it can be stored
548 * in @target. If NULL, the value is not copied, but is used as-is
549 *
550 * Add each item in @source to @target, replacing any existing item with the
551 * same key. @key_dup and @value_dup are used to duplicate the items; in
552 * principle they could also be used to convert between types.
553 *
554 * Since: 0.7.0
555 */
556 void
tp_g_hash_table_update(GHashTable * target,GHashTable * source,GBoxedCopyFunc key_dup,GBoxedCopyFunc value_dup)557 tp_g_hash_table_update (GHashTable *target,
558 GHashTable *source,
559 GBoxedCopyFunc key_dup,
560 GBoxedCopyFunc value_dup)
561 {
562 struct _tp_g_hash_table_update data = { target, key_dup,
563 value_dup };
564
565 g_return_if_fail (target != NULL);
566 g_return_if_fail (source != NULL);
567 g_return_if_fail (target != source);
568
569 g_hash_table_foreach (source, _tp_g_hash_table_update_helper, &data);
570 }
571
572 /**
573 * tp_str_empty: (skip)
574 * @s: (type utf8) (transfer none): a string
575 *
576 * Return %TRUE if @s is empty, counting %NULL as empty.
577 *
578 * Returns: (type boolean): %TRUE if @s is either %NULL or ""
579 *
580 * Since: 0.11.1
581 */
582 /* no definition here - it's inlined */
583
584 /**
585 * tp_strdiff: (skip)
586 * @left: The first string to compare (may be NULL)
587 * @right: The second string to compare (may be NULL)
588 *
589 * Return %TRUE if the given strings are different. Unlike #strcmp this
590 * function will handle null pointers, treating them as distinct from any
591 * string.
592 *
593 * Returns: %FALSE if @left and @right are both %NULL, or if
594 * neither is %NULL and both have the same contents; %TRUE otherwise
595 */
596
597 gboolean
tp_strdiff(const gchar * left,const gchar * right)598 tp_strdiff (const gchar *left, const gchar *right)
599 {
600 return g_strcmp0 (left, right) != 0;
601 }
602
603
604
605 /**
606 * tp_mixin_offset_cast: (skip)
607 * @instance: A pointer to a structure
608 * @offset: The offset of a structure member in bytes, which must not be 0
609 *
610 * Extend a pointer by an offset, provided the offset is not 0.
611 * This is used to cast from an object instance to one of the telepathy-glib
612 * mixin classes.
613 *
614 * Returns: a pointer @offset bytes beyond @instance
615 */
616 gpointer
tp_mixin_offset_cast(gpointer instance,guint offset)617 tp_mixin_offset_cast (gpointer instance, guint offset)
618 {
619 g_return_val_if_fail (offset != 0, NULL);
620
621 return ((guchar *) instance + offset);
622 }
623
624
625 /**
626 * tp_mixin_instance_get_offset: (skip)
627 * @instance: A pointer to a GObject-derived instance structure
628 * @quark: A quark that was used to store the offset with g_type_set_qdata()
629 *
630 * If the type of @instance, or any of its ancestor types, has had an offset
631 * attached using qdata with the given @quark, return that offset. If not,
632 * return 0.
633 *
634 * In older telepathy-glib versions, calling this function on an instance that
635 * did not have the mixin was considered to be a programming error. Since
636 * version 0.13.9, 0 is returned, without error.
637 *
638 * This is used to implement the telepathy-glib mixin classes.
639 *
640 * Returns: the offset of the mixin
641 */
642 guint
tp_mixin_instance_get_offset(gpointer instance,GQuark quark)643 tp_mixin_instance_get_offset (gpointer instance,
644 GQuark quark)
645 {
646 GType t;
647
648 for (t = G_OBJECT_TYPE (instance);
649 t != 0;
650 t = g_type_parent (t))
651 {
652 gpointer qdata = g_type_get_qdata (t, quark);
653
654 if (qdata != NULL)
655 return GPOINTER_TO_UINT (qdata);
656 }
657
658 return 0;
659 }
660
661
662 /**
663 * tp_mixin_class_get_offset: (skip)
664 * @klass: A pointer to a GObjectClass-derived class structure
665 * @quark: A quark that was used to store the offset with g_type_set_qdata()
666 *
667 * If the type of @klass, or any of its ancestor types, has had an offset
668 * attached using qdata with the given @quark, return that offset; if not,
669 * return 0.
670 *
671 * In older telepathy-glib versions, calling this function on an instance that
672 * did not have the mixin was considered to be a programming error. Since
673 * version 0.13.9, 0 is returned, without error.
674 *
675 * This is used to implement the telepathy-glib mixin classes.
676 *
677 * Returns: the offset of the mixin class
678 */
679 guint
tp_mixin_class_get_offset(gpointer klass,GQuark quark)680 tp_mixin_class_get_offset (gpointer klass,
681 GQuark quark)
682 {
683 GType t;
684
685 for (t = G_OBJECT_CLASS_TYPE (klass);
686 t != 0;
687 t = g_type_parent (t))
688 {
689 gpointer qdata = g_type_get_qdata (t, quark);
690
691 if (qdata != NULL)
692 return GPOINTER_TO_UINT (qdata);
693 }
694
695 return 0;
696 }
697
698
699 static inline gboolean
_esc_ident_bad(gchar c,gboolean is_first)700 _esc_ident_bad (gchar c, gboolean is_first)
701 {
702 return ((c < 'a' || c > 'z') &&
703 (c < 'A' || c > 'Z') &&
704 (c < '0' || c > '9' || is_first));
705 }
706
707
708 /**
709 * tp_escape_as_identifier:
710 * @name: The string to be escaped
711 *
712 * Escape an arbitrary string so it follows the rules for a C identifier,
713 * and hence an object path component, interface element component,
714 * bus name component or member name in D-Bus.
715 *
716 * Unlike g_strcanon this is a reversible encoding, so it preserves
717 * distinctness.
718 *
719 * The escaping consists of replacing all non-alphanumerics, and the first
720 * character if it's a digit, with an underscore and two lower-case hex
721 * digits:
722 *
723 * "0123abc_xyz\x01\xff" -> _30123abc_5fxyz_01_ff
724 *
725 * i.e. similar to URI encoding, but with _ taking the role of %, and a
726 * smaller allowed set. As a special case, "" is escaped to "_" (just for
727 * completeness, really).
728 *
729 * Returns: (transfer full): the escaped string, which must be freed by
730 * the caller with #g_free
731 */
732 gchar *
tp_escape_as_identifier(const gchar * name)733 tp_escape_as_identifier (const gchar *name)
734 {
735 gboolean bad = FALSE;
736 size_t len = 0;
737 GString *op;
738 const gchar *ptr, *first_ok;
739
740 g_return_val_if_fail (name != NULL, NULL);
741
742 /* fast path for empty name */
743 if (name[0] == '\0')
744 return g_strdup ("_");
745
746 for (ptr = name; *ptr; ptr++)
747 {
748 if (_esc_ident_bad (*ptr, ptr == name))
749 {
750 bad = TRUE;
751 len += 3;
752 }
753 else
754 len++;
755 }
756
757 /* fast path if it's clean */
758 if (!bad)
759 return g_strdup (name);
760
761 /* If strictly less than ptr, first_ok is the first uncopied safe character.
762 */
763 first_ok = name;
764 op = g_string_sized_new (len);
765 for (ptr = name; *ptr; ptr++)
766 {
767 if (_esc_ident_bad (*ptr, ptr == name))
768 {
769 /* copy preceding safe characters if any */
770 if (first_ok < ptr)
771 {
772 g_string_append_len (op, first_ok, ptr - first_ok);
773 }
774 /* escape the unsafe character */
775 g_string_append_printf (op, "_%02x", (unsigned char)(*ptr));
776 /* restart after it */
777 first_ok = ptr + 1;
778 }
779 }
780 /* copy trailing safe characters if any */
781 if (first_ok < ptr)
782 {
783 g_string_append_len (op, first_ok, ptr - first_ok);
784 }
785 return g_string_free (op, FALSE);
786 }
787
788
789 /**
790 * tp_strv_contains: (skip)
791 * @strv: a NULL-terminated array of strings, or %NULL (which is treated as an
792 * empty strv)
793 * @str: a non-NULL string
794 *
795 * <!-- -->
796 * Returns: TRUE if @str is an element of @strv, according to strcmp().
797 *
798 * Since: 0.7.15
799 */
800 gboolean
tp_strv_contains(const gchar * const * strv,const gchar * str)801 tp_strv_contains (const gchar * const *strv,
802 const gchar *str)
803 {
804 g_return_val_if_fail (str != NULL, FALSE);
805
806 if (strv == NULL)
807 return FALSE;
808
809 while (*strv != NULL)
810 {
811 if (!tp_strdiff (str, *strv))
812 return TRUE;
813 strv++;
814 }
815
816 return FALSE;
817 }
818
819 /**
820 * tp_g_key_file_get_int64: (skip)
821 * @key_file: a non-%NULL #GKeyFile
822 * @group_name: a non-%NULL group name
823 * @key: a non-%NULL key
824 * @error: return location for a #GError
825 *
826 * Returns the value associated with @key under @group_name as a signed
827 * 64-bit integer. This is similar to g_key_file_get_integer() but can return
828 * 64-bit results without truncation.
829 *
830 * Returns: the value associated with the key as a signed 64-bit integer, or
831 * 0 if the key was not found or could not be parsed.
832 *
833 * Since: 0.7.31
834 * Deprecated: Since 0.21.0. Use g_key_file_get_int64() instead.
835 */
836 gint64
tp_g_key_file_get_int64(GKeyFile * key_file,const gchar * group_name,const gchar * key,GError ** error)837 tp_g_key_file_get_int64 (GKeyFile *key_file,
838 const gchar *group_name,
839 const gchar *key,
840 GError **error)
841 {
842 gchar *s, *end;
843 gint64 v;
844
845 g_return_val_if_fail (key_file != NULL, -1);
846 g_return_val_if_fail (group_name != NULL, -1);
847 g_return_val_if_fail (key != NULL, -1);
848
849 s = g_key_file_get_value (key_file, group_name, key, error);
850
851 if (s == NULL)
852 return 0;
853
854 v = g_ascii_strtoll (s, &end, 10);
855
856 if (*s == '\0' || *end != '\0')
857 {
858 g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE,
859 "Key '%s' in group '%s' has value '%s' where int64 was expected",
860 key, group_name, s);
861 return 0;
862 }
863
864 g_free (s);
865 return v;
866 }
867
868 /**
869 * tp_g_key_file_get_uint64: (skip)
870 * @key_file: a non-%NULL #GKeyFile
871 * @group_name: a non-%NULL group name
872 * @key: a non-%NULL key
873 * @error: return location for a #GError
874 *
875 * Returns the value associated with @key under @group_name as an unsigned
876 * 64-bit integer. This is similar to g_key_file_get_integer() but can return
877 * large positive results without truncation.
878 *
879 * Returns: the value associated with the key as an unsigned 64-bit integer,
880 * or 0 if the key was not found or could not be parsed.
881 *
882 * Since: 0.7.31
883 * Deprecated: Since 0.21.0. Use g_key_file_get_uint64() instead.
884 */
885 guint64
tp_g_key_file_get_uint64(GKeyFile * key_file,const gchar * group_name,const gchar * key,GError ** error)886 tp_g_key_file_get_uint64 (GKeyFile *key_file,
887 const gchar *group_name,
888 const gchar *key,
889 GError **error)
890 {
891 gchar *s, *end;
892 guint64 v;
893
894 g_return_val_if_fail (key_file != NULL, -1);
895 g_return_val_if_fail (group_name != NULL, -1);
896 g_return_val_if_fail (key != NULL, -1);
897
898 s = g_key_file_get_value (key_file, group_name, key, error);
899
900 if (s == NULL)
901 return 0;
902
903 v = g_ascii_strtoull (s, &end, 10);
904
905 if (*s == '\0' || *end != '\0')
906 {
907 g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE,
908 "Key '%s' in group '%s' has value '%s' where uint64 was expected",
909 key, group_name, s);
910 return 0;
911 }
912
913 g_free (s);
914 return v;
915 }
916
917 typedef struct {
918 GObject *instance;
919 GObject *observer;
920 GClosure *closure;
921 gulong handler_id;
922 } WeakHandlerCtx;
923
924 static WeakHandlerCtx *
whc_new(GObject * instance,GObject * observer)925 whc_new (GObject *instance,
926 GObject *observer)
927 {
928 WeakHandlerCtx *ctx = g_slice_new0 (WeakHandlerCtx);
929
930 ctx->instance = instance;
931 ctx->observer = observer;
932
933 return ctx;
934 }
935
936 static void
whc_free(WeakHandlerCtx * ctx)937 whc_free (WeakHandlerCtx *ctx)
938 {
939 g_slice_free (WeakHandlerCtx, ctx);
940 }
941
942 static void observer_destroyed_cb (gpointer, GObject *);
943 static void closure_invalidated_cb (gpointer, GClosure *);
944
945 /*
946 * If signal handlers are removed before the object is destroyed, this
947 * callback will never get triggered.
948 */
949 static void
instance_destroyed_cb(gpointer ctx_,GObject * where_the_instance_was)950 instance_destroyed_cb (gpointer ctx_,
951 GObject *where_the_instance_was)
952 {
953 WeakHandlerCtx *ctx = ctx_;
954
955 /* No need to disconnect the signal here, the instance has gone away. */
956 g_object_weak_unref (ctx->observer, observer_destroyed_cb, ctx);
957 g_closure_remove_invalidate_notifier (ctx->closure, ctx,
958 closure_invalidated_cb);
959 whc_free (ctx);
960 }
961
962 /* Triggered when the observer is destroyed. */
963 static void
observer_destroyed_cb(gpointer ctx_,GObject * where_the_observer_was)964 observer_destroyed_cb (gpointer ctx_,
965 GObject *where_the_observer_was)
966 {
967 WeakHandlerCtx *ctx = ctx_;
968
969 g_closure_remove_invalidate_notifier (ctx->closure, ctx,
970 closure_invalidated_cb);
971 g_signal_handler_disconnect (ctx->instance, ctx->handler_id);
972 g_object_weak_unref (ctx->instance, instance_destroyed_cb, ctx);
973 whc_free (ctx);
974 }
975
976 /* Triggered when either object is destroyed or the handler is disconnected. */
977 static void
closure_invalidated_cb(gpointer ctx_,GClosure * where_the_closure_was)978 closure_invalidated_cb (gpointer ctx_,
979 GClosure *where_the_closure_was)
980 {
981 WeakHandlerCtx *ctx = ctx_;
982
983 g_object_weak_unref (ctx->instance, instance_destroyed_cb, ctx);
984 g_object_weak_unref (ctx->observer, observer_destroyed_cb, ctx);
985 whc_free (ctx);
986 }
987
988 /**
989 * tp_g_signal_connect_object: (skip)
990 * @instance: the instance to connect to.
991 * @detailed_signal: a string of the form "signal-name::detail".
992 * @c_handler: the #GCallback to connect.
993 * @gobject: the object to pass as data to @c_handler.
994 * @connect_flags: a combination of #GConnectFlags. Only
995 * %G_CONNECT_AFTER and %G_CONNECT_SWAPPED are supported by this function.
996 *
997 * Connects a #GCallback function to a signal for a particular object, as if
998 * with g_signal_connect(). Additionally, arranges for the signal handler to be
999 * disconnected if @gobject is destroyed.
1000 *
1001 * This is similar to g_signal_connect_data(), but uses a closure which
1002 * ensures that the @gobject stays alive during the call to @c_handler
1003 * by temporarily adding a reference count to @gobject.
1004 *
1005 * This is similar to g_signal_connect_object(), but doesn't have the
1006 * documented bug that everyone is too scared to fix. Also, it does not allow
1007 * you to pass in NULL as @gobject
1008 *
1009 * This is intended to be a convenient way for objects to use themselves as
1010 * user_data for callbacks without having to explicitly disconnect all the
1011 * handlers in their finalizers.
1012 *
1013 * Changed in 0.10.4 and 0.11.3: %G_CONNECT_AFTER is now respected.
1014 *
1015 * Returns: the handler id
1016 *
1017 * Since: 0.9.2
1018 */
1019 gulong
tp_g_signal_connect_object(gpointer instance,const gchar * detailed_signal,GCallback c_handler,gpointer gobject,GConnectFlags connect_flags)1020 tp_g_signal_connect_object (gpointer instance,
1021 const gchar *detailed_signal,
1022 GCallback c_handler,
1023 gpointer gobject,
1024 GConnectFlags connect_flags)
1025 {
1026 GObject *instance_obj = G_OBJECT (instance);
1027 WeakHandlerCtx *ctx = whc_new (instance_obj, gobject);
1028
1029 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1030 g_return_val_if_fail (detailed_signal != NULL, 0);
1031 g_return_val_if_fail (c_handler != NULL, 0);
1032 g_return_val_if_fail (G_IS_OBJECT (gobject), 0);
1033 g_return_val_if_fail (
1034 (connect_flags & ~(G_CONNECT_AFTER|G_CONNECT_SWAPPED)) == 0, 0);
1035
1036 if (connect_flags & G_CONNECT_SWAPPED)
1037 ctx->closure = g_cclosure_new_object_swap (c_handler, gobject);
1038 else
1039 ctx->closure = g_cclosure_new_object (c_handler, gobject);
1040
1041 ctx->handler_id = g_signal_connect_closure (instance, detailed_signal,
1042 ctx->closure, (connect_flags & G_CONNECT_AFTER) ? TRUE : FALSE);
1043
1044 g_object_weak_ref (instance_obj, instance_destroyed_cb, ctx);
1045 g_object_weak_ref (gobject, observer_destroyed_cb, ctx);
1046 g_closure_add_invalidate_notifier (ctx->closure, ctx,
1047 closure_invalidated_cb);
1048
1049 return ctx->handler_id;
1050 }
1051
1052 /*
1053 * _tp_quark_array_copy:
1054 * @quarks: A 0-terminated list of quarks to copy
1055 *
1056 * Copy a zero-terminated array into a GArray. The trailing
1057 * 0 is not counted in the @len member of the returned
1058 * array, but the @data member is guaranteed to be
1059 * zero-terminated.
1060 *
1061 * Returns: A new GArray containing a copy of @quarks.
1062 */
1063 GArray *
_tp_quark_array_copy(const GQuark * quarks)1064 _tp_quark_array_copy (const GQuark *quarks)
1065 {
1066 GArray *array;
1067 const GQuark *q;
1068
1069 array = g_array_new (TRUE, TRUE, sizeof (GQuark));
1070
1071 for (q = quarks; q != NULL && *q != 0; q++)
1072 {
1073 g_array_append_val (array, *q);
1074 }
1075
1076 return array;
1077 }
1078
1079 /**
1080 * tp_value_array_build: (skip)
1081 * @length: The number of elements that should be in the array
1082 * @type: The type of the first argument.
1083 * @...: The value of the first item in the struct followed by a list of type,
1084 * value pairs terminated by G_TYPE_INVALID.
1085 *
1086 * Creates a new #GValueArray for use with structs, containing the values
1087 * passed in as parameters. The values are copied or reffed as appropriate for
1088 * their type.
1089 *
1090 * <example>
1091 * <title> using tp_value_array_build</title>
1092 * <programlisting>
1093 * GValueArray *array = tp_value_array_build (2,
1094 * G_TYPE_STRING, host,
1095 * G_TYPE_UINT, port,
1096 * G_TYPE_INVALID);
1097 * </programlisting>
1098 * </example>
1099 *
1100 * Returns: a newly created #GValueArray, free with tp_value_array_free()
1101 *
1102 * Since: 0.9.2
1103 */
1104 GValueArray *
tp_value_array_build(gsize length,GType type,...)1105 tp_value_array_build (gsize length,
1106 GType type,
1107 ...)
1108 {
1109 GValueArray *arr;
1110 GType t;
1111 va_list var_args;
1112 char *error = NULL;
1113
1114 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1115 arr = g_value_array_new (length);
1116 G_GNUC_END_IGNORE_DEPRECATIONS
1117
1118 va_start (var_args, type);
1119
1120 for (t = type; t != G_TYPE_INVALID; t = va_arg (var_args, GType))
1121 {
1122 GValue *v = arr->values + arr->n_values;
1123
1124 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1125 g_value_array_append (arr, NULL);
1126 G_GNUC_END_IGNORE_DEPRECATIONS
1127
1128 g_value_init (v, t);
1129
1130 G_VALUE_COLLECT (v, var_args, 0, &error);
1131
1132 if (error != NULL)
1133 {
1134 CRITICAL ("%s", error);
1135 g_free (error);
1136
1137 tp_value_array_free (arr);
1138 va_end (var_args);
1139 return NULL;
1140 }
1141 }
1142
1143 g_warn_if_fail (arr->n_values == length);
1144
1145 va_end (var_args);
1146 return arr;
1147 }
1148
1149 /**
1150 * tp_value_array_unpack: (skip)
1151 * @array: the array to unpack
1152 * @len: The number of elements that should be in the array
1153 * @...: a list of correctly typed pointers to store the values in
1154 *
1155 * Unpacks a #GValueArray into separate variables.
1156 *
1157 * The contents of the values aren't copied into the variables, and so become
1158 * invalid when @array is freed.
1159 *
1160 * <example>
1161 * <title>using tp_value_array_unpack</title>
1162 * <programlisting>
1163 * const gchar *host;
1164 * guint port;
1165 *
1166 * tp_value_array_unpack (array, 2,
1167 * &host,
1168 * &port);
1169 * </programlisting>
1170 * </example>
1171 *
1172 * Since: 0.11.0
1173 */
1174 void
tp_value_array_unpack(GValueArray * array,gsize len,...)1175 tp_value_array_unpack (GValueArray *array,
1176 gsize len,
1177 ...)
1178 {
1179 va_list var_args;
1180 guint i;
1181
1182 va_start (var_args, len);
1183
1184 for (i = 0; i < len; i++)
1185 {
1186 GValue *value;
1187 char *error = NULL;
1188
1189 if (G_UNLIKELY (i > array->n_values))
1190 {
1191 WARNING ("More parameters than entries in the struct!");
1192 break;
1193 }
1194
1195 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1196 value = g_value_array_get_nth (array, i);
1197 G_GNUC_END_IGNORE_DEPRECATIONS
1198
1199 G_VALUE_LCOPY (value, var_args, G_VALUE_NOCOPY_CONTENTS, &error);
1200 if (error != NULL)
1201 {
1202 WARNING ("%s", error);
1203 g_free (error);
1204 break;
1205 }
1206 }
1207
1208 va_end (var_args);
1209 }
1210
1211 /**
1212 * TpWeakRef:
1213 *
1214 * A simple wrapper for a weak reference to a #GObject, suitable for use in
1215 * asynchronous calls which should only affect the object if it hasn't already
1216 * been freed.
1217 *
1218 * As well as wrapping a weak reference to an object, this structure can
1219 * contain an extra pointer to arbitrary data. This is useful for asynchronous
1220 * calls which act on an object and some second piece of data, which are quite
1221 * common in practice.
1222 *
1223 * If more than one piece of auxiliary data is required, the @user_data
1224 * argument to the constructor can be a struct or a #GValueArray.
1225 *
1226 * Since: 0.11.3
1227 */
1228 struct _TpWeakRef {
1229 /*<private>*/
1230 gpointer object;
1231 gpointer user_data;
1232 GDestroyNotify destroy;
1233 };
1234
1235 /**
1236 * tp_weak_ref_new: (skip)
1237 * @object: (type GObject.Object): an object to which to take a weak reference
1238 * @user_data: optional additional data to store alongside the weak ref
1239 * @destroy: destructor for @user_data, called when the weak ref
1240 * is freed
1241 *
1242 * Return a new weak reference wrapper for @object.
1243 *
1244 * Returns: (transfer full): a new weak-reference wrapper
1245 *
1246 * Free-function: tp_weak_ref_destroy()
1247 *
1248 * Since: 0.11.3
1249 */
1250 TpWeakRef *
tp_weak_ref_new(gpointer object,gpointer user_data,GDestroyNotify destroy)1251 tp_weak_ref_new (gpointer object,
1252 gpointer user_data,
1253 GDestroyNotify destroy)
1254 {
1255 TpWeakRef *self;
1256
1257 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1258
1259 self = g_slice_new (TpWeakRef);
1260 self->object = object;
1261 g_object_add_weak_pointer (self->object, &self->object);
1262 self->user_data = user_data;
1263 self->destroy = destroy;
1264 return self;
1265 }
1266
1267 /**
1268 * tp_weak_ref_get_user_data: (skip)
1269 * @self: a weak reference
1270 *
1271 * Return the additional data that was passed to tp_weak_ref_new().
1272 *
1273 * Returns: the additional data supplied in tp_weak_ref_new(), which may be
1274 * %NULL
1275 *
1276 * Since: 0.11.3
1277 */
1278 gpointer
tp_weak_ref_get_user_data(TpWeakRef * self)1279 tp_weak_ref_get_user_data (TpWeakRef *self)
1280 {
1281 return self->user_data;
1282 }
1283
1284 /**
1285 * tp_weak_ref_dup_object: (skip)
1286 * @self: a weak reference
1287 *
1288 * If the weakly referenced object still exists, return a new reference to
1289 * it. Otherwise, return %NULL.
1290 *
1291 * Returns: (type GObject.Object) (transfer full): a new reference, or %NULL
1292 *
1293 * Since: 0.11.3
1294 */
1295 gpointer
tp_weak_ref_dup_object(TpWeakRef * self)1296 tp_weak_ref_dup_object (TpWeakRef *self)
1297 {
1298 if (self->object != NULL)
1299 return g_object_ref (self->object);
1300
1301 return NULL;
1302 }
1303
1304 /**
1305 * tp_weak_ref_destroy: (skip)
1306 * @self: (transfer full): a weak reference
1307 *
1308 * Free a weak reference wrapper. This drops the weak reference to the
1309 * object (if it still exists), and frees the user data with the user-supplied
1310 * destructor function if one was provided.
1311 *
1312 * Since: 0.11.3
1313 */
1314 void
tp_weak_ref_destroy(TpWeakRef * self)1315 tp_weak_ref_destroy (TpWeakRef *self)
1316 {
1317 if (self->object != NULL)
1318 g_object_remove_weak_pointer (self->object, &self->object);
1319
1320 if (self->destroy != NULL)
1321 (self->destroy) (self->user_data);
1322
1323 g_slice_free (TpWeakRef, self);
1324 }
1325
1326 /**
1327 * tp_clear_object: (skip)
1328 * @op: a pointer to a variable, struct member etc. holding a #GObject
1329 *
1330 * Set a variable holding a #GObject to %NULL. If it was not already %NULL,
1331 * unref the object it previously pointed to.
1332 *
1333 * This is exactly equivalent to calling tp_clear_pointer() on @op,
1334 * with @destroy = g_object_unref(). See tp_clear_pointer() for example usage.
1335 *
1336 * Since: 0.11.7
1337 */
1338
1339 /**
1340 * tp_clear_pointer: (skip)
1341 * @pp: a pointer to a variable, struct member etc. holding a pointer
1342 * @destroy: a function to which a gpointer can be passed, to destroy *@pp
1343 * (if calling this macro from C++, explicitly casting the function to
1344 * #GDestroyNotify may be necessary)
1345 *
1346 * Set a variable holding a pointer to %NULL. If it was not already %NULL,
1347 * unref or destroy the object it previously pointed to with @destroy.
1348 *
1349 * More precisely, if *@pp is non-%NULL, set *@pp to %NULL, then
1350 * call @destroy on the object that *@pp previously pointed to.
1351 *
1352 * This is analogous to g_clear_error() for non-error objects, but also
1353 * ensures that @pp is already %NULL before the destructor is run.
1354 *
1355 * Typical usage is something like this:
1356 *
1357 * |[
1358 * typedef struct {
1359 * TpConnection *conn;
1360 * GError *error;
1361 * GHashTable *table;
1362 * MyStruct *misc;
1363 * } Foo;
1364 * Foo *foo;
1365 *
1366 * ...
1367 *
1368 * tp_clear_object (&foo->conn);
1369 * g_clear_error (&foo->error);
1370 * tp_clear_boxed (G_TYPE_HASH_TABLE, &foo->table);
1371 * tp_clear_pointer (&foo->misc, my_struct_destroy);
1372 * ]|
1373 *
1374 * Since: 0.11.7
1375 */
1376
1377 /**
1378 * tp_clear_boxed: (skip)
1379 * @gtype: (type GObject.Type): the #GType of *@pp, e.g. %G_TYPE_HASH_TABLE
1380 * @pp: a pointer to a variable, struct member etc. holding a boxed object
1381 *
1382 * Set a variable holding a boxed object to %NULL. If it was not already %NULL,
1383 * destroy the boxed object it previously pointed to, as appropriate for
1384 * @gtype.
1385 *
1386 * More precisely, if *@pp is non-%NULL, set *@pp to %NULL, then
1387 * call g_boxed_free() on the object that *@pp previously pointed to.
1388 *
1389 * This is similar to tp_clear_pointer(); see that function's documentation
1390 * for typical usage.
1391 *
1392 * Since: 0.11.7
1393 */
1394
1395 /**
1396 * tp_simple_async_report_success_in_idle:
1397 * @source: (allow-none): the source object
1398 * @callback: (scope async): the callback
1399 * @user_data: (closure): user data for @callback
1400 * @source_tag: the source tag for the #GSimpleAsyncResult
1401 *
1402 * Create a new #GSimpleAsyncResult with no operation result, and call
1403 * g_simple_async_result_complete_in_idle() on it.
1404 *
1405 * This is like a successful version of g_simple_async_report_error_in_idle(),
1406 * suitable for asynchronous functions that (conceptually) either succeed and
1407 * return nothing, or raise an error, such as tp_proxy_prepare_async().
1408 *
1409 * The corresponding finish function should not call a function that attempts
1410 * to get a result, such as g_simple_async_result_get_op_res_gpointer().
1411 *
1412 * Since: 0.11.9
1413 */
1414 void
tp_simple_async_report_success_in_idle(GObject * source,GAsyncReadyCallback callback,gpointer user_data,gpointer source_tag)1415 tp_simple_async_report_success_in_idle (GObject *source,
1416 GAsyncReadyCallback callback,
1417 gpointer user_data,
1418 gpointer source_tag)
1419 {
1420 GSimpleAsyncResult *simple;
1421
1422 simple = g_simple_async_result_new (source, callback, user_data, source_tag);
1423 g_simple_async_result_complete_in_idle (simple);
1424 g_object_unref (simple);
1425 }
1426
1427 /**
1428 * tp_user_action_time_from_x11:
1429 * @x11_time: an X11 timestamp, or 0 to indicate the current time
1430 *
1431 * Convert an X11 timestamp into a user action time as used in Telepathy.
1432 *
1433 * This also works for the timestamps used by GDK 2, GDK 3 and Clutter 1.0;
1434 * it may or may not work with other toolkits or versions.
1435 *
1436 * Returns: a nonzero Telepathy user action time, or
1437 * %TP_USER_ACTION_TIME_CURRENT_TIME
1438 *
1439 * Since: 0.11.13
1440 */
1441 gint64
tp_user_action_time_from_x11(guint32 x11_time)1442 tp_user_action_time_from_x11 (guint32 x11_time)
1443 {
1444 if (x11_time == 0)
1445 {
1446 return TP_USER_ACTION_TIME_CURRENT_TIME;
1447 }
1448
1449 return x11_time;
1450 }
1451
1452 /**
1453 * tp_user_action_time_should_present:
1454 * @user_action_time: (type gint64): the Telepathy user action time
1455 * @x11_time: (out) (allow-none): a pointer to guint32 used to
1456 * return an X11 timestamp, or 0 to indicate the current time; if
1457 * %FALSE is returned, the value placed here is not meaningful
1458 *
1459 * Interpret a Telepathy user action time to decide whether a Handler should
1460 * attempt to gain focus. If %TRUE is returned, it would be appropriate to
1461 * call gtk_window_present_with_time() using @x11_time as input, for instance.
1462 *
1463 * @x11_time is used to return a timestamp in the right format for X11,
1464 * GDK 2, GDK 3 and Clutter 1.0; it may or may not work with other
1465 * toolkits or versions.
1466 *
1467 * Returns: %TRUE if it would be appropriate to present a window
1468 *
1469 * Since: 0.11.13
1470 */
1471
1472 gboolean
tp_user_action_time_should_present(gint64 user_action_time,guint32 * x11_time)1473 tp_user_action_time_should_present (gint64 user_action_time,
1474 guint32 *x11_time)
1475 {
1476 guint32 when = 0;
1477 gboolean ret;
1478
1479 if (user_action_time > 0 && user_action_time <= G_MAXUINT32)
1480 {
1481 when = (guint32) user_action_time;
1482 ret = TRUE;
1483 }
1484 else if (user_action_time == TP_USER_ACTION_TIME_CURRENT_TIME)
1485 {
1486 ret = TRUE;
1487 }
1488 else
1489 {
1490 ret = FALSE;
1491 }
1492
1493 if (ret && x11_time != NULL)
1494 *x11_time = when;
1495
1496 return ret;
1497 }
1498
1499 /* Add each of @quarks to @array if it isn't already present.
1500 *
1501 * There are @n quarks, or if @n == -1, the array is 0-terminated. */
1502 void
_tp_quark_array_merge(GArray * array,const GQuark * quarks,gssize n)1503 _tp_quark_array_merge (GArray *array,
1504 const GQuark *quarks,
1505 gssize n)
1506 {
1507 gssize i;
1508 guint j;
1509
1510 g_return_if_fail (array != NULL);
1511 g_return_if_fail (g_array_get_element_size (array) == sizeof (GQuark));
1512 g_return_if_fail (n >= -1);
1513 g_return_if_fail (n <= 0 || quarks != NULL);
1514
1515 if (quarks == NULL || n == 0)
1516 return;
1517
1518 if (n < 0)
1519 {
1520 n = 0;
1521
1522 for (i = 0; quarks[i] != 0; i++)
1523 n++;
1524 }
1525 else
1526 {
1527 for (i = 0; i < n; i++)
1528 g_return_if_fail (quarks[i] != 0);
1529 }
1530
1531 if (array->len == 0)
1532 {
1533 /* fast-path for the common case: there's nothing to merge with */
1534 g_array_append_vals (array, quarks, n);
1535 return;
1536 }
1537
1538 for (i = 0; i < n; i++)
1539 {
1540 for (j = 0; j < array->len; j++)
1541 {
1542 if (g_array_index (array, GQuark, j) == quarks[i])
1543 goto next_i;
1544 }
1545
1546 g_array_append_val (array, quarks[i]);
1547 next_i:
1548 continue;
1549 }
1550 }
1551
1552 /* Helper to implement functions with 0-terminated list of features in args */
1553 void
_tp_quark_array_merge_valist(GArray * array,GQuark feature,va_list var_args)1554 _tp_quark_array_merge_valist (GArray *array,
1555 GQuark feature,
1556 va_list var_args)
1557 {
1558 GArray *features;
1559 GQuark f;
1560
1561 features = g_array_new (FALSE, FALSE, sizeof (GQuark));
1562
1563 for (f = feature; f != 0; f = va_arg (var_args, GQuark))
1564 g_array_append_val (features, f);
1565
1566 _tp_quark_array_merge (array, (GQuark *) features->data, features->len);
1567
1568 g_array_unref (features);
1569 }
1570
1571 #ifdef HAVE_GIO_UNIX
1572 GSocketAddress *
_tp_create_temp_unix_socket(GSocketService * service,gchar ** tmpdir,GError ** error)1573 _tp_create_temp_unix_socket (GSocketService *service,
1574 gchar **tmpdir,
1575 GError **error)
1576 {
1577 GSocketAddress *address;
1578 gchar *dir = g_dir_make_tmp ("tp-glib-socket.XXXXXX", error);
1579 gchar *name;
1580
1581 if (dir == NULL)
1582 return NULL;
1583
1584 if (g_chmod (dir, 0700) != 0)
1585 {
1586 int e = errno;
1587
1588 g_set_error (error, G_IO_ERROR, g_io_error_from_errno (e),
1589 "unable to set permissions of %s to 0700: %s", dir,
1590 g_strerror (e));
1591 g_free (dir);
1592 return NULL;
1593 }
1594
1595 name = g_build_filename (dir, "s", NULL);
1596 address = g_unix_socket_address_new (name);
1597 g_free (name);
1598
1599 if (!g_socket_listener_add_address (G_SOCKET_LISTENER (service),
1600 address, G_SOCKET_TYPE_STREAM,
1601 G_SOCKET_PROTOCOL_DEFAULT,
1602 NULL, NULL, error))
1603 {
1604 g_object_unref (address);
1605 g_free (dir);
1606 return NULL;
1607 }
1608
1609 if (tmpdir != NULL)
1610 *tmpdir = dir;
1611 else
1612 g_free (dir);
1613
1614 return address;
1615 }
1616 #endif /* HAVE_GIO_UNIX */
1617
1618 GList *
_tp_create_channel_request_list(TpSimpleClientFactory * factory,GHashTable * request_props)1619 _tp_create_channel_request_list (TpSimpleClientFactory *factory,
1620 GHashTable *request_props)
1621 {
1622 GHashTableIter iter;
1623 GList *result = NULL;
1624 gpointer key, value;
1625
1626 g_hash_table_iter_init (&iter, request_props);
1627 while (g_hash_table_iter_next (&iter, &key, &value))
1628 {
1629 TpChannelRequest *req;
1630 const gchar *path = key;
1631 GHashTable *props = value;
1632 GError *error = NULL;
1633
1634 req = _tp_simple_client_factory_ensure_channel_request (factory, path,
1635 props, &error);
1636 if (req == NULL)
1637 {
1638 DEBUG ("Failed to create TpChannelRequest: %s", error->message);
1639 g_error_free (error);
1640 continue;
1641 }
1642
1643 result = g_list_prepend (result, req);
1644 }
1645
1646 return result;
1647 }
1648
1649 /**
1650 * tp_utf8_make_valid:
1651 * @name: string to coerce into UTF8
1652 *
1653 * Validate that the provided string is valid UTF8. If not,
1654 * replace all invalid bytes with unicode replacement
1655 * character (U+FFFD).
1656 *
1657 * This method is a verbatim copy of glib's internal
1658 * _g_utf8_make_valid<!-- -->() function, and will be deprecated as
1659 * soon as the glib one becomes public.
1660 *
1661 * Returns: (transfer full): a new valid UTF8 string
1662 *
1663 * Since: 0.13.15
1664 */
1665 gchar *
tp_utf8_make_valid(const gchar * name)1666 tp_utf8_make_valid (const gchar *name)
1667 {
1668 GString *string;
1669 const gchar *remainder, *invalid;
1670 gint remaining_bytes, valid_bytes;
1671
1672 g_return_val_if_fail (name != NULL, NULL);
1673
1674 string = NULL;
1675 remainder = name;
1676 remaining_bytes = strlen (name);
1677
1678 while (remaining_bytes != 0)
1679 {
1680 if (g_utf8_validate (remainder, remaining_bytes, &invalid))
1681 break;
1682 valid_bytes = invalid - remainder;
1683
1684 if (string == NULL)
1685 string = g_string_sized_new (remaining_bytes);
1686
1687 g_string_append_len (string, remainder, valid_bytes);
1688 /* append U+FFFD REPLACEMENT CHARACTER */
1689 g_string_append (string, "\357\277\275");
1690
1691 remaining_bytes -= valid_bytes + 1;
1692 remainder = invalid + 1;
1693 }
1694
1695 if (string == NULL)
1696 return g_strdup (name);
1697
1698 g_string_append (string, remainder);
1699
1700 g_assert (g_utf8_validate (string->str, -1, NULL));
1701
1702 return g_string_free (string, FALSE);
1703 }
1704
1705 /*
1706 * _tp_enum_from_nick:
1707 * @enum_type: the GType of a subtype of GEnum
1708 * @nick: a non-%NULL string purporting to be the nickname of a value of
1709 * @enum_type
1710 * @value: the address at which to store the value of @enum_type corresponding
1711 * to @nick if this functions returns %TRUE; if this function returns
1712 * %FALSE, this variable will be left untouched.
1713 *
1714 * <!-- -->
1715 *
1716 * Returns: %TRUE if @nick is a member of @enum_type, or %FALSE otherwise
1717 */
1718 gboolean
_tp_enum_from_nick(GType enum_type,const gchar * nick,gint * value)1719 _tp_enum_from_nick (
1720 GType enum_type,
1721 const gchar *nick,
1722 gint *value)
1723 {
1724 GEnumClass *klass = g_type_class_ref (enum_type);
1725 GEnumValue *enum_value;
1726
1727 g_return_val_if_fail (klass != NULL, FALSE);
1728 g_return_val_if_fail (value != NULL, FALSE);
1729
1730 enum_value = g_enum_get_value_by_nick (klass, nick);
1731 g_type_class_unref (klass);
1732
1733 if (enum_value != NULL)
1734 {
1735 *value = enum_value->value;
1736 return TRUE;
1737 }
1738 else
1739 {
1740 return FALSE;
1741 }
1742 }
1743
1744 /*
1745 * _tp_enum_to_nick:
1746 * @enum_type: the GType of a subtype of GEnum
1747 * @value: a value of @enum_type
1748 *
1749 * <!-- -->
1750 *
1751 * Returns: the nickname of @value, or %NULL if it is not, in fact, a value of
1752 * @enum_type
1753 */
1754 const gchar *
_tp_enum_to_nick(GType enum_type,gint value)1755 _tp_enum_to_nick (
1756 GType enum_type,
1757 gint value)
1758 {
1759 GEnumClass *klass = g_type_class_ref (enum_type);
1760 GEnumValue *enum_value;
1761
1762 g_return_val_if_fail (klass != NULL, NULL);
1763
1764 enum_value = g_enum_get_value (klass, value);
1765 g_type_class_unref (klass);
1766
1767 if (enum_value != NULL)
1768 return enum_value->value_nick;
1769 else
1770 return NULL;
1771 }
1772
1773 /*
1774 * _tp_enum_to_nick_nonnull:
1775 *
1776 * The same as _tp_enum_to_nick, but always returns non-NULL.
1777 */
1778 const gchar *
_tp_enum_to_nick_nonnull(GType enum_type,gint value)1779 _tp_enum_to_nick_nonnull (
1780 GType enum_type,
1781 gint value)
1782 {
1783 GEnumClass *klass = g_type_class_ref (enum_type);
1784 GEnumValue *enum_value;
1785
1786 g_return_val_if_fail (klass != NULL, "(incorrect class)");
1787
1788 enum_value = g_enum_get_value (klass, value);
1789 g_type_class_unref (klass);
1790
1791 if (enum_value == NULL)
1792 return "(out-of-range value)";
1793 else if (enum_value->value_nick == NULL)
1794 return "(value with no nickname)";
1795 else
1796 return enum_value->value_nick;
1797 }
1798
1799 gboolean
_tp_bind_connection_status_to_boolean(GBinding * binding,const GValue * src_value,GValue * dest_value,gpointer user_data)1800 _tp_bind_connection_status_to_boolean (GBinding *binding,
1801 const GValue *src_value,
1802 GValue *dest_value,
1803 gpointer user_data)
1804 {
1805 gboolean invert = GPOINTER_TO_UINT (user_data);
1806 gboolean value;
1807
1808 g_return_val_if_fail (G_VALUE_HOLDS_UINT (src_value), FALSE);
1809 g_return_val_if_fail (G_VALUE_HOLDS_BOOLEAN (dest_value), FALSE);
1810
1811 value = (g_value_get_uint (src_value) == TP_CONNECTION_STATUS_CONNECTED);
1812
1813 if (invert)
1814 value = !value;
1815
1816 g_value_set_boolean (dest_value, value);
1817
1818 return TRUE;
1819 }
1820
1821 /*
1822 * _tp_determine_socket_address_type:
1823 *
1824 * Determines the best available socket address type.
1825 *
1826 */
1827 static gboolean
_tp_determine_socket_address_type(GHashTable * supported_sockets,TpSocketAddressType * address_type,GError ** error)1828 _tp_determine_socket_address_type (GHashTable *supported_sockets,
1829 TpSocketAddressType *address_type,
1830 GError **error)
1831 {
1832 guint i;
1833 TpSocketAddressType types[] = {
1834 #ifdef HAVE_GIO_UNIX
1835 TP_SOCKET_ADDRESS_TYPE_UNIX,
1836 #endif /* HAVE_GIO_UNIX */
1837 TP_SOCKET_ADDRESS_TYPE_IPV4,
1838 TP_SOCKET_ADDRESS_TYPE_IPV6
1839 };
1840
1841 for (i = 0; i < G_N_ELEMENTS (types); i++)
1842 {
1843 GArray *arr = g_hash_table_lookup (supported_sockets,
1844 GUINT_TO_POINTER (types[i]));
1845
1846 if (arr != NULL)
1847 {
1848 *address_type = types[i];
1849 return TRUE;
1850 }
1851 }
1852
1853 /* This should never happen */
1854 g_set_error (error, TP_ERROR,
1855 TP_ERROR_NOT_IMPLEMENTED, "No supported socket types");
1856
1857 return FALSE;
1858 }
1859
1860 /*
1861 * _tp_determine_access_control_type:
1862 *
1863 * Determines the best available socket access control type, falling back to
1864 * TP_SOCKET_ACCESS_CONTROL_LOCALHOST if needed.
1865 *
1866 */
1867 static gboolean
_tp_determine_access_control_type(GHashTable * supported_sockets,TpSocketAddressType address_type,TpSocketAccessControl * access_control,GError ** error)1868 _tp_determine_access_control_type (GHashTable *supported_sockets,
1869 TpSocketAddressType address_type,
1870 TpSocketAccessControl *access_control,
1871 GError **error)
1872 {
1873 gboolean support_localhost = FALSE;
1874 GArray *arr;
1875 guint i;
1876
1877 arr = g_hash_table_lookup (supported_sockets,
1878 GUINT_TO_POINTER (address_type));
1879
1880 switch (address_type)
1881 {
1882 #ifdef HAVE_GIO_UNIX
1883 case TP_SOCKET_ADDRESS_TYPE_UNIX:
1884 case TP_SOCKET_ADDRESS_TYPE_ABSTRACT_UNIX:
1885 {
1886 /* Preferred order: credentials, localhost */
1887 for (i = 0; i < arr->len; i++)
1888 {
1889 TpSocketAccessControl _access = g_array_index (arr,
1890 TpSocketAccessControl, i);
1891
1892 if (_access == TP_SOCKET_ACCESS_CONTROL_CREDENTIALS)
1893 {
1894 *access_control = _access;
1895 return TRUE;
1896 }
1897 else if (_access == TP_SOCKET_ACCESS_CONTROL_LOCALHOST)
1898 {
1899 support_localhost = TRUE;
1900 }
1901 }
1902 }
1903 break;
1904 #else
1905 case TP_SOCKET_ADDRESS_TYPE_UNIX:
1906 case TP_SOCKET_ADDRESS_TYPE_ABSTRACT_UNIX:
1907 break;
1908 #endif
1909 case TP_SOCKET_ADDRESS_TYPE_IPV6:
1910 case TP_SOCKET_ADDRESS_TYPE_IPV4:
1911 {
1912 /* Preferred order: port, localhost */
1913 for (i = 0; i < arr->len; i++)
1914 {
1915 TpSocketAccessControl _access = g_array_index (arr,
1916 TpSocketAccessControl, i);
1917
1918 if (_access == TP_SOCKET_ACCESS_CONTROL_PORT)
1919 {
1920 *access_control = _access;
1921 return TRUE;
1922 }
1923 else if (_access == TP_SOCKET_ACCESS_CONTROL_LOCALHOST)
1924 {
1925 support_localhost = TRUE;
1926 }
1927 }
1928 }
1929 break;
1930 }
1931
1932 /* This should never happen */
1933 if (!support_localhost)
1934 {
1935 g_set_error (error, TP_ERROR,
1936 TP_ERROR_NOT_IMPLEMENTED, "No supported access control");
1937 return FALSE;
1938 }
1939
1940 *access_control = TP_SOCKET_ACCESS_CONTROL_LOCALHOST;
1941 return TRUE;
1942 }
1943
1944 gboolean
_tp_set_socket_address_type_and_access_control_type(GHashTable * supported_sockets,TpSocketAddressType * address_type,TpSocketAccessControl * access_control,GError ** error)1945 _tp_set_socket_address_type_and_access_control_type (
1946 GHashTable *supported_sockets,
1947 TpSocketAddressType *address_type,
1948 TpSocketAccessControl *access_control,
1949 GError **error)
1950 {
1951 g_return_val_if_fail (address_type != NULL, FALSE);
1952 g_return_val_if_fail (access_control != NULL, FALSE);
1953
1954 if (!_tp_determine_socket_address_type (supported_sockets, address_type,
1955 error))
1956 return FALSE;
1957
1958 return _tp_determine_access_control_type (supported_sockets,
1959 *address_type, access_control, error);
1960 }
1961
1962 GSocket *
_tp_create_client_socket(TpSocketAddressType socket_type,GError ** error)1963 _tp_create_client_socket (TpSocketAddressType socket_type,
1964 GError **error)
1965 {
1966 GSocket *client_socket;
1967 GSocketFamily family;
1968
1969 switch (socket_type)
1970 {
1971 #ifdef HAVE_GIO_UNIX
1972 case TP_SOCKET_ADDRESS_TYPE_UNIX:
1973 family = G_SOCKET_FAMILY_UNIX;
1974 break;
1975 #endif
1976
1977 case TP_SOCKET_ADDRESS_TYPE_IPV4:
1978 family = G_SOCKET_FAMILY_IPV4;
1979 break;
1980
1981 case TP_SOCKET_ADDRESS_TYPE_IPV6:
1982 family = G_SOCKET_FAMILY_IPV6;
1983 break;
1984
1985 default:
1986 g_assert_not_reached ();
1987 }
1988
1989 /* Create socket to connect to the CM. We use a GSocket and not a
1990 * GSocketClient because it creates the underlying socket when trying to
1991 * connect and we need to be able to get the local port (needed for
1992 * TP_SOCKET_ACCESS_CONTROL_PORT) of the socket before actually connecting. */
1993 client_socket = g_socket_new (family, G_SOCKET_TYPE_STREAM,
1994 G_SOCKET_PROTOCOL_DEFAULT, error);
1995 if (client_socket == NULL)
1996 return NULL;
1997
1998 if (socket_type == TP_SOCKET_ADDRESS_TYPE_IPV4 ||
1999 socket_type == TP_SOCKET_ADDRESS_TYPE_IPV6)
2000 {
2001 /* Bind local address. This is needed to be able to get the local port
2002 * of the socket and pass it to the CM when using
2003 * TP_SOCKET_ACCESS_CONTROL_PORT. */
2004 GSocketAddress *local_address;
2005 GInetAddress *tmp;
2006 gboolean success;
2007
2008 tmp = g_inet_address_new_any (family);
2009 local_address = g_inet_socket_address_new (tmp, 0);
2010
2011 success = g_socket_bind (client_socket, local_address,
2012 TRUE, error);
2013
2014 g_object_unref (tmp);
2015 g_object_unref (local_address);
2016
2017 if (!success)
2018 return NULL;
2019 }
2020
2021 return client_socket;
2022 }
2023
2024 gboolean
_tp_contacts_to_handles(TpConnection * connection,guint n_contacts,TpContact * const * contacts,GArray ** handles)2025 _tp_contacts_to_handles (TpConnection *connection,
2026 guint n_contacts,
2027 TpContact * const *contacts,
2028 GArray **handles)
2029 {
2030 guint i;
2031
2032 g_return_val_if_fail (handles != NULL, FALSE);
2033 g_return_val_if_fail (n_contacts > 0, FALSE);
2034
2035 *handles = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), n_contacts);
2036
2037 for (i = 0; i < n_contacts; i++)
2038 {
2039 TpHandle handle;
2040
2041 if (!TP_IS_CONTACT (contacts[i]) ||
2042 tp_contact_get_connection (contacts[i]) != connection)
2043 {
2044 tp_clear_pointer (handles, g_array_unref);
2045 return FALSE;
2046 }
2047
2048 handle = tp_contact_get_handle (contacts[i]);
2049 g_array_append_val (*handles, handle);
2050 }
2051
2052 return TRUE;
2053 }
2054
2055 /* table's key can be anything (usually TpHandle) but value must be a
2056 * TpContact */
2057 GPtrArray *
_tp_contacts_from_values(GHashTable * table)2058 _tp_contacts_from_values (GHashTable *table)
2059 {
2060 GPtrArray *contacts;
2061 GHashTableIter iter;
2062 gpointer value;
2063
2064 if (table == NULL)
2065 return NULL;
2066
2067 contacts = g_ptr_array_new_full (g_hash_table_size (table),
2068 g_object_unref);
2069
2070 g_hash_table_iter_init (&iter, table);
2071 while (g_hash_table_iter_next (&iter, NULL, &value))
2072 {
2073 if (value == NULL)
2074 continue;
2075 g_assert (TP_IS_CONTACT (value));
2076
2077 g_ptr_array_add (contacts, g_object_ref (value));
2078 }
2079
2080 return contacts;
2081 }
2082
2083 /*
2084 * @l: (transfer none) (element-type GLib.Object): a list of #GObject or
2085 * any subclass
2086 *
2087 * Returns: (transfer full): a copy of @l
2088 */
2089 GList *
_tp_object_list_copy(GList * l)2090 _tp_object_list_copy (GList *l)
2091 {
2092 return _tp_g_list_copy_deep (l, (GCopyFunc) g_object_ref, NULL);
2093 }
2094
2095 /*
2096 * @l: (transfer full) (element-type GLib.Object): a list of #GObject or
2097 * any subclass
2098 *
2099 * Unref each item of @l and free the list.
2100 *
2101 * This function can be cast to #GDestroyNotify.
2102 */
2103 void
_tp_object_list_free(GList * l)2104 _tp_object_list_free (GList *l)
2105 {
2106 g_list_free_full (l, g_object_unref);
2107 }
2108
2109 GList *
_tp_g_list_copy_deep(GList * list,GCopyFunc func,gpointer user_data)2110 _tp_g_list_copy_deep (GList *list,
2111 GCopyFunc func,
2112 gpointer user_data)
2113 {
2114 GList *ret = NULL;
2115 GList *l;
2116
2117 ret = g_list_copy (list);
2118
2119 if (func != NULL)
2120 {
2121 for (l = ret; l != NULL; l = l->next)
2122 l->data = func (l->data, user_data);
2123 }
2124
2125 return ret;
2126 }
2127
2128 /**
2129 * tp_value_array_free:
2130 * @va: a #GValueArray
2131 *
2132 * Free @va. This is exactly the same as g_value_array_free(), but does not
2133 * provoke deprecation warnings from GLib when used in conjunction with
2134 * tp_value_array_build() and tp_value_array_unpack().
2135 *
2136 * Since: 0.23.0
2137 */
2138 void
2139 (tp_value_array_free) (GValueArray *va)
2140 {
2141 _tp_value_array_free_inline (va);
2142 }
2143