nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * Copyright © 2007, 2008 Ryan Lortie |
||
3 | * Copyright © 2009, 2010 Codethink Limited |
||
4 | * |
||
5 | * This library is free software; you can redistribute it and/or |
||
6 | * modify it under the terms of the GNU Lesser General Public |
||
7 | * License as published by the Free Software Foundation; either |
||
8 | * version 2 of the licence, or (at your option) any later version. |
||
9 | * |
||
10 | * This library is distributed in the hope that it will be useful, |
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
13 | * Lesser General Public License for more details. |
||
14 | * |
||
15 | * You should have received a copy of the GNU Lesser General Public |
||
16 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
||
17 | * |
||
18 | * Author: Ryan Lortie <desrt@desrt.ca> |
||
19 | */ |
||
20 | |||
21 | #include "config.h" |
||
22 | |||
23 | #include "gvarianttype.h" |
||
24 | |||
25 | #include <glib/gtestutils.h> |
||
26 | #include <glib/gstrfuncs.h> |
||
27 | |||
28 | #include <string.h> |
||
29 | |||
30 | |||
31 | /** |
||
32 | * SECTION:gvarianttype |
||
33 | * @title: GVariantType |
||
34 | * @short_description: introduction to the GVariant type system |
||
35 | * @see_also: #GVariantType, #GVariant |
||
36 | * |
||
37 | * This section introduces the GVariant type system. It is based, in |
||
38 | * large part, on the D-Bus type system, with two major changes and |
||
39 | * some minor lifting of restrictions. The |
||
40 | * [D-Bus specification](http://dbus.freedesktop.org/doc/dbus-specification.html), |
||
41 | * therefore, provides a significant amount of |
||
42 | * information that is useful when working with GVariant. |
||
43 | * |
||
44 | * The first major change with respect to the D-Bus type system is the |
||
45 | * introduction of maybe (or "nullable") types. Any type in GVariant can be |
||
46 | * converted to a maybe type, in which case, "nothing" (or "null") becomes a |
||
47 | * valid value. Maybe types have been added by introducing the |
||
48 | * character "m" to type strings. |
||
49 | * |
||
50 | * The second major change is that the GVariant type system supports the |
||
51 | * concept of "indefinite types" -- types that are less specific than |
||
52 | * the normal types found in D-Bus. For example, it is possible to speak |
||
53 | * of "an array of any type" in GVariant, where the D-Bus type system |
||
54 | * would require you to speak of "an array of integers" or "an array of |
||
55 | * strings". Indefinite types have been added by introducing the |
||
56 | * characters "*", "?" and "r" to type strings. |
||
57 | * |
||
58 | * Finally, all arbitrary restrictions relating to the complexity of |
||
59 | * types are lifted along with the restriction that dictionary entries |
||
60 | * may only appear nested inside of arrays. |
||
61 | * |
||
62 | * Just as in D-Bus, GVariant types are described with strings ("type |
||
63 | * strings"). Subject to the differences mentioned above, these strings |
||
64 | * are of the same form as those found in DBus. Note, however: D-Bus |
||
65 | * always works in terms of messages and therefore individual type |
||
66 | * strings appear nowhere in its interface. Instead, "signatures" |
||
67 | * are a concatenation of the strings of the type of each argument in a |
||
68 | * message. GVariant deals with single values directly so GVariant type |
||
69 | * strings always describe the type of exactly one value. This means |
||
70 | * that a D-Bus signature string is generally not a valid GVariant type |
||
71 | * string -- except in the case that it is the signature of a message |
||
72 | * containing exactly one argument. |
||
73 | * |
||
74 | * An indefinite type is similar in spirit to what may be called an |
||
75 | * abstract type in other type systems. No value can exist that has an |
||
76 | * indefinite type as its type, but values can exist that have types |
||
77 | * that are subtypes of indefinite types. That is to say, |
||
78 | * g_variant_get_type() will never return an indefinite type, but |
||
79 | * calling g_variant_is_of_type() with an indefinite type may return |
||
80 | * %TRUE. For example, you cannot have a value that represents "an |
||
81 | * array of no particular type", but you can have an "array of integers" |
||
82 | * which certainly matches the type of "an array of no particular type", |
||
83 | * since "array of integers" is a subtype of "array of no particular |
||
84 | * type". |
||
85 | * |
||
86 | * This is similar to how instances of abstract classes may not |
||
87 | * directly exist in other type systems, but instances of their |
||
88 | * non-abstract subtypes may. For example, in GTK, no object that has |
||
89 | * the type of #GtkBin can exist (since #GtkBin is an abstract class), |
||
90 | * but a #GtkWindow can certainly be instantiated, and you would say |
||
91 | * that the #GtkWindow is a #GtkBin (since #GtkWindow is a subclass of |
||
92 | * #GtkBin). |
||
93 | * |
||
94 | * ## GVariant Type Strings |
||
95 | * |
||
96 | * A GVariant type string can be any of the following: |
||
97 | * |
||
98 | * - any basic type string (listed below) |
||
99 | * |
||
100 | * - "v", "r" or "*" |
||
101 | * |
||
102 | * - one of the characters 'a' or 'm', followed by another type string |
||
103 | * |
||
104 | * - the character '(', followed by a concatenation of zero or more other |
||
105 | * type strings, followed by the character ')' |
||
106 | * |
||
107 | * - the character '{', followed by a basic type string (see below), |
||
108 | * followed by another type string, followed by the character '}' |
||
109 | * |
||
110 | * A basic type string describes a basic type (as per |
||
111 | * g_variant_type_is_basic()) and is always a single character in length. |
||
112 | * The valid basic type strings are "b", "y", "n", "q", "i", "u", "x", "t", |
||
113 | * "h", "d", "s", "o", "g" and "?". |
||
114 | * |
||
115 | * The above definition is recursive to arbitrary depth. "aaaaai" and |
||
116 | * "(ui(nq((y)))s)" are both valid type strings, as is |
||
117 | * "a(aa(ui)(qna{ya(yd)}))". |
||
118 | * |
||
119 | * The meaning of each of the characters is as follows: |
||
120 | * - `b`: the type string of %G_VARIANT_TYPE_BOOLEAN; a boolean value. |
||
121 | * - `y`: the type string of %G_VARIANT_TYPE_BYTE; a byte. |
||
122 | * - `n`: the type string of %G_VARIANT_TYPE_INT16; a signed 16 bit integer. |
||
123 | * - `q`: the type string of %G_VARIANT_TYPE_UINT16; an unsigned 16 bit integer. |
||
124 | * - `i`: the type string of %G_VARIANT_TYPE_INT32; a signed 32 bit integer. |
||
125 | * - `u`: the type string of %G_VARIANT_TYPE_UINT32; an unsigned 32 bit integer. |
||
126 | * - `x`: the type string of %G_VARIANT_TYPE_INT64; a signed 64 bit integer. |
||
127 | * - `t`: the type string of %G_VARIANT_TYPE_UINT64; an unsigned 64 bit integer. |
||
128 | * - `h`: the type string of %G_VARIANT_TYPE_HANDLE; a signed 32 bit value |
||
129 | * that, by convention, is used as an index into an array of file |
||
130 | * descriptors that are sent alongside a D-Bus message. |
||
131 | * - `d`: the type string of %G_VARIANT_TYPE_DOUBLE; a double precision |
||
132 | * floating point value. |
||
133 | * - `s`: the type string of %G_VARIANT_TYPE_STRING; a string. |
||
134 | * - `o`: the type string of %G_VARIANT_TYPE_OBJECT_PATH; a string in the form |
||
135 | * of a D-Bus object path. |
||
136 | * - `g`: the type string of %G_VARIANT_TYPE_STRING; a string in the form of |
||
137 | * a D-Bus type signature. |
||
138 | * - `?`: the type string of %G_VARIANT_TYPE_BASIC; an indefinite type that |
||
139 | * is a supertype of any of the basic types. |
||
140 | * - `v`: the type string of %G_VARIANT_TYPE_VARIANT; a container type that |
||
141 | * contain any other type of value. |
||
142 | * - `a`: used as a prefix on another type string to mean an array of that |
||
143 | * type; the type string "ai", for example, is the type of an array of |
||
144 | * signed 32-bit integers. |
||
145 | * - `m`: used as a prefix on another type string to mean a "maybe", or |
||
146 | * "nullable", version of that type; the type string "ms", for example, |
||
147 | * is the type of a value that maybe contains a string, or maybe contains |
||
148 | * nothing. |
||
149 | * - `()`: used to enclose zero or more other concatenated type strings to |
||
150 | * create a tuple type; the type string "(is)", for example, is the type of |
||
151 | * a pair of an integer and a string. |
||
152 | * - `r`: the type string of %G_VARIANT_TYPE_TUPLE; an indefinite type that is |
||
153 | * a supertype of any tuple type, regardless of the number of items. |
||
154 | * - `{}`: used to enclose a basic type string concatenated with another type |
||
155 | * string to create a dictionary entry type, which usually appears inside of |
||
156 | * an array to form a dictionary; the type string "a{sd}", for example, is |
||
157 | * the type of a dictionary that maps strings to double precision floating |
||
158 | * point values. |
||
159 | * |
||
160 | * The first type (the basic type) is the key type and the second type is |
||
161 | * the value type. The reason that the first type is restricted to being a |
||
162 | * basic type is so that it can easily be hashed. |
||
163 | * - `*`: the type string of %G_VARIANT_TYPE_ANY; the indefinite type that is |
||
164 | * a supertype of all types. Note that, as with all type strings, this |
||
165 | * character represents exactly one type. It cannot be used inside of tuples |
||
166 | * to mean "any number of items". |
||
167 | * |
||
168 | * Any type string of a container that contains an indefinite type is, |
||
169 | * itself, an indefinite type. For example, the type string "a*" |
||
170 | * (corresponding to %G_VARIANT_TYPE_ARRAY) is an indefinite type |
||
171 | * that is a supertype of every array type. "(*s)" is a supertype |
||
172 | * of all tuples that contain exactly two items where the second |
||
173 | * item is a string. |
||
174 | * |
||
175 | * "a{?*}" is an indefinite type that is a supertype of all arrays |
||
176 | * containing dictionary entries where the key is any basic type and |
||
177 | * the value is any type at all. This is, by definition, a dictionary, |
||
178 | * so this type string corresponds to %G_VARIANT_TYPE_DICTIONARY. Note |
||
179 | * that, due to the restriction that the key of a dictionary entry must |
||
180 | * be a basic type, "{**}" is not a valid type string. |
||
181 | */ |
||
182 | |||
183 | |||
184 | static gboolean |
||
185 | g_variant_type_check (const GVariantType *type) |
||
186 | { |
||
187 | if (type == NULL) |
||
188 | return FALSE; |
||
189 | |||
190 | #if 0 |
||
191 | return g_variant_type_string_scan ((const gchar *) type, NULL, NULL); |
||
192 | #else |
||
193 | return TRUE; |
||
194 | #endif |
||
195 | } |
||
196 | |||
197 | /** |
||
198 | * g_variant_type_string_scan: |
||
199 | * @string: a pointer to any string |
||
200 | * @limit: (allow-none): the end of @string, or %NULL |
||
201 | * @endptr: (out) (allow-none): location to store the end pointer, or %NULL |
||
202 | * |
||
203 | * Scan for a single complete and valid GVariant type string in @string. |
||
204 | * The memory pointed to by @limit (or bytes beyond it) is never |
||
205 | * accessed. |
||
206 | * |
||
207 | * If a valid type string is found, @endptr is updated to point to the |
||
208 | * first character past the end of the string that was found and %TRUE |
||
209 | * is returned. |
||
210 | * |
||
211 | * If there is no valid type string starting at @string, or if the type |
||
212 | * string does not end before @limit then %FALSE is returned. |
||
213 | * |
||
214 | * For the simple case of checking if a string is a valid type string, |
||
215 | * see g_variant_type_string_is_valid(). |
||
216 | * |
||
217 | * Returns: %TRUE if a valid type string was found |
||
218 | * |
||
219 | * Since: 2.24 |
||
220 | **/ |
||
221 | gboolean |
||
222 | g_variant_type_string_scan (const gchar *string, |
||
223 | const gchar *limit, |
||
224 | const gchar **endptr) |
||
225 | { |
||
226 | g_return_val_if_fail (string != NULL, FALSE); |
||
227 | |||
228 | if (string == limit || *string == '\0') |
||
229 | return FALSE; |
||
230 | |||
231 | switch (*string++) |
||
232 | { |
||
233 | case '(': |
||
234 | while (string == limit || *string != ')') |
||
235 | if (!g_variant_type_string_scan (string, limit, &string)) |
||
236 | return FALSE; |
||
237 | |||
238 | string++; |
||
239 | break; |
||
240 | |||
241 | case '{': |
||
242 | if (string == limit || *string == '\0' || /* { */ |
||
243 | !strchr ("bynqihuxtdsog?", *string++) || /* key */ |
||
244 | !g_variant_type_string_scan (string, limit, &string) || /* value */ |
||
245 | string == limit || *string++ != '}') /* } */ |
||
246 | return FALSE; |
||
247 | |||
248 | break; |
||
249 | |||
250 | case 'm': case 'a': |
||
251 | return g_variant_type_string_scan (string, limit, endptr); |
||
252 | |||
253 | case 'b': case 'y': case 'n': case 'q': case 'i': case 'u': |
||
254 | case 'x': case 't': case 'd': case 's': case 'o': case 'g': |
||
255 | case 'v': case 'r': case '*': case '?': case 'h': |
||
256 | break; |
||
257 | |||
258 | default: |
||
259 | return FALSE; |
||
260 | } |
||
261 | |||
262 | if (endptr != NULL) |
||
263 | *endptr = string; |
||
264 | |||
265 | return TRUE; |
||
266 | } |
||
267 | |||
268 | /** |
||
269 | * g_variant_type_string_is_valid: |
||
270 | * @type_string: a pointer to any string |
||
271 | * |
||
272 | * Checks if @type_string is a valid GVariant type string. This call is |
||
273 | * equivalent to calling g_variant_type_string_scan() and confirming |
||
274 | * that the following character is a nul terminator. |
||
275 | * |
||
276 | * Returns: %TRUE if @type_string is exactly one valid type string |
||
277 | * |
||
278 | * Since 2.24 |
||
279 | **/ |
||
280 | gboolean |
||
281 | g_variant_type_string_is_valid (const gchar *type_string) |
||
282 | { |
||
283 | const gchar *endptr; |
||
284 | |||
285 | g_return_val_if_fail (type_string != NULL, FALSE); |
||
286 | |||
287 | if (!g_variant_type_string_scan (type_string, NULL, &endptr)) |
||
288 | return FALSE; |
||
289 | |||
290 | return *endptr == '\0'; |
||
291 | } |
||
292 | |||
293 | /** |
||
294 | * g_variant_type_free: |
||
295 | * @type: (allow-none): a #GVariantType, or %NULL |
||
296 | * |
||
297 | * Frees a #GVariantType that was allocated with |
||
298 | * g_variant_type_copy(), g_variant_type_new() or one of the container |
||
299 | * type constructor functions. |
||
300 | * |
||
301 | * In the case that @type is %NULL, this function does nothing. |
||
302 | * |
||
303 | * Since 2.24 |
||
304 | **/ |
||
305 | void |
||
306 | g_variant_type_free (GVariantType *type) |
||
307 | { |
||
308 | g_return_if_fail (type == NULL || g_variant_type_check (type)); |
||
309 | |||
310 | g_free (type); |
||
311 | } |
||
312 | |||
313 | /** |
||
314 | * g_variant_type_copy: |
||
315 | * @type: a #GVariantType |
||
316 | * |
||
317 | * Makes a copy of a #GVariantType. It is appropriate to call |
||
318 | * g_variant_type_free() on the return value. @type may not be %NULL. |
||
319 | * |
||
320 | * Returns: (transfer full): a new #GVariantType |
||
321 | * |
||
322 | * Since 2.24 |
||
323 | **/ |
||
324 | GVariantType * |
||
325 | g_variant_type_copy (const GVariantType *type) |
||
326 | { |
||
327 | gsize length; |
||
328 | gchar *new; |
||
329 | |||
330 | g_return_val_if_fail (g_variant_type_check (type), NULL); |
||
331 | |||
332 | length = g_variant_type_get_string_length (type); |
||
333 | new = g_malloc (length + 1); |
||
334 | |||
335 | memcpy (new, type, length); |
||
336 | new[length] = '\0'; |
||
337 | |||
338 | return (GVariantType *) new; |
||
339 | } |
||
340 | |||
341 | /** |
||
342 | * g_variant_type_new: |
||
343 | * @type_string: a valid GVariant type string |
||
344 | * |
||
345 | * Creates a new #GVariantType corresponding to the type string given |
||
346 | * by @type_string. It is appropriate to call g_variant_type_free() on |
||
347 | * the return value. |
||
348 | * |
||
349 | * It is a programmer error to call this function with an invalid type |
||
350 | * string. Use g_variant_type_string_is_valid() if you are unsure. |
||
351 | * |
||
352 | * Returns: (transfer full): a new #GVariantType |
||
353 | * |
||
354 | * Since: 2.24 |
||
355 | */ |
||
356 | GVariantType * |
||
357 | g_variant_type_new (const gchar *type_string) |
||
358 | { |
||
359 | g_return_val_if_fail (type_string != NULL, NULL); |
||
360 | |||
361 | return g_variant_type_copy (G_VARIANT_TYPE (type_string)); |
||
362 | } |
||
363 | |||
364 | /** |
||
365 | * g_variant_type_get_string_length: |
||
366 | * @type: a #GVariantType |
||
367 | * |
||
368 | * Returns the length of the type string corresponding to the given |
||
369 | * @type. This function must be used to determine the valid extent of |
||
370 | * the memory region returned by g_variant_type_peek_string(). |
||
371 | * |
||
372 | * Returns: the length of the corresponding type string |
||
373 | * |
||
374 | * Since 2.24 |
||
375 | **/ |
||
376 | gsize |
||
377 | g_variant_type_get_string_length (const GVariantType *type) |
||
378 | { |
||
379 | const gchar *type_string = (const gchar *) type; |
||
380 | gint brackets = 0; |
||
381 | gsize index = 0; |
||
382 | |||
383 | g_return_val_if_fail (g_variant_type_check (type), 0); |
||
384 | |||
385 | do |
||
386 | { |
||
387 | while (type_string[index] == 'a' || type_string[index] == 'm') |
||
388 | index++; |
||
389 | |||
390 | if (type_string[index] == '(' || type_string[index] == '{') |
||
391 | brackets++; |
||
392 | |||
393 | else if (type_string[index] == ')' || type_string[index] == '}') |
||
394 | brackets--; |
||
395 | |||
396 | index++; |
||
397 | } |
||
398 | while (brackets); |
||
399 | |||
400 | return index; |
||
401 | } |
||
402 | |||
403 | /* |
||
404 | This function is not introspectable, it returns something that |
||
405 | is not an array and neither a string |
||
406 | */ |
||
407 | /** |
||
408 | * g_variant_type_peek_string: (skip) |
||
409 | * @type: a #GVariantType |
||
410 | * |
||
411 | * Returns the type string corresponding to the given @type. The |
||
412 | * result is not nul-terminated; in order to determine its length you |
||
413 | * must call g_variant_type_get_string_length(). |
||
414 | * |
||
415 | * To get a nul-terminated string, see g_variant_type_dup_string(). |
||
416 | * |
||
417 | * Returns: the corresponding type string (not nul-terminated) |
||
418 | * |
||
419 | * Since 2.24 |
||
420 | **/ |
||
421 | const gchar * |
||
422 | g_variant_type_peek_string (const GVariantType *type) |
||
423 | { |
||
424 | g_return_val_if_fail (g_variant_type_check (type), NULL); |
||
425 | |||
426 | return (const gchar *) type; |
||
427 | } |
||
428 | |||
429 | /** |
||
430 | * g_variant_type_dup_string: |
||
431 | * @type: a #GVariantType |
||
432 | * |
||
433 | * Returns a newly-allocated copy of the type string corresponding to |
||
434 | * @type. The returned string is nul-terminated. It is appropriate to |
||
435 | * call g_free() on the return value. |
||
436 | * |
||
437 | * Returns: (transfer full): the corresponding type string |
||
438 | * |
||
439 | * Since 2.24 |
||
440 | **/ |
||
441 | gchar * |
||
442 | g_variant_type_dup_string (const GVariantType *type) |
||
443 | { |
||
444 | g_return_val_if_fail (g_variant_type_check (type), NULL); |
||
445 | |||
446 | return g_strndup (g_variant_type_peek_string (type), |
||
447 | g_variant_type_get_string_length (type)); |
||
448 | } |
||
449 | |||
450 | /** |
||
451 | * g_variant_type_is_definite: |
||
452 | * @type: a #GVariantType |
||
453 | * |
||
454 | * Determines if the given @type is definite (ie: not indefinite). |
||
455 | * |
||
456 | * A type is definite if its type string does not contain any indefinite |
||
457 | * type characters ('*', '?', or 'r'). |
||
458 | * |
||
459 | * A #GVariant instance may not have an indefinite type, so calling |
||
460 | * this function on the result of g_variant_get_type() will always |
||
461 | * result in %TRUE being returned. Calling this function on an |
||
462 | * indefinite type like %G_VARIANT_TYPE_ARRAY, however, will result in |
||
463 | * %FALSE being returned. |
||
464 | * |
||
465 | * Returns: %TRUE if @type is definite |
||
466 | * |
||
467 | * Since 2.24 |
||
468 | **/ |
||
469 | gboolean |
||
470 | g_variant_type_is_definite (const GVariantType *type) |
||
471 | { |
||
472 | const gchar *type_string; |
||
473 | gsize type_length; |
||
474 | gsize i; |
||
475 | |||
476 | g_return_val_if_fail (g_variant_type_check (type), FALSE); |
||
477 | |||
478 | type_length = g_variant_type_get_string_length (type); |
||
479 | type_string = g_variant_type_peek_string (type); |
||
480 | |||
481 | for (i = 0; i < type_length; i++) |
||
482 | if (type_string[i] == '*' || |
||
483 | type_string[i] == '?' || |
||
484 | type_string[i] == 'r') |
||
485 | return FALSE; |
||
486 | |||
487 | return TRUE; |
||
488 | } |
||
489 | |||
490 | /** |
||
491 | * g_variant_type_is_container: |
||
492 | * @type: a #GVariantType |
||
493 | * |
||
494 | * Determines if the given @type is a container type. |
||
495 | * |
||
496 | * Container types are any array, maybe, tuple, or dictionary |
||
497 | * entry types plus the variant type. |
||
498 | * |
||
499 | * This function returns %TRUE for any indefinite type for which every |
||
500 | * definite subtype is a container -- %G_VARIANT_TYPE_ARRAY, for |
||
501 | * example. |
||
502 | * |
||
503 | * Returns: %TRUE if @type is a container type |
||
504 | * |
||
505 | * Since 2.24 |
||
506 | **/ |
||
507 | gboolean |
||
508 | g_variant_type_is_container (const GVariantType *type) |
||
509 | { |
||
510 | gchar first_char; |
||
511 | |||
512 | g_return_val_if_fail (g_variant_type_check (type), FALSE); |
||
513 | |||
514 | first_char = g_variant_type_peek_string (type)[0]; |
||
515 | switch (first_char) |
||
516 | { |
||
517 | case 'a': |
||
518 | case 'm': |
||
519 | case 'r': |
||
520 | case '(': |
||
521 | case '{': |
||
522 | case 'v': |
||
523 | return TRUE; |
||
524 | |||
525 | default: |
||
526 | return FALSE; |
||
527 | } |
||
528 | } |
||
529 | |||
530 | /** |
||
531 | * g_variant_type_is_basic: |
||
532 | * @type: a #GVariantType |
||
533 | * |
||
534 | * Determines if the given @type is a basic type. |
||
535 | * |
||
536 | * Basic types are booleans, bytes, integers, doubles, strings, object |
||
537 | * paths and signatures. |
||
538 | * |
||
539 | * Only a basic type may be used as the key of a dictionary entry. |
||
540 | * |
||
541 | * This function returns %FALSE for all indefinite types except |
||
542 | * %G_VARIANT_TYPE_BASIC. |
||
543 | * |
||
544 | * Returns: %TRUE if @type is a basic type |
||
545 | * |
||
546 | * Since 2.24 |
||
547 | **/ |
||
548 | gboolean |
||
549 | g_variant_type_is_basic (const GVariantType *type) |
||
550 | { |
||
551 | gchar first_char; |
||
552 | |||
553 | g_return_val_if_fail (g_variant_type_check (type), FALSE); |
||
554 | |||
555 | first_char = g_variant_type_peek_string (type)[0]; |
||
556 | switch (first_char) |
||
557 | { |
||
558 | case 'b': |
||
559 | case 'y': |
||
560 | case 'n': |
||
561 | case 'q': |
||
562 | case 'i': |
||
563 | case 'h': |
||
564 | case 'u': |
||
565 | case 't': |
||
566 | case 'x': |
||
567 | case 'd': |
||
568 | case 's': |
||
569 | case 'o': |
||
570 | case 'g': |
||
571 | case '?': |
||
572 | return TRUE; |
||
573 | |||
574 | default: |
||
575 | return FALSE; |
||
576 | } |
||
577 | } |
||
578 | |||
579 | /** |
||
580 | * g_variant_type_is_maybe: |
||
581 | * @type: a #GVariantType |
||
582 | * |
||
583 | * Determines if the given @type is a maybe type. This is true if the |
||
584 | * type string for @type starts with an 'm'. |
||
585 | * |
||
586 | * This function returns %TRUE for any indefinite type for which every |
||
587 | * definite subtype is a maybe type -- %G_VARIANT_TYPE_MAYBE, for |
||
588 | * example. |
||
589 | * |
||
590 | * Returns: %TRUE if @type is a maybe type |
||
591 | * |
||
592 | * Since 2.24 |
||
593 | **/ |
||
594 | gboolean |
||
595 | g_variant_type_is_maybe (const GVariantType *type) |
||
596 | { |
||
597 | g_return_val_if_fail (g_variant_type_check (type), FALSE); |
||
598 | |||
599 | return g_variant_type_peek_string (type)[0] == 'm'; |
||
600 | } |
||
601 | |||
602 | /** |
||
603 | * g_variant_type_is_array: |
||
604 | * @type: a #GVariantType |
||
605 | * |
||
606 | * Determines if the given @type is an array type. This is true if the |
||
607 | * type string for @type starts with an 'a'. |
||
608 | * |
||
609 | * This function returns %TRUE for any indefinite type for which every |
||
610 | * definite subtype is an array type -- %G_VARIANT_TYPE_ARRAY, for |
||
611 | * example. |
||
612 | * |
||
613 | * Returns: %TRUE if @type is an array type |
||
614 | * |
||
615 | * Since 2.24 |
||
616 | **/ |
||
617 | gboolean |
||
618 | g_variant_type_is_array (const GVariantType *type) |
||
619 | { |
||
620 | g_return_val_if_fail (g_variant_type_check (type), FALSE); |
||
621 | |||
622 | return g_variant_type_peek_string (type)[0] == 'a'; |
||
623 | } |
||
624 | |||
625 | /** |
||
626 | * g_variant_type_is_tuple: |
||
627 | * @type: a #GVariantType |
||
628 | * |
||
629 | * Determines if the given @type is a tuple type. This is true if the |
||
630 | * type string for @type starts with a '(' or if @type is |
||
631 | * %G_VARIANT_TYPE_TUPLE. |
||
632 | * |
||
633 | * This function returns %TRUE for any indefinite type for which every |
||
634 | * definite subtype is a tuple type -- %G_VARIANT_TYPE_TUPLE, for |
||
635 | * example. |
||
636 | * |
||
637 | * Returns: %TRUE if @type is a tuple type |
||
638 | * |
||
639 | * Since 2.24 |
||
640 | **/ |
||
641 | gboolean |
||
642 | g_variant_type_is_tuple (const GVariantType *type) |
||
643 | { |
||
644 | gchar type_char; |
||
645 | |||
646 | g_return_val_if_fail (g_variant_type_check (type), FALSE); |
||
647 | |||
648 | type_char = g_variant_type_peek_string (type)[0]; |
||
649 | return type_char == 'r' || type_char == '('; |
||
650 | } |
||
651 | |||
652 | /** |
||
653 | * g_variant_type_is_dict_entry: |
||
654 | * @type: a #GVariantType |
||
655 | * |
||
656 | * Determines if the given @type is a dictionary entry type. This is |
||
657 | * true if the type string for @type starts with a '{'. |
||
658 | * |
||
659 | * This function returns %TRUE for any indefinite type for which every |
||
660 | * definite subtype is a dictionary entry type -- |
||
661 | * %G_VARIANT_TYPE_DICT_ENTRY, for example. |
||
662 | * |
||
663 | * Returns: %TRUE if @type is a dictionary entry type |
||
664 | * |
||
665 | * Since 2.24 |
||
666 | **/ |
||
667 | gboolean |
||
668 | g_variant_type_is_dict_entry (const GVariantType *type) |
||
669 | { |
||
670 | g_return_val_if_fail (g_variant_type_check (type), FALSE); |
||
671 | |||
672 | return g_variant_type_peek_string (type)[0] == '{'; |
||
673 | } |
||
674 | |||
675 | /** |
||
676 | * g_variant_type_is_variant: |
||
677 | * @type: a #GVariantType |
||
678 | * |
||
679 | * Determines if the given @type is the variant type. |
||
680 | * |
||
681 | * Returns: %TRUE if @type is the variant type |
||
682 | * |
||
683 | * Since 2.24 |
||
684 | **/ |
||
685 | gboolean |
||
686 | g_variant_type_is_variant (const GVariantType *type) |
||
687 | { |
||
688 | g_return_val_if_fail (g_variant_type_check (type), FALSE); |
||
689 | |||
690 | return g_variant_type_peek_string (type)[0] == 'v'; |
||
691 | } |
||
692 | |||
693 | /** |
||
694 | * g_variant_type_hash: |
||
695 | * @type: (type GVariantType): a #GVariantType |
||
696 | * |
||
697 | * Hashes @type. |
||
698 | * |
||
699 | * The argument type of @type is only #gconstpointer to allow use with |
||
700 | * #GHashTable without function pointer casting. A valid |
||
701 | * #GVariantType must be provided. |
||
702 | * |
||
703 | * Returns: the hash value |
||
704 | * |
||
705 | * Since 2.24 |
||
706 | **/ |
||
707 | guint |
||
708 | g_variant_type_hash (gconstpointer type) |
||
709 | { |
||
710 | const gchar *type_string; |
||
711 | guint value = 0; |
||
712 | gsize length; |
||
713 | gsize i; |
||
714 | |||
715 | g_return_val_if_fail (g_variant_type_check (type), 0); |
||
716 | |||
717 | type_string = g_variant_type_peek_string (type); |
||
718 | length = g_variant_type_get_string_length (type); |
||
719 | |||
720 | for (i = 0; i < length; i++) |
||
721 | value = (value << 5) - value + type_string[i]; |
||
722 | |||
723 | return value; |
||
724 | } |
||
725 | |||
726 | /** |
||
727 | * g_variant_type_equal: |
||
728 | * @type1: (type GVariantType): a #GVariantType |
||
729 | * @type2: (type GVariantType): a #GVariantType |
||
730 | * |
||
731 | * Compares @type1 and @type2 for equality. |
||
732 | * |
||
733 | * Only returns %TRUE if the types are exactly equal. Even if one type |
||
734 | * is an indefinite type and the other is a subtype of it, %FALSE will |
||
735 | * be returned if they are not exactly equal. If you want to check for |
||
736 | * subtypes, use g_variant_type_is_subtype_of(). |
||
737 | * |
||
738 | * The argument types of @type1 and @type2 are only #gconstpointer to |
||
739 | * allow use with #GHashTable without function pointer casting. For |
||
740 | * both arguments, a valid #GVariantType must be provided. |
||
741 | * |
||
742 | * Returns: %TRUE if @type1 and @type2 are exactly equal |
||
743 | * |
||
744 | * Since 2.24 |
||
745 | **/ |
||
746 | gboolean |
||
747 | g_variant_type_equal (gconstpointer type1, |
||
748 | gconstpointer type2) |
||
749 | { |
||
750 | const gchar *string1, *string2; |
||
751 | gsize size1, size2; |
||
752 | |||
753 | g_return_val_if_fail (g_variant_type_check (type1), FALSE); |
||
754 | g_return_val_if_fail (g_variant_type_check (type2), FALSE); |
||
755 | |||
756 | if (type1 == type2) |
||
757 | return TRUE; |
||
758 | |||
759 | size1 = g_variant_type_get_string_length (type1); |
||
760 | size2 = g_variant_type_get_string_length (type2); |
||
761 | |||
762 | if (size1 != size2) |
||
763 | return FALSE; |
||
764 | |||
765 | string1 = g_variant_type_peek_string (type1); |
||
766 | string2 = g_variant_type_peek_string (type2); |
||
767 | |||
768 | return memcmp (string1, string2, size1) == 0; |
||
769 | } |
||
770 | |||
771 | /** |
||
772 | * g_variant_type_is_subtype_of: |
||
773 | * @type: a #GVariantType |
||
774 | * @supertype: a #GVariantType |
||
775 | * |
||
776 | * Checks if @type is a subtype of @supertype. |
||
777 | * |
||
778 | * This function returns %TRUE if @type is a subtype of @supertype. All |
||
779 | * types are considered to be subtypes of themselves. Aside from that, |
||
780 | * only indefinite types can have subtypes. |
||
781 | * |
||
782 | * Returns: %TRUE if @type is a subtype of @supertype |
||
783 | * |
||
784 | * Since 2.24 |
||
785 | **/ |
||
786 | gboolean |
||
787 | g_variant_type_is_subtype_of (const GVariantType *type, |
||
788 | const GVariantType *supertype) |
||
789 | { |
||
790 | const gchar *supertype_string; |
||
791 | const gchar *supertype_end; |
||
792 | const gchar *type_string; |
||
793 | |||
794 | g_return_val_if_fail (g_variant_type_check (type), FALSE); |
||
795 | g_return_val_if_fail (g_variant_type_check (supertype), FALSE); |
||
796 | |||
797 | supertype_string = g_variant_type_peek_string (supertype); |
||
798 | type_string = g_variant_type_peek_string (type); |
||
799 | |||
800 | supertype_end = supertype_string + |
||
801 | g_variant_type_get_string_length (supertype); |
||
802 | |||
803 | /* we know that type and supertype are both well-formed, so it's |
||
804 | * safe to treat this merely as a text processing problem. |
||
805 | */ |
||
806 | while (supertype_string < supertype_end) |
||
807 | { |
||
808 | char supertype_char = *supertype_string++; |
||
809 | |||
810 | if (supertype_char == *type_string) |
||
811 | type_string++; |
||
812 | |||
813 | else if (*type_string == ')') |
||
814 | return FALSE; |
||
815 | |||
816 | else |
||
817 | { |
||
818 | const GVariantType *target_type = (GVariantType *) type_string; |
||
819 | |||
820 | switch (supertype_char) |
||
821 | { |
||
822 | case 'r': |
||
823 | if (!g_variant_type_is_tuple (target_type)) |
||
824 | return FALSE; |
||
825 | break; |
||
826 | |||
827 | case '*': |
||
828 | break; |
||
829 | |||
830 | case '?': |
||
831 | if (!g_variant_type_is_basic (target_type)) |
||
832 | return FALSE; |
||
833 | break; |
||
834 | |||
835 | default: |
||
836 | return FALSE; |
||
837 | } |
||
838 | |||
839 | type_string += g_variant_type_get_string_length (target_type); |
||
840 | } |
||
841 | } |
||
842 | |||
843 | return TRUE; |
||
844 | } |
||
845 | |||
846 | /** |
||
847 | * g_variant_type_element: |
||
848 | * @type: an array or maybe #GVariantType |
||
849 | * |
||
850 | * Determines the element type of an array or maybe type. |
||
851 | * |
||
852 | * This function may only be used with array or maybe types. |
||
853 | * |
||
854 | * Returns: (transfer none): the element type of @type |
||
855 | * |
||
856 | * Since 2.24 |
||
857 | **/ |
||
858 | const GVariantType * |
||
859 | g_variant_type_element (const GVariantType *type) |
||
860 | { |
||
861 | const gchar *type_string; |
||
862 | |||
863 | g_return_val_if_fail (g_variant_type_check (type), NULL); |
||
864 | |||
865 | type_string = g_variant_type_peek_string (type); |
||
866 | |||
867 | g_assert (type_string[0] == 'a' || type_string[0] == 'm'); |
||
868 | |||
869 | return (const GVariantType *) &type_string[1]; |
||
870 | } |
||
871 | |||
872 | /** |
||
873 | * g_variant_type_first: |
||
874 | * @type: a tuple or dictionary entry #GVariantType |
||
875 | * |
||
876 | * Determines the first item type of a tuple or dictionary entry |
||
877 | * type. |
||
878 | * |
||
879 | * This function may only be used with tuple or dictionary entry types, |
||
880 | * but must not be used with the generic tuple type |
||
881 | * %G_VARIANT_TYPE_TUPLE. |
||
882 | * |
||
883 | * In the case of a dictionary entry type, this returns the type of |
||
884 | * the key. |
||
885 | * |
||
886 | * %NULL is returned in case of @type being %G_VARIANT_TYPE_UNIT. |
||
887 | * |
||
888 | * This call, together with g_variant_type_next() provides an iterator |
||
889 | * interface over tuple and dictionary entry types. |
||
890 | * |
||
891 | * Returns: (transfer none): the first item type of @type, or %NULL |
||
892 | * |
||
893 | * Since 2.24 |
||
894 | **/ |
||
895 | const GVariantType * |
||
896 | g_variant_type_first (const GVariantType *type) |
||
897 | { |
||
898 | const gchar *type_string; |
||
899 | |||
900 | g_return_val_if_fail (g_variant_type_check (type), NULL); |
||
901 | |||
902 | type_string = g_variant_type_peek_string (type); |
||
903 | g_assert (type_string[0] == '(' || type_string[0] == '{'); |
||
904 | |||
905 | if (type_string[1] == ')') |
||
906 | return NULL; |
||
907 | |||
908 | return (const GVariantType *) &type_string[1]; |
||
909 | } |
||
910 | |||
911 | /** |
||
912 | * g_variant_type_next: |
||
913 | * @type: a #GVariantType from a previous call |
||
914 | * |
||
915 | * Determines the next item type of a tuple or dictionary entry |
||
916 | * type. |
||
917 | * |
||
918 | * @type must be the result of a previous call to |
||
919 | * g_variant_type_first() or g_variant_type_next(). |
||
920 | * |
||
921 | * If called on the key type of a dictionary entry then this call |
||
922 | * returns the value type. If called on the value type of a dictionary |
||
923 | * entry then this call returns %NULL. |
||
924 | * |
||
925 | * For tuples, %NULL is returned when @type is the last item in a tuple. |
||
926 | * |
||
927 | * Returns: (transfer none): the next #GVariantType after @type, or %NULL |
||
928 | * |
||
929 | * Since 2.24 |
||
930 | **/ |
||
931 | const GVariantType * |
||
932 | g_variant_type_next (const GVariantType *type) |
||
933 | { |
||
934 | const gchar *type_string; |
||
935 | |||
936 | g_return_val_if_fail (g_variant_type_check (type), NULL); |
||
937 | |||
938 | type_string = g_variant_type_peek_string (type); |
||
939 | type_string += g_variant_type_get_string_length (type); |
||
940 | |||
941 | if (*type_string == ')' || *type_string == '}') |
||
942 | return NULL; |
||
943 | |||
944 | return (const GVariantType *) type_string; |
||
945 | } |
||
946 | |||
947 | /** |
||
948 | * g_variant_type_n_items: |
||
949 | * @type: a tuple or dictionary entry #GVariantType |
||
950 | * |
||
951 | * Determines the number of items contained in a tuple or |
||
952 | * dictionary entry type. |
||
953 | * |
||
954 | * This function may only be used with tuple or dictionary entry types, |
||
955 | * but must not be used with the generic tuple type |
||
956 | * %G_VARIANT_TYPE_TUPLE. |
||
957 | * |
||
958 | * In the case of a dictionary entry type, this function will always |
||
959 | * return 2. |
||
960 | * |
||
961 | * Returns: the number of items in @type |
||
962 | * |
||
963 | * Since 2.24 |
||
964 | **/ |
||
965 | gsize |
||
966 | g_variant_type_n_items (const GVariantType *type) |
||
967 | { |
||
968 | gsize count = 0; |
||
969 | |||
970 | g_return_val_if_fail (g_variant_type_check (type), 0); |
||
971 | |||
972 | for (type = g_variant_type_first (type); |
||
973 | type; |
||
974 | type = g_variant_type_next (type)) |
||
975 | count++; |
||
976 | |||
977 | return count; |
||
978 | } |
||
979 | |||
980 | /** |
||
981 | * g_variant_type_key: |
||
982 | * @type: a dictionary entry #GVariantType |
||
983 | * |
||
984 | * Determines the key type of a dictionary entry type. |
||
985 | * |
||
986 | * This function may only be used with a dictionary entry type. Other |
||
987 | * than the additional restriction, this call is equivalent to |
||
988 | * g_variant_type_first(). |
||
989 | * |
||
990 | * Returns: (transfer none): the key type of the dictionary entry |
||
991 | * |
||
992 | * Since 2.24 |
||
993 | **/ |
||
994 | const GVariantType * |
||
995 | g_variant_type_key (const GVariantType *type) |
||
996 | { |
||
997 | const gchar *type_string; |
||
998 | |||
999 | g_return_val_if_fail (g_variant_type_check (type), NULL); |
||
1000 | |||
1001 | type_string = g_variant_type_peek_string (type); |
||
1002 | g_assert (type_string[0] == '{'); |
||
1003 | |||
1004 | return (const GVariantType *) &type_string[1]; |
||
1005 | } |
||
1006 | |||
1007 | /** |
||
1008 | * g_variant_type_value: |
||
1009 | * @type: a dictionary entry #GVariantType |
||
1010 | * |
||
1011 | * Determines the value type of a dictionary entry type. |
||
1012 | * |
||
1013 | * This function may only be used with a dictionary entry type. |
||
1014 | * |
||
1015 | * Returns: (transfer none): the value type of the dictionary entry |
||
1016 | * |
||
1017 | * Since 2.24 |
||
1018 | **/ |
||
1019 | const GVariantType * |
||
1020 | g_variant_type_value (const GVariantType *type) |
||
1021 | { |
||
1022 | const gchar *type_string; |
||
1023 | |||
1024 | g_return_val_if_fail (g_variant_type_check (type), NULL); |
||
1025 | |||
1026 | type_string = g_variant_type_peek_string (type); |
||
1027 | g_assert (type_string[0] == '{'); |
||
1028 | |||
1029 | return g_variant_type_next (g_variant_type_key (type)); |
||
1030 | } |
||
1031 | |||
1032 | /** |
||
1033 | * g_variant_type_new_tuple: |
||
1034 | * @items: (array length=length): an array of #GVariantTypes, one for each item |
||
1035 | * @length: the length of @items, or -1 |
||
1036 | * |
||
1037 | * Constructs a new tuple type, from @items. |
||
1038 | * |
||
1039 | * @length is the number of items in @items, or -1 to indicate that |
||
1040 | * @items is %NULL-terminated. |
||
1041 | * |
||
1042 | * It is appropriate to call g_variant_type_free() on the return value. |
||
1043 | * |
||
1044 | * Returns: (transfer full): a new tuple #GVariantType |
||
1045 | * |
||
1046 | * Since 2.24 |
||
1047 | **/ |
||
1048 | static GVariantType * |
||
1049 | g_variant_type_new_tuple_slow (const GVariantType * const *items, |
||
1050 | gint length) |
||
1051 | { |
||
1052 | /* the "slow" version is needed in case the static buffer of 1024 |
||
1053 | * bytes is exceeded when running the normal version. this will |
||
1054 | * happen only in truly insane code, so it can be slow. |
||
1055 | */ |
||
1056 | GString *string; |
||
1057 | gsize i; |
||
1058 | |||
1059 | string = g_string_new ("("); |
||
1060 | for (i = 0; i < length; i++) |
||
1061 | { |
||
1062 | const GVariantType *type; |
||
1063 | gsize size; |
||
1064 | |||
1065 | g_return_val_if_fail (g_variant_type_check (items[i]), NULL); |
||
1066 | |||
1067 | type = items[i]; |
||
1068 | size = g_variant_type_get_string_length (type); |
||
1069 | g_string_append_len (string, (const gchar *) type, size); |
||
1070 | } |
||
1071 | g_string_append_c (string, ')'); |
||
1072 | |||
1073 | return (GVariantType *) g_string_free (string, FALSE); |
||
1074 | } |
||
1075 | |||
1076 | GVariantType * |
||
1077 | g_variant_type_new_tuple (const GVariantType * const *items, |
||
1078 | gint length) |
||
1079 | { |
||
1080 | char buffer[1024]; |
||
1081 | gsize offset; |
||
1082 | gsize i; |
||
1083 | |||
1084 | g_return_val_if_fail (length == 0 || items != NULL, NULL); |
||
1085 | |||
1086 | if (length < 0) |
||
1087 | for (length = 0; items[length] != NULL; length++); |
||
1088 | |||
1089 | offset = 0; |
||
1090 | buffer[offset++] = '('; |
||
1091 | |||
1092 | for (i = 0; i < length; i++) |
||
1093 | { |
||
1094 | const GVariantType *type; |
||
1095 | gsize size; |
||
1096 | |||
1097 | g_return_val_if_fail (g_variant_type_check (items[i]), NULL); |
||
1098 | |||
1099 | type = items[i]; |
||
1100 | size = g_variant_type_get_string_length (type); |
||
1101 | |||
1102 | if (offset + size >= sizeof buffer) /* leave room for ')' */ |
||
1103 | return g_variant_type_new_tuple_slow (items, length); |
||
1104 | |||
1105 | memcpy (&buffer[offset], type, size); |
||
1106 | offset += size; |
||
1107 | } |
||
1108 | |||
1109 | g_assert (offset < sizeof buffer); |
||
1110 | buffer[offset++] = ')'; |
||
1111 | |||
1112 | return (GVariantType *) g_memdup (buffer, offset); |
||
1113 | } |
||
1114 | |||
1115 | /** |
||
1116 | * g_variant_type_new_array: (constructor) |
||
1117 | * @element: a #GVariantType |
||
1118 | * |
||
1119 | * Constructs the type corresponding to an array of elements of the |
||
1120 | * type @type. |
||
1121 | * |
||
1122 | * It is appropriate to call g_variant_type_free() on the return value. |
||
1123 | * |
||
1124 | * Returns: (transfer full): a new array #GVariantType |
||
1125 | * |
||
1126 | * Since 2.24 |
||
1127 | **/ |
||
1128 | GVariantType * |
||
1129 | g_variant_type_new_array (const GVariantType *element) |
||
1130 | { |
||
1131 | gsize size; |
||
1132 | gchar *new; |
||
1133 | |||
1134 | g_return_val_if_fail (g_variant_type_check (element), NULL); |
||
1135 | |||
1136 | size = g_variant_type_get_string_length (element); |
||
1137 | new = g_malloc (size + 1); |
||
1138 | |||
1139 | new[0] = 'a'; |
||
1140 | memcpy (new + 1, element, size); |
||
1141 | |||
1142 | return (GVariantType *) new; |
||
1143 | } |
||
1144 | |||
1145 | /** |
||
1146 | * g_variant_type_new_maybe: (constructor) |
||
1147 | * @element: a #GVariantType |
||
1148 | * |
||
1149 | * Constructs the type corresponding to a maybe instance containing |
||
1150 | * type @type or Nothing. |
||
1151 | * |
||
1152 | * It is appropriate to call g_variant_type_free() on the return value. |
||
1153 | * |
||
1154 | * Returns: (transfer full): a new maybe #GVariantType |
||
1155 | * |
||
1156 | * Since 2.24 |
||
1157 | **/ |
||
1158 | GVariantType * |
||
1159 | g_variant_type_new_maybe (const GVariantType *element) |
||
1160 | { |
||
1161 | gsize size; |
||
1162 | gchar *new; |
||
1163 | |||
1164 | g_return_val_if_fail (g_variant_type_check (element), NULL); |
||
1165 | |||
1166 | size = g_variant_type_get_string_length (element); |
||
1167 | new = g_malloc (size + 1); |
||
1168 | |||
1169 | new[0] = 'm'; |
||
1170 | memcpy (new + 1, element, size); |
||
1171 | |||
1172 | return (GVariantType *) new; |
||
1173 | } |
||
1174 | |||
1175 | /** |
||
1176 | * g_variant_type_new_dict_entry: (constructor) |
||
1177 | * @key: a basic #GVariantType |
||
1178 | * @value: a #GVariantType |
||
1179 | * |
||
1180 | * Constructs the type corresponding to a dictionary entry with a key |
||
1181 | * of type @key and a value of type @value. |
||
1182 | * |
||
1183 | * It is appropriate to call g_variant_type_free() on the return value. |
||
1184 | * |
||
1185 | * Returns: (transfer full): a new dictionary entry #GVariantType |
||
1186 | * |
||
1187 | * Since 2.24 |
||
1188 | **/ |
||
1189 | GVariantType * |
||
1190 | g_variant_type_new_dict_entry (const GVariantType *key, |
||
1191 | const GVariantType *value) |
||
1192 | { |
||
1193 | gsize keysize, valsize; |
||
1194 | gchar *new; |
||
1195 | |||
1196 | g_return_val_if_fail (g_variant_type_check (key), NULL); |
||
1197 | g_return_val_if_fail (g_variant_type_check (value), NULL); |
||
1198 | |||
1199 | keysize = g_variant_type_get_string_length (key); |
||
1200 | valsize = g_variant_type_get_string_length (value); |
||
1201 | |||
1202 | new = g_malloc (1 + keysize + valsize + 1); |
||
1203 | |||
1204 | new[0] = '{'; |
||
1205 | memcpy (new + 1, key, keysize); |
||
1206 | memcpy (new + 1 + keysize, value, valsize); |
||
1207 | new[1 + keysize + valsize] = '}'; |
||
1208 | |||
1209 | return (GVariantType *) new; |
||
1210 | } |
||
1211 | |||
1212 | /* private */ |
||
1213 | const GVariantType * |
||
1214 | g_variant_type_checked_ (const gchar *type_string) |
||
1215 | { |
||
1216 | g_return_val_if_fail (g_variant_type_string_is_valid (type_string), NULL); |
||
1217 | return (const GVariantType *) type_string; |
||
1218 | } |