Codebase list telepathy-glib / d1d2203
GVariant: Add tp_vardict_get_foo() similar to tp_asv_get_foo() Xavier Claessens 11 years ago
4 changed file(s) with 556 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
1919 <xi:include href="xml/proxy-tp-properties.xml"/>
2020 <xi:include href="xml/dbus.xml"/>
2121 <xi:include href="xml/asv.xml"/>
22 <xi:include href="xml/variant-util.xml"/>
23 <xi:include href="xml/vardict.xml"/>
2224 <xi:include href="xml/proxy-subclass.xml"/>
2325 </chapter>
2426 <chapter id="ch-protocol">
24642464 tp_asv_set_uint64
24652465 tp_asv_lookup
24662466 tp_asv_dump
2467 </SECTION>
2468
2469 <SECTION>
2470 <FILE>variant-util</FILE>
2471 <TITLE>variant-util</TITLE>
2472 <INCLUDE>telepathy-glib/telepathy-glib.h</INCLUDE>
2473 tp_variant_type_classify
2474 tp_variant_convert
2475 </SECTION>
2476
2477 <SECTION>
2478 <FILE>vardict</FILE>
2479 <TITLE>vardict</TITLE>
2480 <INCLUDE>telepathy-glib/telepathy-glib.h</INCLUDE>
2481 tp_vardict_get_boolean
2482 tp_vardict_get_double
2483 tp_vardict_get_int32
2484 tp_vardict_get_int64
2485 tp_vardict_get_object_path
2486 tp_vardict_get_string
2487 tp_vardict_get_uint32
2488 tp_vardict_get_uint64
24672489 </SECTION>
24682490
24692491 <SECTION>
2626 */
2727
2828 /**
29 * SECTION:vardic
29 * SECTION:vardict
3030 * @title: Manipulating a{sv} mappings
3131 * @short_description: Functions to manipulate mappings from string to
32 * variant, as represented in GDBus by a %G_VARIANT_TYPE_VARDICT
32 * variant, as represented in GVariant by a %G_VARIANT_TYPE_VARDICT
3333 *
3434 * These functions provide convenient access to the values in such
3535 * a mapping.
105105 g_value_unset (&v);
106106 return result;
107107 }
108
109 /**
110 * tp_variant_type_classify:
111 * @type: a #GVariantType
112 *
113 * Classifies @type according to its top-level type.
114 *
115 * Returns: the #GVariantClass of @type
116 * Since: 0.UNRELEASED
117 **/
118 GVariantClass
119 tp_variant_type_classify (const GVariantType *type)
120 {
121 /* Same as g_variant_classify() but for a GVariantType. This returns the first
122 * letter of the dbus type and cast it to an enum where elements have the
123 * ascii value of the type letters. */
124 return g_variant_type_peek_string (type)[0];
125 }
126
127 static gdouble
128 _tp_variant_convert_double (GVariant *variant,
129 gboolean *valid)
130 {
131 *valid = TRUE;
132
133 switch (g_variant_classify (variant))
134 {
135 case G_VARIANT_CLASS_DOUBLE:
136 return g_variant_get_double (variant);
137
138 case G_VARIANT_CLASS_BYTE:
139 return g_variant_get_byte (variant);
140
141 case G_VARIANT_CLASS_UINT32:
142 return g_variant_get_uint32 (variant);
143
144 case G_VARIANT_CLASS_INT32:
145 return g_variant_get_int32 (variant);
146
147 case G_VARIANT_CLASS_INT64:
148 return g_variant_get_int64 (variant);
149
150 case G_VARIANT_CLASS_UINT64:
151 return g_variant_get_uint64 (variant);
152
153 default:
154 break;
155 }
156
157 *valid = FALSE;
158 return 0.0;
159 }
160
161 static gint32
162 _tp_variant_convert_int32 (GVariant *variant,
163 gboolean *valid)
164 {
165 gint64 i;
166 guint64 u;
167
168 *valid = TRUE;
169
170 switch (g_variant_classify (variant))
171 {
172 case G_VARIANT_CLASS_BYTE:
173 return g_variant_get_byte (variant);
174
175 case G_VARIANT_CLASS_UINT32:
176 u = g_variant_get_uint32 (variant);
177 if (G_LIKELY (u <= G_MAXINT32))
178 return u;
179 break;
180
181 case G_VARIANT_CLASS_INT32:
182 return g_variant_get_int32 (variant);
183
184 case G_VARIANT_CLASS_INT64:
185 i = g_variant_get_int64 (variant);
186 if (G_LIKELY (i >= G_MININT32 && i <= G_MAXINT32))
187 return i;
188 break;
189
190 case G_VARIANT_CLASS_UINT64:
191 u = g_variant_get_uint64 (variant);
192 if (G_LIKELY (u <= G_MAXINT32))
193 return u;
194 break;
195
196 default:
197 break;
198 }
199
200 *valid = FALSE;
201 return 0;
202 }
203
204 static gint64
205 _tp_variant_convert_int64 (GVariant *variant,
206 gboolean *valid)
207 {
208 guint64 u;
209
210 *valid = TRUE;
211
212 switch (g_variant_classify (variant))
213 {
214 case G_VARIANT_CLASS_BYTE:
215 return g_variant_get_byte (variant);
216
217 case G_VARIANT_CLASS_UINT32:
218 return g_variant_get_uint32 (variant);
219
220 case G_VARIANT_CLASS_INT32:
221 return g_variant_get_int32 (variant);
222
223 case G_VARIANT_CLASS_INT64:
224 return g_variant_get_int64 (variant);
225
226 case G_VARIANT_CLASS_UINT64:
227 u = g_variant_get_uint64 (variant);
228 if (G_LIKELY (u <= G_MAXINT64))
229 return u;
230 break;
231
232 default:
233 break;
234 }
235
236 *valid = FALSE;
237 return 0;
238 }
239
240 static guint32
241 _tp_variant_convert_uint32 (GVariant *variant,
242 gboolean *valid)
243 {
244 gint64 i;
245 guint64 u;
246
247 *valid = TRUE;
248
249 switch (g_variant_classify (variant))
250 {
251 case G_VARIANT_CLASS_BYTE:
252 return g_variant_get_byte (variant);
253
254 case G_VARIANT_CLASS_UINT32:
255 return g_variant_get_uint32 (variant);
256
257 case G_VARIANT_CLASS_INT32:
258 i = g_variant_get_int32 (variant);
259 if (G_LIKELY (i >= 0))
260 return i;
261 break;
262
263 case G_VARIANT_CLASS_INT64:
264 i = g_variant_get_int64 (variant);
265 if (G_LIKELY (i >= 0 && i <= G_MAXUINT32))
266 return i;
267 break;
268
269 case G_VARIANT_CLASS_UINT64:
270 u = g_variant_get_uint64 (variant);
271 if (G_LIKELY (u <= G_MAXUINT32))
272 return u;
273 break;
274
275 default:
276 break;
277 }
278
279 *valid = FALSE;
280 return 0;
281 }
282
283 static guint64
284 _tp_variant_convert_uint64 (GVariant *variant,
285 gboolean *valid)
286 {
287 gint64 tmp;
288
289 *valid = TRUE;
290
291 switch (g_variant_classify (variant))
292 {
293 case G_VARIANT_CLASS_BYTE:
294 return g_variant_get_byte (variant);
295
296 case G_VARIANT_CLASS_UINT32:
297 return g_variant_get_uint32 (variant);
298
299 case G_VARIANT_CLASS_INT32:
300 tmp = g_variant_get_int32 (variant);
301 if (G_LIKELY (tmp >= 0))
302 return tmp;
303 break;
304
305 case G_VARIANT_CLASS_INT64:
306 tmp = g_variant_get_int64 (variant);
307 if (G_LIKELY (tmp >= 0))
308 return tmp;
309 break;
310
311 case G_VARIANT_CLASS_UINT64:
312 return g_variant_get_uint64 (variant);
313
314 default:
315 break;
316 }
317
318 *valid = FALSE;
319 return 0;
320 }
321
322 /**
323 * tp_variant_convert:
324 * @variant: (transfer full): a #GVariant to convert
325 * @type: a #GVariantType @variant must be converted to
326 *
327 * Convert the type of @variant to @type if possible. This takes ownership of
328 * @variant. If no conversion is needed, simply return @variant. If conversion
329 * is not possible, %NULL is returned.
330 *
331 * Returns: (transfer full): a new #GVariant owned by the caller.
332 * Since: 0.UNRELEASED
333 **/
334 GVariant *
335 tp_variant_convert (GVariant *variant,
336 const GVariantType *type)
337 {
338 GVariant *ret = NULL;
339 gboolean valid;
340
341 if (variant == NULL)
342 return NULL;
343
344 g_variant_ref_sink (variant);
345
346 if (g_variant_is_of_type (variant, type))
347 return variant;
348
349 switch (tp_variant_type_classify (type))
350 {
351 #define CASE(type) \
352 { \
353 g##type tmp = _tp_variant_convert_##type (variant, &valid); \
354 if (valid) \
355 ret = g_variant_new_##type (tmp); \
356 }
357 case G_VARIANT_CLASS_DOUBLE:
358 CASE (double);
359 break;
360
361 case G_VARIANT_CLASS_INT32:
362 CASE (int32);
363 break;
364
365 case G_VARIANT_CLASS_INT64:
366 CASE (int64);
367 break;
368
369 case G_VARIANT_CLASS_UINT32:
370 CASE (uint32);
371 break;
372
373 case G_VARIANT_CLASS_UINT64:
374 CASE (uint64);
375 break;
376
377 default:
378 break;
379 #undef CASE
380 }
381
382 g_variant_unref (variant);
383
384 return (ret != NULL) ? g_variant_ref_sink (ret) : NULL;
385 }
386
387 /**
388 * tp_vardict_get_string:
389 * @variant: a #GVariant of type %G_VARIANT_TYPE_VARDICT
390 * @key: The key to look up
391 *
392 * If a value for @key in @variant is present and is a string, return it.
393 *
394 * Otherwise return %NULL.
395 *
396 * The returned value is not copied, and is only valid as long as @variant is
397 * kept. Copy it with g_strdup() if you need to keep it for longer.
398 *
399 * Returns: (transfer none) (allow-none): the string value of @key, or %NULL
400 * Since: 0.UNRELEASED
401 */
402 const gchar *
403 tp_vardict_get_string (GVariant *variant,
404 const gchar *key)
405 {
406 const gchar *ret;
407
408 g_return_val_if_fail (variant != NULL, NULL);
409 g_return_val_if_fail (key != NULL, NULL);
410 g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), NULL);
411
412 if (!g_variant_lookup (variant, key, "&s", &ret))
413 return NULL;
414
415 return ret;
416 }
417
418 /**
419 * tp_vardict_get_object_path:
420 * @variant: a #GVariant of type %G_VARIANT_TYPE_VARDICT
421 * @key: The key to look up
422 *
423 * If a value for @key in @variant is present and is an object path, return it.
424 *
425 * Otherwise return %NULL.
426 *
427 * The returned value is not copied, and is only valid as long as @variant is
428 * kept. Copy it with g_strdup() if you need to keep it for longer.
429 *
430 * Returns: (transfer none) (allow-none): the object path value of @key, or
431 * %NULL
432 * Since: 0.UNRELEASED
433 */
434 const gchar *
435 tp_vardict_get_object_path (GVariant *variant,
436 const gchar *key)
437 {
438 const gchar *ret;
439
440 g_return_val_if_fail (variant != NULL, NULL);
441 g_return_val_if_fail (key != NULL, NULL);
442 g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), NULL);
443
444 if (!g_variant_lookup (variant, key, "&o", &ret))
445 return NULL;
446
447 return ret;
448 }
449
450 /**
451 * tp_vardict_get_boolean:
452 * @variant: a #GVariant of type %G_VARIANT_TYPE_VARDICT
453 * @key: The key to look up
454 * @valid: (out): Either %NULL, or a location to store %TRUE if the key actually
455 * exists and has a boolean value
456 *
457 * If a value for @key in @variant is present and boolean, return it,
458 * and set *@valid to %TRUE if @valid is not %NULL.
459 *
460 * Otherwise return %FALSE, and set *@valid to %FALSE if @valid is not %NULL.
461 *
462 * Returns: a boolean value for @key
463 * Since: 0.UNRELEASED
464 */
465 gboolean
466 tp_vardict_get_boolean (GVariant *variant,
467 const gchar *key,
468 gboolean *valid)
469 {
470 gboolean ret;
471
472 g_return_val_if_fail (variant != NULL, FALSE);
473 g_return_val_if_fail (key != NULL, FALSE);
474 g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), FALSE);
475
476 if (!g_variant_lookup (variant, key, "b", &ret))
477 {
478 if (valid != NULL)
479 *valid = FALSE;
480
481 return FALSE;
482 }
483
484 if (valid != NULL)
485 *valid = TRUE;
486
487 return ret;
488 }
489
490 #define IMPLEMENT(type) \
491 g##type \
492 tp_vardict_get_##type (GVariant *variant, \
493 const gchar *key, \
494 gboolean *valid) \
495 { \
496 g##type ret = 0; \
497 gboolean ret_valid = FALSE; \
498 GVariant *value; \
499 \
500 g_return_val_if_fail (variant != NULL, 0); \
501 g_return_val_if_fail (key != NULL, 0); \
502 g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), 0); \
503 \
504 value = g_variant_lookup_value (variant, key, NULL); \
505 if (value != NULL) \
506 { \
507 ret = _tp_variant_convert_##type (value, &ret_valid); \
508 g_variant_unref (value); \
509 } \
510 \
511 if (valid != NULL) \
512 *valid = ret_valid; \
513 \
514 return ret; \
515 }
516
517 /**
518 * tp_vardict_get_double:
519 * @variant: a #GVariant of type %G_VARIANT_TYPE_VARDICT
520 * @key: The key to look up
521 * @valid: (out): Either %NULL, or a location in which to store %TRUE on success
522 * or %FALSE on failure
523 *
524 * If a value for @key in @variant is present and has any numeric type used by
525 * GVariant (gint32, guint32, gint64, guint64 or gdouble),
526 * return it as a double, and if @valid is not %NULL, set *@valid to %TRUE.
527 *
528 * Otherwise, return 0.0, and if @valid is not %NULL, set *@valid to %FALSE.
529 *
530 * Returns: the double precision floating-point value of @key, or 0.0
531 * Since: 0.UNRELEASED
532 */
533 IMPLEMENT (double)
534
535 /**
536 * tp_vardict_get_int32:
537 * @variant: a #GVariant of type %G_VARIANT_TYPE_VARDICT
538 * @key: The key to look up
539 * @valid: (out): Either %NULL, or a location in which to store %TRUE on success
540 * or %FALSE on failure
541 *
542 * If a value for @key in @variant is present, has an integer type used by
543 * GVariant (gint32, guint32, gint64 or guint64) and fits in the
544 * range of a gint32, return it, and if @valid is not %NULL, set *@valid to
545 * %TRUE.
546 *
547 * Otherwise, return 0, and if @valid is not %NULL, set *@valid to %FALSE.
548 *
549 * Returns: the 32-bit signed integer value of @key, or 0
550 * Since: 0.UNRELEASED
551 */
552 IMPLEMENT (int32)
553
554 /**
555 * tp_vardict_get_int64:
556 * @variant: a #GVariant of type %G_VARIANT_TYPE_VARDICT
557 * @key: The key to look up
558 * @valid: (out): Either %NULL, or a location in which to store %TRUE on success
559 * or %FALSE on failure
560 *
561 * If a value for @key in @variant is present, has an integer type used by
562 * GVariant (gint32, guint32, gint64 or guint64) and fits in the
563 * range of a gint64, return it, and if @valid is not %NULL, set *@valid to
564 * %TRUE.
565 *
566 * Otherwise, return 0, and if @valid is not %NULL, set *@valid to %FALSE.
567 *
568 * Returns: the 64-bit signed integer value of @key, or 0
569 * Since: 0.UNRELEASED
570 */
571 IMPLEMENT (int64)
572
573 /**
574 * tp_vardict_get_uint32:
575 * @variant: a #GVariant of type %G_VARIANT_TYPE_VARDICT
576 * @key: The key to look up
577 * @valid: (out): Either %NULL, or a location in which to store %TRUE on success
578 * or %FALSE on failure
579 *
580 * If a value for @key in @variant is present, has an integer type used by
581 * GVariant (gint32, guint32, gint64 or guint64) and fits in the
582 * range of a guint32, return it, and if @valid is not %NULL, set *@valid to
583 * %TRUE.
584 *
585 * Otherwise, return 0, and if @valid is not %NULL, set *@valid to %FALSE.
586 *
587 * Returns: the 32-bit unsigned integer value of @key, or 0
588 * Since: 0.UNRELEASED
589 */
590 IMPLEMENT (uint32)
591
592 /**
593 * tp_vardict_get_uint64:
594 * @variant: a #GVariant of type %G_VARIANT_TYPE_VARDICT
595 * @key: The key to look up
596 * @valid: (out): Either %NULL, or a location in which to store %TRUE on success
597 * or %FALSE on failure
598 *
599 * If a value for @key in @variant is present, has an integer type used by
600 * GVariant (gint32, guint32, gint64 or guint64) and is non-negative,
601 * return it, and if @valid is not %NULL, set *@valid to %TRUE.
602 *
603 * Otherwise, return 0, and if @valid is not %NULL, set *@valid to %FALSE.
604 *
605 * Returns: the 64-bit unsigned integer value of @key, or 0
606 * Since: 0.UNRELEASED
607 */
608 IMPLEMENT (uint64)
609
610 #undef IMPLEMENT
2929
3030 G_BEGIN_DECLS
3131
32 GVariantClass tp_variant_type_classify (const GVariantType *type);
33
34 GVariant *tp_variant_convert (GVariant *variant,
35 const GVariantType *type);
36
37 const gchar *tp_vardict_get_string (GVariant *variant,
38 const gchar *key);
39 const gchar *tp_vardict_get_object_path (GVariant *variant,
40 const gchar *key);
41 gboolean tp_vardict_get_boolean (GVariant *variant,
42 const gchar *key,
43 gboolean *valid);
44 gdouble tp_vardict_get_double (GVariant *variant,
45 const gchar *key,
46 gboolean *valid);
47 gint32 tp_vardict_get_int32 (GVariant *variant,
48 const gchar *key,
49 gboolean *valid);
50 gint64 tp_vardict_get_int64 (GVariant *variant,
51 const gchar *key,
52 gboolean *valid);
53 guint32 tp_vardict_get_uint32 (GVariant *variant,
54 const gchar *key,
55 gboolean *valid);
56 guint64 tp_vardict_get_uint64 (GVariant *variant,
57 const gchar *key,
58 gboolean *valid);
3259
3360 G_END_DECLS
3461