2 * Copyright © 2009, 2010 Codethink Limited
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the licence, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
19 * Author: Ryan Lortie <desrt@desrt.ca>
31 * designed by ryan lortie and william hua
32 * designed in itb-229 and at ghazi's, 2009.
36 * G_VARIANT_PARSE_ERROR:
38 * Error domain for GVariant text format parsing. Specific error codes
39 * are not currently defined for this domain. See #GError for
40 * information on error domains.
44 * @G_VARIANT_PARSE_ERROR_FAILED: generic error
46 * Error codes returned by parsing text-format GVariants. Currently the
47 * parser makes no distinction between different types of error.
50 g_variant_parser_get_error_quark (void)
52 static GQuark the_quark;
55 the_quark = g_quark_from_static_string ("g-variant-parse-error-quark");
66 parser_set_error_va (GError **error,
72 GString *msg = g_string_new (NULL);
74 if (location->start == location->end)
75 g_string_append_printf (msg, "%d", location->start);
77 g_string_append_printf (msg, "%d-%d", location->start, location->end);
81 g_assert (other->start != other->end);
82 g_string_append_printf (msg, ",%d-%d", other->start, other->end);
84 g_string_append_c (msg, ':');
86 g_string_append_vprintf (msg, format, ap);
87 g_set_error_literal (error, G_VARIANT_PARSE_ERROR, 0, msg->str);
88 g_string_free (msg, TRUE);
92 parser_set_error (GError **error,
100 va_start (ap, format);
101 parser_set_error_va (error, location, other, format, ap);
116 token_stream_set_error (TokenStream *stream,
125 ref.start = stream->this - stream->start;
128 ref.end = stream->stream - stream->start;
132 va_start (ap, format);
133 parser_set_error_va (error, &ref, NULL, format, ap);
138 token_stream_prepare (TokenStream *stream)
143 if (stream->this != NULL)
146 while (stream->stream != stream->end && g_ascii_isspace (*stream->stream))
149 if (stream->stream == stream->end || *stream->stream == '\0')
151 stream->this = stream->stream;
155 switch (stream->stream[0])
157 case '-': case '+': case '.': case '0': case '1': case '2':
158 case '3': case '4': case '5': case '6': case '7': case '8':
160 for (end = stream->stream; end != stream->end; end++)
161 if (!g_ascii_isalnum (*end) &&
162 *end != '-' && *end != '+' && *end != '.')
166 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
167 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
168 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
169 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
171 for (end = stream->stream; end != stream->end; end++)
172 if (!g_ascii_isalnum (*end))
177 /* stop at the first space, comma, colon or unmatched bracket.
178 * deals nicely with cases like (%i, %i) or {%i: %i}.
180 for (end = stream->stream + 1;
181 end != stream->end && *end != ',' &&
182 *end != ':' && !g_ascii_isspace (*end);
185 if (*end == '(' || *end == '{')
188 else if ((*end == ')' || *end == '}') && !brackets--)
194 for (end = stream->stream + 1; end != stream->end; end++)
195 if (*end == stream->stream[0] || *end == '\0' ||
196 (*end == '\\' && (++end == stream->end || *end == '\0')))
199 if (end != stream->end && *end)
204 end = stream->stream + 1;
208 stream->this = stream->stream;
209 stream->stream = end;
213 token_stream_next (TokenStream *stream)
219 token_stream_peek (TokenStream *stream,
222 token_stream_prepare (stream);
224 return stream->this[0] == first_char;
228 token_stream_is_keyword (TokenStream *stream)
230 token_stream_prepare (stream);
232 return g_ascii_isalpha (stream->this[0]);
236 token_stream_is_numeric (TokenStream *stream)
238 token_stream_prepare (stream);
240 return (g_ascii_isdigit (stream->this[0]) ||
241 stream->this[0] == '-' ||
242 stream->this[0] == '+' ||
243 stream->this[0] == '.');
247 token_stream_consume (TokenStream *stream,
250 gint length = strlen (token);
252 token_stream_prepare (stream);
254 if (stream->stream - stream->this == length &&
255 memcmp (stream->this, token, length) == 0)
257 token_stream_next (stream);
265 token_stream_require (TokenStream *stream,
267 const gchar *purpose,
271 if (!token_stream_consume (stream, token))
273 token_stream_set_error (stream, error, FALSE,
274 "expected `%s'%s", token, purpose);
282 token_stream_assert (TokenStream *stream,
285 gboolean correct_token;
287 correct_token = token_stream_consume (stream, token);
288 g_assert (correct_token);
292 token_stream_get (TokenStream *stream)
296 token_stream_prepare (stream);
298 result = g_strndup (stream->this, stream->stream - stream->this);
304 token_stream_start_ref (TokenStream *stream,
307 token_stream_prepare (stream);
308 ref->start = stream->this - stream->start;
312 token_stream_end_ref (TokenStream *stream,
315 ref->end = stream->stream - stream->start;
319 pattern_copy (gchar **out,
324 while (**in == 'a' || **in == 'm' || **in == 'M')
325 *(*out)++ = *(*in)++;
329 if (**in == '(' || **in == '{')
332 else if (**in == ')' || **in == '}')
335 *(*out)++ = *(*in)++;
341 pattern_coalesce (const gchar *left,
347 /* the length of the output is loosely bound by the sum of the input
348 * lengths, not simply the greater of the two lengths.
350 * (*(iii)) + ((iii)*) ((iii)(iii))
354 out = result = g_malloc (strlen (left) + strlen (right));
356 while (*left && *right)
366 const gchar **one = &left, **the_other = &right;
369 if (**one == '*' && **the_other != ')')
371 pattern_copy (&out, the_other);
375 else if (**one == 'M' && **the_other == 'm')
377 *out++ = *(*the_other)++;
380 else if (**one == 'M' && **the_other != 'm')
385 else if (**one == 'N' && strchr ("ynqiuxthd", **the_other))
387 *out++ = *(*the_other)++;
391 else if (**one == 'S' && strchr ("sog", **the_other))
393 *out++ = *(*the_other)++;
397 else if (one == &left)
399 one = &right, the_other = &left;
419 typedef struct _AST AST;
420 typedef gchar * (*get_pattern_func) (AST *ast,
422 typedef GVariant * (*get_value_func) (AST *ast,
423 const GVariantType *type,
425 typedef GVariant * (*get_base_value_func) (AST *ast,
426 const GVariantType *type,
428 typedef void (*free_func) (AST *ast);
432 gchar * (* get_pattern) (AST *ast,
434 GVariant * (* get_value) (AST *ast,
435 const GVariantType *type,
437 GVariant * (* get_base_value) (AST *ast,
438 const GVariantType *type,
440 void (* free) (AST *ast);
445 const ASTClass *class;
446 SourceRef source_ref;
450 ast_get_pattern (AST *ast,
453 return ast->class->get_pattern (ast, error);
457 ast_get_value (AST *ast,
458 const GVariantType *type,
461 return ast->class->get_value (ast, type, error);
467 ast->class->free (ast);
471 ast_set_error (AST *ast,
479 va_start (ap, format);
480 parser_set_error_va (error, &ast->source_ref,
481 other_ast ? & other_ast->source_ref : NULL,
487 ast_type_error (AST *ast,
488 const GVariantType *type,
493 typestr = g_variant_type_dup_string (type);
494 ast_set_error (ast, error, NULL,
495 "can not parse as value of type `%s'",
503 ast_resolve (AST *ast,
510 pattern = ast_get_pattern (ast, error);
515 /* choose reasonable defaults
517 * 1) favour non-maybe values where possible
518 * 2) default type for strings is 's'
519 * 3) default type for integers is 'i'
521 for (i = 0; pattern[i]; i++)
525 ast_set_error (ast, error, NULL, "unable to infer type");
541 pattern[j++] = pattern[i];
546 value = ast_get_value (ast, G_VARIANT_TYPE (pattern), error);
553 static AST *parse (TokenStream *stream,
558 ast_array_append (AST ***array,
562 if ((*n_items & (*n_items - 1)) == 0)
563 *array = g_renew (AST *, *array, *n_items ? 2 ** n_items : 1);
565 (*array)[(*n_items)++] = ast;
569 ast_array_free (AST **array,
574 for (i = 0; i < n_items; i++)
580 ast_array_get_pattern (AST **array,
587 pattern = ast_get_pattern (array[0], error);
592 for (i = 1; i < n_items; i++)
596 tmp = ast_get_pattern (array[i], error);
604 merged = pattern_coalesce (pattern, tmp);
609 /* set coalescence implies pairwise coalescence (i think).
610 * we should therefore be able to trace the failure to a single
621 /* if 'j' reaches 'i' then we failed to find the pair */
624 tmp2 = ast_get_pattern (array[j], NULL);
625 g_assert (tmp2 != NULL);
627 m = pattern_coalesce (tmp, tmp2);
633 /* we found a conflict between 'i' and 'j'.
635 * report the error. note: 'j' is first.
637 ast_set_error (array[j], error, array[i],
638 "unable to find a common type");
659 maybe_get_pattern (AST *ast,
662 Maybe *maybe = (Maybe *) ast;
664 if (maybe->child != NULL)
666 gchar *child_pattern;
669 child_pattern = ast_get_pattern (maybe->child, error);
671 if (child_pattern == NULL)
674 pattern = g_strdup_printf ("m%s", child_pattern);
675 g_free (child_pattern);
680 return g_strdup ("m*");
684 maybe_get_value (AST *ast,
685 const GVariantType *type,
688 Maybe *maybe = (Maybe *) ast;
691 if (!g_variant_type_is_maybe (type))
692 return ast_type_error (ast, type, error);
694 type = g_variant_type_element (type);
698 value = ast_get_value (maybe->child, type, error);
706 return g_variant_new_maybe (type, value);
710 maybe_free (AST *ast)
712 Maybe *maybe = (Maybe *) ast;
714 if (maybe->child != NULL)
715 ast_free (maybe->child);
717 g_slice_free (Maybe, maybe);
721 maybe_parse (TokenStream *stream,
725 static const ASTClass maybe_class = {
727 maybe_get_value, NULL,
733 if (token_stream_consume (stream, "just"))
735 child = parse (stream, app, error);
740 else if (!token_stream_consume (stream, "nothing"))
742 token_stream_set_error (stream, error, TRUE, "unknown keyword");
746 maybe = g_slice_new (Maybe);
747 maybe->ast.class = &maybe_class;
748 maybe->child = child;
750 return (AST *) maybe;
754 maybe_wrapper (AST *ast,
755 const GVariantType *type,
758 const GVariantType *t;
762 for (depth = 0, t = type;
763 g_variant_type_is_maybe (t);
764 depth++, t = g_variant_type_element (t));
766 value = ast->class->get_base_value (ast, t, error);
772 value = g_variant_new_maybe (NULL, value);
786 array_get_pattern (AST *ast,
789 Array *array = (Array *) ast;
793 if (array->n_children == 0)
794 return g_strdup ("Ma*");
796 pattern = ast_array_get_pattern (array->children, array->n_children, error);
801 result = g_strdup_printf ("Ma%s", pattern);
808 array_get_value (AST *ast,
809 const GVariantType *type,
812 Array *array = (Array *) ast;
813 const GVariantType *childtype;
814 GVariantBuilder builder;
817 if (!g_variant_type_is_array (type))
818 return ast_type_error (ast, type, error);
820 g_variant_builder_init (&builder, type);
821 childtype = g_variant_type_element (type);
823 for (i = 0; i < array->n_children; i++)
827 if (!(child = ast_get_value (array->children[i], childtype, error)))
829 g_variant_builder_clear (&builder);
833 g_variant_builder_add_value (&builder, child);
836 return g_variant_builder_end (&builder);
840 array_free (AST *ast)
842 Array *array = (Array *) ast;
844 ast_array_free (array->children, array->n_children);
845 g_slice_free (Array, array);
849 array_parse (TokenStream *stream,
853 static const ASTClass array_class = {
855 maybe_wrapper, array_get_value,
858 gboolean need_comma = FALSE;
861 array = g_slice_new (Array);
862 array->ast.class = &array_class;
863 array->children = NULL;
864 array->n_children = 0;
866 token_stream_assert (stream, "[");
867 while (!token_stream_consume (stream, "]"))
872 !token_stream_require (stream, ",",
873 " or `]' to follow array element",
877 child = parse (stream, app, error);
882 ast_array_append (&array->children, &array->n_children, child);
886 return (AST *) array;
889 ast_array_free (array->children, array->n_children);
890 g_slice_free (Array, array);
904 tuple_get_pattern (AST *ast,
907 Tuple *tuple = (Tuple *) ast;
908 gchar *result = NULL;
912 parts = g_new (gchar *, tuple->n_children + 4);
913 parts[tuple->n_children + 1] = (gchar *) ")";
914 parts[tuple->n_children + 2] = NULL;
915 parts[0] = (gchar *) "M(";
917 for (i = 0; i < tuple->n_children; i++)
918 if (!(parts[i + 1] = ast_get_pattern (tuple->children[i], error)))
921 if (i == tuple->n_children)
922 result = g_strjoinv ("", parts);
924 /* parts[0] should not be freed */
933 tuple_get_value (AST *ast,
934 const GVariantType *type,
937 Tuple *tuple = (Tuple *) ast;
938 const GVariantType *childtype;
939 GVariantBuilder builder;
942 if (!g_variant_type_is_tuple (type))
943 return ast_type_error (ast, type, error);
945 g_variant_builder_init (&builder, type);
946 childtype = g_variant_type_first (type);
948 for (i = 0; i < tuple->n_children; i++)
952 if (!(child = ast_get_value (tuple->children[i], childtype, error)))
954 g_variant_builder_clear (&builder);
958 g_variant_builder_add_value (&builder, child);
959 childtype = g_variant_type_next (childtype);
962 return g_variant_builder_end (&builder);
966 tuple_free (AST *ast)
968 Tuple *tuple = (Tuple *) ast;
970 ast_array_free (tuple->children, tuple->n_children);
971 g_slice_free (Tuple, tuple);
975 tuple_parse (TokenStream *stream,
979 static const ASTClass tuple_class = {
981 maybe_wrapper, tuple_get_value,
984 gboolean need_comma = FALSE;
985 gboolean first = TRUE;
988 tuple = g_slice_new (Tuple);
989 tuple->ast.class = &tuple_class;
990 tuple->children = NULL;
991 tuple->n_children = 0;
993 token_stream_assert (stream, "(");
994 while (!token_stream_consume (stream, ")"))
999 !token_stream_require (stream, ",",
1000 " or `)' to follow tuple element",
1004 child = parse (stream, app, error);
1009 ast_array_append (&tuple->children, &tuple->n_children, child);
1011 /* the first time, we absolutely require a comma, so grab it here
1012 * and leave need_comma = FALSE so that the code above doesn't
1013 * require a second comma.
1015 * the second and remaining times, we set need_comma = TRUE.
1019 if (!token_stream_require (stream, ",",
1020 " after first tuple element", error))
1029 return (AST *) tuple;
1032 ast_array_free (tuple->children, tuple->n_children);
1033 g_slice_free (Tuple, tuple);
1046 variant_get_pattern (AST *ast,
1049 return g_strdup ("Mv");
1053 variant_get_value (AST *ast,
1054 const GVariantType *type,
1057 Variant *variant = (Variant *) ast;
1060 g_assert (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT));
1061 child = ast_resolve (variant->value, error);
1066 return g_variant_new_variant (child);
1070 variant_free (AST *ast)
1072 Variant *variant = (Variant *) ast;
1074 ast_free (variant->value);
1075 g_slice_free (Variant, variant);
1079 variant_parse (TokenStream *stream,
1083 static const ASTClass variant_class = {
1084 variant_get_pattern,
1085 maybe_wrapper, variant_get_value,
1091 token_stream_assert (stream, "<");
1092 value = parse (stream, app, error);
1097 if (!token_stream_require (stream, ">", " to follow variant value", error))
1103 variant = g_slice_new (Variant);
1104 variant->ast.class = &variant_class;
1105 variant->value = value;
1107 return (AST *) variant;
1120 dictionary_get_pattern (AST *ast,
1123 Dictionary *dict = (Dictionary *) ast;
1124 gchar *value_pattern;
1129 if (dict->n_children == 0)
1130 return g_strdup ("Ma{**}");
1132 key_pattern = ast_array_get_pattern (dict->keys,
1133 abs (dict->n_children),
1136 if (key_pattern == NULL)
1139 /* we can not have maybe keys */
1140 if (key_pattern[0] == 'M')
1141 key_char = key_pattern[1];
1143 key_char = key_pattern[0];
1145 g_free (key_pattern);
1148 * plus undetermined number type and undetermined string type.
1150 if (!strchr ("bynqiuxthdsogNS", key_char))
1152 ast_set_error (ast, error, NULL,
1153 "dictionary keys must have basic types");
1157 value_pattern = ast_get_pattern (dict->values[0], error);
1159 if (value_pattern == NULL)
1162 result = g_strdup_printf ("M%s{%c%s}",
1163 dict->n_children > 0 ? "a" : "",
1164 key_char, value_pattern);
1165 g_free (value_pattern);
1171 dictionary_get_value (AST *ast,
1172 const GVariantType *type,
1175 Dictionary *dict = (Dictionary *) ast;
1177 if (dict->n_children == -1)
1179 const GVariantType *subtype;
1180 GVariantBuilder builder;
1183 if (!g_variant_type_is_dict_entry (type))
1184 return ast_type_error (ast, type, error);
1186 g_variant_builder_init (&builder, type);
1188 subtype = g_variant_type_key (type);
1189 if (!(subvalue = ast_get_value (dict->keys[0], subtype, error)))
1191 g_variant_builder_clear (&builder);
1194 g_variant_builder_add_value (&builder, subvalue);
1196 subtype = g_variant_type_value (type);
1197 if (!(subvalue = ast_get_value (dict->values[0], subtype, error)))
1199 g_variant_builder_clear (&builder);
1202 g_variant_builder_add_value (&builder, subvalue);
1204 return g_variant_builder_end (&builder);
1208 const GVariantType *entry, *key, *val;
1209 GVariantBuilder builder;
1212 if (!g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_DICTIONARY))
1213 return ast_type_error (ast, type, error);
1215 entry = g_variant_type_element (type);
1216 key = g_variant_type_key (entry);
1217 val = g_variant_type_value (entry);
1219 g_variant_builder_init (&builder, type);
1221 for (i = 0; i < dict->n_children; i++)
1225 g_variant_builder_open (&builder, entry);
1227 if (!(subvalue = ast_get_value (dict->keys[i], key, error)))
1229 g_variant_builder_clear (&builder);
1232 g_variant_builder_add_value (&builder, subvalue);
1234 if (!(subvalue = ast_get_value (dict->values[i], val, error)))
1236 g_variant_builder_clear (&builder);
1239 g_variant_builder_add_value (&builder, subvalue);
1240 g_variant_builder_close (&builder);
1243 return g_variant_builder_end (&builder);
1248 dictionary_free (AST *ast)
1250 Dictionary *dict = (Dictionary *) ast;
1253 if (dict->n_children > -1)
1254 n_children = dict->n_children;
1258 ast_array_free (dict->keys, n_children);
1259 ast_array_free (dict->values, n_children);
1260 g_slice_free (Dictionary, dict);
1264 dictionary_parse (TokenStream *stream,
1268 static const ASTClass dictionary_class = {
1269 dictionary_get_pattern,
1270 maybe_wrapper, dictionary_get_value,
1273 gint n_keys, n_values;
1278 dict = g_slice_new (Dictionary);
1279 dict->ast.class = &dictionary_class;
1281 dict->values = NULL;
1282 n_keys = n_values = 0;
1284 token_stream_assert (stream, "{");
1286 if (token_stream_consume (stream, "}"))
1288 dict->n_children = 0;
1289 return (AST *) dict;
1292 if ((first = parse (stream, app, error)) == NULL)
1295 ast_array_append (&dict->keys, &n_keys, first);
1297 only_one = token_stream_consume (stream, ",");
1299 !token_stream_require (stream, ":",
1300 " or `,' to follow dictionary entry key",
1304 if ((first = parse (stream, app, error)) == NULL)
1307 ast_array_append (&dict->values, &n_values, first);
1311 if (!token_stream_require (stream, "}", " at end of dictionary entry",
1315 g_assert (n_keys == 1 && n_values == 1);
1316 dict->n_children = -1;
1318 return (AST *) dict;
1321 while (!token_stream_consume (stream, "}"))
1325 if (!token_stream_require (stream, ",",
1326 " or `}' to follow dictionary entry", error))
1329 child = parse (stream, app, error);
1334 ast_array_append (&dict->keys, &n_keys, child);
1336 if (!token_stream_require (stream, ":",
1337 " to follow dictionary entry key", error))
1340 child = parse (stream, app, error);
1345 ast_array_append (&dict->values, &n_values, child);
1348 g_assert (n_keys == n_values);
1349 dict->n_children = n_keys;
1351 return (AST *) dict;
1354 ast_array_free (dict->keys, n_keys);
1355 ast_array_free (dict->values, n_values);
1356 g_slice_free (Dictionary, dict);
1368 string_get_pattern (AST *ast,
1371 return g_strdup ("MS");
1375 string_get_value (AST *ast,
1376 const GVariantType *type,
1379 String *string = (String *) ast;
1381 if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
1382 return g_variant_new_string (string->string);
1384 else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
1386 if (!g_variant_is_object_path (string->string))
1388 ast_set_error (ast, error, NULL, "not a valid object path");
1392 return g_variant_new_object_path (string->string);
1395 else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
1397 if (!g_variant_is_signature (string->string))
1399 ast_set_error (ast, error, NULL, "not a valid signature");
1403 return g_variant_new_signature (string->string);
1407 return ast_type_error (ast, type, error);
1411 string_free (AST *ast)
1413 String *string = (String *) ast;
1415 g_free (string->string);
1416 g_slice_free (String, string);
1420 unicode_unescape (const gchar *src,
1434 g_assert (length < sizeof (buffer));
1435 strncpy (buffer, src + *src_ofs, length);
1436 buffer[length] = '\0';
1438 value = g_ascii_strtoull (buffer, &end, 0x10);
1440 if (value == 0 || end != buffer + length)
1442 parser_set_error (error, ref, NULL,
1443 "invalid %d-character unicode escape", length);
1447 g_assert (value <= G_MAXUINT32);
1449 *dest_ofs += g_unichar_to_utf8 (value, dest + *dest_ofs);
1456 string_parse (TokenStream *stream,
1460 static const ASTClass string_class = {
1462 maybe_wrapper, string_get_value,
1473 token_stream_start_ref (stream, &ref);
1474 token = token_stream_get (stream);
1475 token_stream_end_ref (stream, &ref);
1476 length = strlen (token);
1479 str = g_malloc (length);
1480 g_assert (quote == '"' || quote == '\'');
1483 while (token[i] != quote)
1487 parser_set_error (error, &ref, NULL,
1488 "unterminated string constant");
1496 parser_set_error (error, &ref, NULL,
1497 "unterminated string constant");
1502 if (!unicode_unescape (token, &i, str, &j, 4, &ref, error))
1510 if (!unicode_unescape (token, &i, str, &j, 8, &ref, error))
1517 case 'a': str[j++] = '\a'; i++; continue;
1518 case 'b': str[j++] = '\b'; i++; continue;
1519 case 'f': str[j++] = '\f'; i++; continue;
1520 case 'n': str[j++] = '\n'; i++; continue;
1521 case 'r': str[j++] = '\r'; i++; continue;
1522 case 't': str[j++] = '\t'; i++; continue;
1523 case 'v': str[j++] = '\v'; i++; continue;
1524 case '\n': i++; continue;
1528 str[j++] = token[i++];
1533 string = g_slice_new (String);
1534 string->ast.class = &string_class;
1535 string->string = str;
1537 token_stream_next (stream);
1539 return (AST *) string;
1550 number_get_pattern (AST *ast,
1553 Number *number = (Number *) ast;
1555 if (strchr (number->token, '.') ||
1556 (!g_str_has_prefix (number->token, "0x") &&
1557 strchr (number->token, 'e')))
1558 return g_strdup ("Md");
1560 return g_strdup ("MN");
1564 number_overflow (AST *ast,
1565 const GVariantType *type,
1568 ast_set_error (ast, error, NULL, "number out of range for type `%c'",
1569 g_variant_type_peek_string (type)[0]);
1574 number_get_value (AST *ast,
1575 const GVariantType *type,
1578 Number *number = (Number *) ast;
1586 token = number->token;
1588 if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
1593 dbl_val = g_ascii_strtod (token, &end);
1594 if (dbl_val != 0.0 && errno == ERANGE)
1596 ast_set_error (ast, error, NULL, "number too big for any type");
1600 /* silence uninitialised warnings... */
1607 negative = token[0] == '-';
1608 if (token[0] == '-')
1612 abs_val = g_ascii_strtoull (token, &end, 0);
1613 if (abs_val == G_MAXUINT64 && errno == ERANGE)
1615 ast_set_error (ast, error, NULL, "integer too big for any type");
1622 /* silence uninitialised warning... */
1630 ref = ast->source_ref;
1631 ref.start += end - number->token;
1632 ref.end = ref.start + 1;
1634 parser_set_error (error, &ref, NULL,
1635 "invalid character in number");
1640 return g_variant_new_double (dbl_val);
1642 switch (*g_variant_type_peek_string (type))
1645 if (negative || abs_val > G_MAXUINT8)
1646 return number_overflow (ast, type, error);
1647 return g_variant_new_byte (abs_val);
1650 if (abs_val - negative > G_MAXINT16)
1651 return number_overflow (ast, type, error);
1652 return g_variant_new_int16 (negative ? -abs_val : abs_val);
1655 if (negative || abs_val > G_MAXUINT16)
1656 return number_overflow (ast, type, error);
1657 return g_variant_new_uint16 (negative ? -abs_val : abs_val);
1660 if (abs_val - negative > G_MAXINT32)
1661 return number_overflow (ast, type, error);
1662 return g_variant_new_int32 (negative ? -abs_val : abs_val);
1665 if (negative || abs_val > G_MAXUINT32)
1666 return number_overflow (ast, type, error);
1667 return g_variant_new_uint32 (negative ? -abs_val : abs_val);
1670 if (abs_val - negative > G_MAXINT64)
1671 return number_overflow (ast, type, error);
1672 return g_variant_new_int64 (negative ? -abs_val : abs_val);
1676 return number_overflow (ast, type, error);
1677 return g_variant_new_uint64 (negative ? -abs_val : abs_val);
1680 if (abs_val - negative > G_MAXINT32)
1681 return number_overflow (ast, type, error);
1682 return g_variant_new_handle (negative ? -abs_val : abs_val);
1685 return ast_type_error (ast, type, error);
1690 number_free (AST *ast)
1692 Number *number = (Number *) ast;
1694 g_free (number->token);
1695 g_slice_free (Number, number);
1699 number_parse (TokenStream *stream,
1703 static const ASTClass number_class = {
1705 maybe_wrapper, number_get_value,
1710 number = g_slice_new (Number);
1711 number->ast.class = &number_class;
1712 number->token = token_stream_get (stream);
1713 token_stream_next (stream);
1715 return (AST *) number;
1725 boolean_get_pattern (AST *ast,
1728 return g_strdup ("Mb");
1732 boolean_get_value (AST *ast,
1733 const GVariantType *type,
1736 Boolean *boolean = (Boolean *) ast;
1738 if (!g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
1739 return ast_type_error (ast, type, error);
1741 return g_variant_new_boolean (boolean->value);
1745 boolean_free (AST *ast)
1747 Boolean *boolean = (Boolean *) ast;
1749 g_slice_free (Boolean, boolean);
1753 boolean_new (gboolean value)
1755 static const ASTClass boolean_class = {
1756 boolean_get_pattern,
1757 maybe_wrapper, boolean_get_value,
1762 boolean = g_slice_new (Boolean);
1763 boolean->ast.class = &boolean_class;
1764 boolean->value = value;
1766 return (AST *) boolean;
1777 positional_get_pattern (AST *ast,
1780 Positional *positional = (Positional *) ast;
1782 return g_strdup (g_variant_get_type_string (positional->value));
1786 positional_get_value (AST *ast,
1787 const GVariantType *type,
1790 Positional *positional = (Positional *) ast;
1793 g_assert (positional->value != NULL);
1795 if G_UNLIKELY (!g_variant_is_of_type (positional->value, type))
1796 return ast_type_error (ast, type, error);
1798 /* NOTE: if _get is called more than once then
1799 * things get messed up with respect to floating refs.
1801 * fortunately, this function should only ever get called once.
1803 g_assert (positional->value != NULL);
1804 value = positional->value;
1805 positional->value = NULL;
1811 positional_free (AST *ast)
1813 Positional *positional = (Positional *) ast;
1815 /* if positional->value is set, just leave it.
1816 * memory management doesn't matter in case of programmer error.
1818 g_slice_free (Positional, positional);
1822 positional_parse (TokenStream *stream,
1826 static const ASTClass positional_class = {
1827 positional_get_pattern,
1828 positional_get_value, NULL,
1831 Positional *positional;
1832 const gchar *endptr;
1835 token = token_stream_get (stream);
1836 g_assert (token[0] == '%');
1838 positional = g_slice_new (Positional);
1839 positional->ast.class = &positional_class;
1840 positional->value = g_variant_new_va (token + 1, &endptr, app);
1842 if (*endptr || positional->value == NULL)
1844 token_stream_set_error (stream, error, TRUE,
1845 "invalid GVariant format string");
1846 /* memory management doesn't matter in case of programmer error. */
1850 token_stream_next (stream);
1853 return (AST *) positional;
1865 typedecl_get_pattern (AST *ast,
1868 TypeDecl *decl = (TypeDecl *) ast;
1870 return g_variant_type_dup_string (decl->type);
1874 typedecl_get_value (AST *ast,
1875 const GVariantType *type,
1878 TypeDecl *decl = (TypeDecl *) ast;
1880 return ast_get_value (decl->child, type, error);
1884 typedecl_free (AST *ast)
1886 TypeDecl *decl = (TypeDecl *) ast;
1888 ast_free (decl->child);
1889 g_variant_type_free (decl->type);
1890 g_slice_free (TypeDecl, decl);
1894 typedecl_parse (TokenStream *stream,
1898 static const ASTClass typedecl_class = {
1899 typedecl_get_pattern,
1900 typedecl_get_value, NULL,
1907 if (token_stream_peek (stream, '@'))
1911 token = token_stream_get (stream);
1913 if (!g_variant_type_string_is_valid (token + 1))
1915 token_stream_set_error (stream, error, TRUE,
1916 "invalid type declaration");
1922 type = g_variant_type_new (token + 1);
1924 if (!g_variant_type_is_definite (type))
1926 token_stream_set_error (stream, error, TRUE,
1927 "type declarations must be definite");
1928 g_variant_type_free (type);
1934 token_stream_next (stream);
1939 if (token_stream_consume (stream, "boolean"))
1940 type = g_variant_type_copy (G_VARIANT_TYPE_BOOLEAN);
1942 else if (token_stream_consume (stream, "byte"))
1943 type = g_variant_type_copy (G_VARIANT_TYPE_BYTE);
1945 else if (token_stream_consume (stream, "int16"))
1946 type = g_variant_type_copy (G_VARIANT_TYPE_INT16);
1948 else if (token_stream_consume (stream, "uint16"))
1949 type = g_variant_type_copy (G_VARIANT_TYPE_UINT16);
1951 else if (token_stream_consume (stream, "int32"))
1952 type = g_variant_type_copy (G_VARIANT_TYPE_INT32);
1954 else if (token_stream_consume (stream, "handle"))
1955 type = g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
1957 else if (token_stream_consume (stream, "uint32"))
1958 type = g_variant_type_copy (G_VARIANT_TYPE_UINT32);
1960 else if (token_stream_consume (stream, "int64"))
1961 type = g_variant_type_copy (G_VARIANT_TYPE_INT64);
1963 else if (token_stream_consume (stream, "uint64"))
1964 type = g_variant_type_copy (G_VARIANT_TYPE_UINT64);
1966 else if (token_stream_consume (stream, "double"))
1967 type = g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
1969 else if (token_stream_consume (stream, "string"))
1970 type = g_variant_type_copy (G_VARIANT_TYPE_STRING);
1972 else if (token_stream_consume (stream, "objectpath"))
1973 type = g_variant_type_copy (G_VARIANT_TYPE_OBJECT_PATH);
1975 else if (token_stream_consume (stream, "signature"))
1976 type = g_variant_type_copy (G_VARIANT_TYPE_SIGNATURE);
1980 token_stream_set_error (stream, error, TRUE, "unknown keyword");
1985 if ((child = parse (stream, app, error)) == NULL)
1987 g_variant_type_free (type);
1991 decl = g_slice_new (TypeDecl);
1992 decl->ast.class = &typedecl_class;
1994 decl->child = child;
1996 return (AST *) decl;
2000 parse (TokenStream *stream,
2004 SourceRef source_ref;
2007 token_stream_prepare (stream);
2008 token_stream_start_ref (stream, &source_ref);
2010 if (token_stream_peek (stream, '['))
2011 result = array_parse (stream, app, error);
2013 else if (token_stream_peek (stream, '('))
2014 result = tuple_parse (stream, app, error);
2016 else if (token_stream_peek (stream, '<'))
2017 result = variant_parse (stream, app, error);
2019 else if (token_stream_peek (stream, '{'))
2020 result = dictionary_parse (stream, app, error);
2022 else if (app && token_stream_peek (stream, '%'))
2023 result = positional_parse (stream, app, error);
2025 else if (token_stream_consume (stream, "true"))
2026 result = boolean_new (TRUE);
2028 else if (token_stream_consume (stream, "false"))
2029 result = boolean_new (FALSE);
2031 else if (token_stream_peek (stream, 'n') ||
2032 token_stream_peek (stream, 'j'))
2033 result = maybe_parse (stream, app, error);
2035 else if (token_stream_peek (stream, '@') ||
2036 token_stream_is_keyword (stream))
2037 result = typedecl_parse (stream, app, error);
2039 else if (token_stream_is_numeric (stream))
2040 result = number_parse (stream, app, error);
2042 else if (token_stream_peek (stream, '\'') ||
2043 token_stream_peek (stream, '"'))
2044 result = string_parse (stream, app, error);
2048 token_stream_set_error (stream, error, FALSE, "expected value");
2054 token_stream_end_ref (stream, &source_ref);
2055 result->source_ref = source_ref;
2063 * @type: a #GVariantType, or %NULL
2064 * @text: a string containing a GVariant in text form
2065 * @limit: a pointer to the end of @text, or %NULL
2066 * @endptr: a location to store the end pointer, or %NULL
2067 * @error: a pointer to a %NULL #GError pointer, or %NULL
2068 * @Returns: a reference to a #GVariant, or %NULL
2070 * Parses a #GVariant from a text representation.
2072 * A single #GVariant is parsed from the content of @text.
2074 * The memory at @limit will never be accessed and the parser behaves as
2075 * if the character at @limit is the nul terminator. This has the
2076 * effect of bounding @text.
2078 * If @endptr is non-%NULL then @text is permitted to contain data
2079 * following the value that this function parses and @endptr will be
2080 * updated to point to the first character past the end of the text
2081 * parsed by this function. If @endptr is %NULL and there is extra data
2082 * then an error is returned.
2084 * If @type is non-%NULL then the value will be parsed to have that
2085 * type. This may result in additional parse errors (in the case that
2086 * the parsed value doesn't fit the type) but may also result in fewer
2087 * errors (in the case that the type would have been ambiguous, such as
2088 * with empty arrays).
2090 * In the event that the parsing is successful, the resulting #GVariant
2093 * In case of any error, %NULL will be returned. If @error is non-%NULL
2094 * then it will be set to reflect the error that occured.
2096 * Officially, the language understood by the parser is "any string
2097 * produced by g_variant_print()".
2100 g_variant_parse (const GVariantType *type,
2103 const gchar **endptr,
2106 TokenStream stream = { 0, };
2107 GVariant *result = NULL;
2110 g_return_val_if_fail (text != NULL, NULL);
2111 g_return_val_if_fail (text == limit || text != NULL, NULL);
2113 stream.start = text;
2114 stream.stream = text;
2117 if ((ast = parse (&stream, NULL, error)))
2120 result = ast_resolve (ast, error);
2122 result = ast_get_value (ast, type, error);
2126 g_variant_ref_sink (result);
2130 while (stream.stream != limit &&
2131 g_ascii_isspace (*stream.stream))
2134 if (stream.stream != limit && *stream.stream != '\0')
2136 SourceRef ref = { stream.stream - text,
2137 stream.stream - text };
2139 parser_set_error (error, &ref, NULL,
2140 "expected end of input");
2141 g_variant_unref (result);
2147 *endptr = stream.stream;
2157 * g_variant_new_parsed_va:
2158 * @format: a text format #GVariant
2159 * @app: a pointer to a #va_list
2160 * @returns: a new, usually floating, #GVariant
2162 * Parses @format and returns the result.
2164 * This is the version of g_variant_new_parsed() intended to be used
2167 * The return value will be floating if it was a newly created GVariant
2168 * instance. In the case that @format simply specified the collection
2169 * of a #GVariant pointer (eg: @format was "%*") then the collected
2170 * #GVariant pointer will be returned unmodified, without adding any
2171 * additional references.
2173 * In order to behave correctly in all cases it is necessary for the
2174 * calling function to g_variant_ref_sink() the return result before
2175 * returning control to the user that originally provided the pointer.
2176 * At this point, the caller will have their own full reference to the
2177 * result. This can also be done by adding the result to a container,
2178 * or by passing it to another g_variant_new() call.
2181 g_variant_new_parsed_va (const gchar *format,
2184 TokenStream stream = { 0, };
2185 GVariant *result = NULL;
2186 GError *error = NULL;
2189 g_return_val_if_fail (format != NULL, NULL);
2190 g_return_val_if_fail (app != NULL, NULL);
2192 stream.start = format;
2193 stream.stream = format;
2196 if ((ast = parse (&stream, app, &error)))
2198 result = ast_resolve (ast, &error);
2203 g_error ("g_variant_new_parsed: %s", error->message);
2206 g_error ("g_variant_new_parsed: trailing text after value");
2212 * g_variant_new_parsed:
2213 * @format: a text format #GVariant
2214 * @...: arguments as per @format
2215 * @returns: a new floating #GVariant instance
2217 * Parses @format and returns the result.
2219 * @format must be a text format #GVariant with one extention: at any
2220 * point that a value may appear in the text, a '%' character followed
2221 * by a GVariant format string (as per g_variant_new()) may appear. In
2222 * that case, the same arguments are collected from the argument list as
2223 * g_variant_new() would have collected.
2225 * Consider this simple example:
2227 * <informalexample><programlisting>
2228 * g_variant_new_parsed ("[('one', 1), ('two', %i), (%s, 3)]", 2, "three");
2229 * </programlisting></informalexample>
2231 * In the example, the variable argument parameters are collected and
2232 * filled in as if they were part of the original string to produce the
2233 * result of <code>[('one', 1), ('two', 2), ('three', 3)]</code>.
2235 * This function is intended only to be used with @format as a string
2236 * literal. Any parse error is fatal to the calling process. If you
2237 * want to parse data from untrusted sources, use g_variant_parse().
2239 * You may not use this function to return, unmodified, a single
2240 * #GVariant pointer from the argument list. ie: @format may not solely
2241 * be anything along the lines of "%*", "%?", "%r", or anything starting
2245 g_variant_new_parsed (const gchar *format,
2251 va_start (ap, format);
2252 result = g_variant_new_parsed_va (format, &ap);
2259 * g_variant_builder_add_parsed:
2260 * @builder: a #GVariantBuilder
2261 * @format: a text format #GVariant
2262 * @...: arguments as per @format
2264 * Adds to a #GVariantBuilder.
2266 * This call is a convenience wrapper that is exactly equivalent to
2267 * calling g_variant_new_parsed() followed by
2268 * g_variant_builder_add_value().
2270 * This function might be used as follows:
2274 * make_pointless_dictionary (void)
2276 * GVariantBuilder *builder;
2279 * builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
2280 * g_variant_builder_add_parsed (builder, "{'width', <%i>}", 600);
2281 * g_variant_builder_add_parsed (builder, "{'title', <%s>}", "foo");
2282 * g_variant_builder_add_parsed (builder, "{'transparency', <0.5>}");
2283 * return g_variant_builder_end (builder);
2290 g_variant_builder_add_parsed (GVariantBuilder *builder,
2291 const gchar *format,
2296 va_start (ap, format);
2297 g_variant_builder_add_value (builder, g_variant_new_parsed_va (format, &ap));
2302 #define __G_VARIANT_PARSER_C__
2303 #include "galiasdef.c"