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.
43 g_variant_parser_get_error_quark (void)
45 static GQuark the_quark;
48 the_quark = g_quark_from_static_string ("g-variant-parse-error-quark");
59 parser_set_error_va (GError **error,
65 GString *msg = g_string_new (NULL);
67 if (location->start == location->end)
68 g_string_append_printf (msg, "%d", location->start);
70 g_string_append_printf (msg, "%d-%d", location->start, location->end);
74 g_assert (other->start != other->end);
75 g_string_append_printf (msg, ",%d-%d", other->start, other->end);
77 g_string_append_c (msg, ':');
79 g_string_append_vprintf (msg, format, ap);
80 g_set_error_literal (error, G_VARIANT_PARSE_ERROR, 0, msg->str);
81 g_string_free (msg, TRUE);
85 parser_set_error (GError **error,
93 va_start (ap, format);
94 parser_set_error_va (error, location, other, format, ap);
109 token_stream_set_error (TokenStream *stream,
118 ref.start = stream->this - stream->start;
121 ref.end = stream->stream - stream->start;
125 va_start (ap, format);
126 parser_set_error_va (error, &ref, NULL, format, ap);
131 token_stream_prepare (TokenStream *stream)
136 if (stream->this != NULL)
139 while (stream->stream != stream->end && g_ascii_isspace (*stream->stream))
142 if (stream->stream == stream->end || *stream->stream == '\0')
144 stream->this = stream->stream;
148 switch (stream->stream[0])
150 case '-': case '+': case '.': case '0': case '1': case '2':
151 case '3': case '4': case '5': case '6': case '7': case '8':
153 for (end = stream->stream; end != stream->end; end++)
154 if (!g_ascii_isalnum (*end) &&
155 *end != '-' && *end != '+' && *end != '.')
159 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
160 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
161 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
162 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
164 for (end = stream->stream; end != stream->end; end++)
165 if (!g_ascii_isalnum (*end))
170 /* stop at the first space, comma, colon or unmatched bracket.
171 * deals nicely with cases like (%i, %i) or {%i: %i}.
173 for (end = stream->stream + 1;
174 end != stream->end && *end != ',' &&
175 *end != ':' && !g_ascii_isspace (*end);
178 if (*end == '(' || *end == '{')
181 else if ((*end == ')' || *end == '}') && !brackets--)
187 for (end = stream->stream + 1; end != stream->end; end++)
188 if (*end == stream->stream[0] || *end == '\0' ||
189 (*end == '\\' && (++end == stream->end || *end == '\0')))
192 if (end != stream->end && *end)
197 end = stream->stream + 1;
201 stream->this = stream->stream;
202 stream->stream = end;
206 token_stream_next (TokenStream *stream)
212 token_stream_peek (TokenStream *stream,
215 token_stream_prepare (stream);
217 return stream->this[0] == first_char;
221 token_stream_is_keyword (TokenStream *stream)
223 token_stream_prepare (stream);
225 return g_ascii_isalpha (stream->this[0]);
229 token_stream_is_numeric (TokenStream *stream)
231 token_stream_prepare (stream);
233 return (g_ascii_isdigit (stream->this[0]) ||
234 stream->this[0] == '-' ||
235 stream->this[0] == '+' ||
236 stream->this[0] == '.');
240 token_stream_consume (TokenStream *stream,
243 gint length = strlen (token);
245 token_stream_prepare (stream);
247 if (stream->stream - stream->this == length &&
248 memcmp (stream->this, token, length) == 0)
250 token_stream_next (stream);
258 token_stream_require (TokenStream *stream,
260 const gchar *purpose,
264 if (!token_stream_consume (stream, token))
266 token_stream_set_error (stream, error, FALSE,
267 "expected `%s'%s", token, purpose);
275 token_stream_assert (TokenStream *stream,
278 gboolean correct_token;
280 correct_token = token_stream_consume (stream, token);
281 g_assert (correct_token);
285 token_stream_get (TokenStream *stream)
289 token_stream_prepare (stream);
291 result = g_strndup (stream->this, stream->stream - stream->this);
297 token_stream_start_ref (TokenStream *stream,
300 token_stream_prepare (stream);
301 ref->start = stream->this - stream->start;
305 token_stream_end_ref (TokenStream *stream,
308 ref->end = stream->stream - stream->start;
312 pattern_copy (gchar **out,
317 while (**in == 'a' || **in == 'm' || **in == 'M')
318 *(*out)++ = *(*in)++;
322 if (**in == '(' || **in == '{')
325 else if (**in == ')' || **in == '}')
328 *(*out)++ = *(*in)++;
334 pattern_coalesce (const gchar *left,
340 /* the length of the output is loosely bound by the sum of the input
341 * lengths, not simply the greater of the two lengths.
343 * (*(iii)) + ((iii)*) ((iii)(iii))
347 out = result = g_malloc (strlen (left) + strlen (right));
349 while (*left && *right)
359 const gchar **one = &left, **the_other = &right;
362 if (**one == '*' && **the_other != ')')
364 pattern_copy (&out, the_other);
368 else if (**one == 'M' && **the_other == 'm')
370 *out++ = *(*the_other)++;
373 else if (**one == 'M' && **the_other != 'm')
378 else if (**one == 'N' && strchr ("ynqiuxthd", **the_other))
380 *out++ = *(*the_other)++;
384 else if (**one == 'S' && strchr ("sog", **the_other))
386 *out++ = *(*the_other)++;
390 else if (one == &left)
392 one = &right, the_other = &left;
412 typedef struct _AST AST;
413 typedef gchar * (*get_pattern_func) (AST *ast,
415 typedef GVariant * (*get_value_func) (AST *ast,
416 const GVariantType *type,
418 typedef GVariant * (*get_base_value_func) (AST *ast,
419 const GVariantType *type,
421 typedef void (*free_func) (AST *ast);
425 gchar * (* get_pattern) (AST *ast,
427 GVariant * (* get_value) (AST *ast,
428 const GVariantType *type,
430 GVariant * (* get_base_value) (AST *ast,
431 const GVariantType *type,
433 void (* free) (AST *ast);
438 const ASTClass *class;
439 SourceRef source_ref;
443 ast_get_pattern (AST *ast,
446 return ast->class->get_pattern (ast, error);
450 ast_get_value (AST *ast,
451 const GVariantType *type,
454 return ast->class->get_value (ast, type, error);
460 ast->class->free (ast);
464 ast_set_error (AST *ast,
472 va_start (ap, format);
473 parser_set_error_va (error, &ast->source_ref,
474 other_ast ? & other_ast->source_ref : NULL,
480 ast_type_error (AST *ast,
481 const GVariantType *type,
486 typestr = g_variant_type_dup_string (type);
487 ast_set_error (ast, error, NULL,
488 "can not parse as value of type `%s'",
496 ast_resolve (AST *ast,
503 pattern = ast_get_pattern (ast, error);
508 /* choose reasonable defaults
510 * 1) favour non-maybe values where possible
511 * 2) default type for strings is 's'
512 * 3) default type for integers is 'i'
514 for (i = 0; pattern[i]; i++)
518 ast_set_error (ast, error, NULL, "unable to infer type");
534 pattern[j++] = pattern[i];
539 value = ast_get_value (ast, G_VARIANT_TYPE (pattern), error);
546 static AST *parse (TokenStream *stream,
551 ast_array_append (AST ***array,
555 if ((*n_items & (*n_items - 1)) == 0)
556 *array = g_renew (AST *, *array, *n_items ? 2 ** n_items : 1);
558 (*array)[(*n_items)++] = ast;
562 ast_array_free (AST **array,
567 for (i = 0; i < n_items; i++)
573 ast_array_get_pattern (AST **array,
580 pattern = ast_get_pattern (array[0], error);
585 for (i = 1; i < n_items; i++)
589 tmp = ast_get_pattern (array[i], error);
597 merged = pattern_coalesce (pattern, tmp);
602 /* set coalescence implies pairwise coalescence (i think).
603 * we should therefore be able to trace the failure to a single
614 /* if 'j' reaches 'i' then we failed to find the pair */
617 tmp2 = ast_get_pattern (array[j], NULL);
618 g_assert (tmp2 != NULL);
620 m = pattern_coalesce (tmp, tmp2);
626 /* we found a conflict between 'i' and 'j'.
628 * report the error. note: 'j' is first.
630 ast_set_error (array[j], error, array[i],
631 "unable to find a common type");
652 maybe_get_pattern (AST *ast,
655 Maybe *maybe = (Maybe *) ast;
657 if (maybe->child != NULL)
659 gchar *child_pattern;
662 child_pattern = ast_get_pattern (maybe->child, error);
664 if (child_pattern == NULL)
667 pattern = g_strdup_printf ("m%s", child_pattern);
668 g_free (child_pattern);
673 return g_strdup ("m*");
677 maybe_get_value (AST *ast,
678 const GVariantType *type,
681 Maybe *maybe = (Maybe *) ast;
684 if (!g_variant_type_is_maybe (type))
685 return ast_type_error (ast, type, error);
687 type = g_variant_type_element (type);
691 value = ast_get_value (maybe->child, type, error);
699 return g_variant_new_maybe (type, value);
703 maybe_free (AST *ast)
705 Maybe *maybe = (Maybe *) ast;
707 if (maybe->child != NULL)
708 ast_free (maybe->child);
710 g_slice_free (Maybe, maybe);
714 maybe_parse (TokenStream *stream,
718 static const ASTClass maybe_class = {
720 maybe_get_value, NULL,
726 if (token_stream_consume (stream, "just"))
728 child = parse (stream, app, error);
733 else if (!token_stream_consume (stream, "nothing"))
735 token_stream_set_error (stream, error, TRUE, "unknown keyword");
739 maybe = g_slice_new (Maybe);
740 maybe->ast.class = &maybe_class;
741 maybe->child = child;
743 return (AST *) maybe;
747 maybe_wrapper (AST *ast,
748 const GVariantType *type,
751 const GVariantType *t;
755 for (depth = 0, t = type;
756 g_variant_type_is_maybe (t);
757 depth++, t = g_variant_type_element (t));
759 value = ast->class->get_base_value (ast, t, error);
765 value = g_variant_new_maybe (NULL, value);
779 array_get_pattern (AST *ast,
782 Array *array = (Array *) ast;
786 if (array->n_children == 0)
787 return g_strdup ("Ma*");
789 pattern = ast_array_get_pattern (array->children, array->n_children, error);
794 result = g_strdup_printf ("Ma%s", pattern);
801 array_get_value (AST *ast,
802 const GVariantType *type,
805 Array *array = (Array *) ast;
806 const GVariantType *childtype;
807 GVariantBuilder builder;
810 if (!g_variant_type_is_array (type))
811 return ast_type_error (ast, type, error);
813 g_variant_builder_init (&builder, type);
814 childtype = g_variant_type_element (type);
816 for (i = 0; i < array->n_children; i++)
820 if (!(child = ast_get_value (array->children[i], childtype, error)))
822 g_variant_builder_clear (&builder);
826 g_variant_builder_add_value (&builder, child);
829 return g_variant_builder_end (&builder);
833 array_free (AST *ast)
835 Array *array = (Array *) ast;
837 ast_array_free (array->children, array->n_children);
838 g_slice_free (Array, array);
842 array_parse (TokenStream *stream,
846 static const ASTClass array_class = {
848 maybe_wrapper, array_get_value,
851 gboolean need_comma = FALSE;
854 array = g_slice_new (Array);
855 array->ast.class = &array_class;
856 array->children = NULL;
857 array->n_children = 0;
859 token_stream_assert (stream, "[");
860 while (!token_stream_consume (stream, "]"))
865 !token_stream_require (stream, ",",
866 " or `]' to follow array element",
870 child = parse (stream, app, error);
875 ast_array_append (&array->children, &array->n_children, child);
879 return (AST *) array;
882 ast_array_free (array->children, array->n_children);
883 g_slice_free (Array, array);
897 tuple_get_pattern (AST *ast,
900 Tuple *tuple = (Tuple *) ast;
901 gchar *result = NULL;
905 parts = g_new (gchar *, tuple->n_children + 4);
906 parts[tuple->n_children + 1] = (gchar *) ")";
907 parts[tuple->n_children + 2] = NULL;
908 parts[0] = (gchar *) "M(";
910 for (i = 0; i < tuple->n_children; i++)
911 if (!(parts[i + 1] = ast_get_pattern (tuple->children[i], error)))
914 if (i == tuple->n_children)
915 result = g_strjoinv ("", parts);
917 /* parts[0] should not be freed */
926 tuple_get_value (AST *ast,
927 const GVariantType *type,
930 Tuple *tuple = (Tuple *) ast;
931 const GVariantType *childtype;
932 GVariantBuilder builder;
935 if (!g_variant_type_is_tuple (type))
936 return ast_type_error (ast, type, error);
938 g_variant_builder_init (&builder, type);
939 childtype = g_variant_type_first (type);
941 for (i = 0; i < tuple->n_children; i++)
945 if (!(child = ast_get_value (tuple->children[i], childtype, error)))
947 g_variant_builder_clear (&builder);
951 g_variant_builder_add_value (&builder, child);
952 childtype = g_variant_type_next (childtype);
955 return g_variant_builder_end (&builder);
959 tuple_free (AST *ast)
961 Tuple *tuple = (Tuple *) ast;
963 ast_array_free (tuple->children, tuple->n_children);
964 g_slice_free (Tuple, tuple);
968 tuple_parse (TokenStream *stream,
972 static const ASTClass tuple_class = {
974 maybe_wrapper, tuple_get_value,
977 gboolean need_comma = FALSE;
978 gboolean first = TRUE;
981 tuple = g_slice_new (Tuple);
982 tuple->ast.class = &tuple_class;
983 tuple->children = NULL;
984 tuple->n_children = 0;
986 token_stream_assert (stream, "(");
987 while (!token_stream_consume (stream, ")"))
992 !token_stream_require (stream, ",",
993 " or `)' to follow tuple element",
997 child = parse (stream, app, error);
1002 ast_array_append (&tuple->children, &tuple->n_children, child);
1004 /* the first time, we absolutely require a comma, so grab it here
1005 * and leave need_comma = FALSE so that the code above doesn't
1006 * require a second comma.
1008 * the second and remaining times, we set need_comma = TRUE.
1012 if (!token_stream_require (stream, ",",
1013 " after first tuple element", error))
1022 return (AST *) tuple;
1025 ast_array_free (tuple->children, tuple->n_children);
1026 g_slice_free (Tuple, tuple);
1039 variant_get_pattern (AST *ast,
1042 return g_strdup ("Mv");
1046 variant_get_value (AST *ast,
1047 const GVariantType *type,
1050 Variant *variant = (Variant *) ast;
1053 g_assert (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT));
1054 child = ast_resolve (variant->value, error);
1059 return g_variant_new_variant (child);
1063 variant_free (AST *ast)
1065 Variant *variant = (Variant *) ast;
1067 ast_free (variant->value);
1068 g_slice_free (Variant, variant);
1072 variant_parse (TokenStream *stream,
1076 static const ASTClass variant_class = {
1077 variant_get_pattern,
1078 maybe_wrapper, variant_get_value,
1084 token_stream_assert (stream, "<");
1085 value = parse (stream, app, error);
1090 if (!token_stream_require (stream, ">", " to follow variant value", error))
1096 variant = g_slice_new (Variant);
1097 variant->ast.class = &variant_class;
1098 variant->value = value;
1100 return (AST *) variant;
1113 dictionary_get_pattern (AST *ast,
1116 Dictionary *dict = (Dictionary *) ast;
1117 gchar *value_pattern;
1122 if (dict->n_children == 0)
1123 return g_strdup ("Ma{**}");
1125 key_pattern = ast_array_get_pattern (dict->keys,
1126 abs (dict->n_children),
1129 if (key_pattern == NULL)
1132 /* we can not have maybe keys */
1133 if (key_pattern[0] == 'M')
1134 key_char = key_pattern[1];
1136 key_char = key_pattern[0];
1138 g_free (key_pattern);
1141 * plus undetermined number type and undetermined string type.
1143 if (!strchr ("bynqiuxthdsogNS", key_char))
1145 ast_set_error (ast, error, NULL,
1146 "dictionary keys must have basic types");
1150 value_pattern = ast_get_pattern (dict->values[0], error);
1152 if (value_pattern == NULL)
1155 result = g_strdup_printf ("M%s{%c%s}",
1156 dict->n_children > 0 ? "a" : "",
1157 key_char, value_pattern);
1158 g_free (value_pattern);
1164 dictionary_get_value (AST *ast,
1165 const GVariantType *type,
1168 Dictionary *dict = (Dictionary *) ast;
1170 if (dict->n_children == -1)
1172 const GVariantType *subtype;
1173 GVariantBuilder builder;
1176 if (!g_variant_type_is_dict_entry (type))
1177 return ast_type_error (ast, type, error);
1179 g_variant_builder_init (&builder, type);
1181 subtype = g_variant_type_key (type);
1182 if (!(subvalue = ast_get_value (dict->keys[0], subtype, error)))
1184 g_variant_builder_clear (&builder);
1187 g_variant_builder_add_value (&builder, subvalue);
1189 subtype = g_variant_type_value (type);
1190 if (!(subvalue = ast_get_value (dict->values[0], subtype, error)))
1192 g_variant_builder_clear (&builder);
1195 g_variant_builder_add_value (&builder, subvalue);
1197 return g_variant_builder_end (&builder);
1201 const GVariantType *entry, *key, *val;
1202 GVariantBuilder builder;
1205 if (!g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_DICTIONARY))
1206 return ast_type_error (ast, type, error);
1208 entry = g_variant_type_element (type);
1209 key = g_variant_type_key (entry);
1210 val = g_variant_type_value (entry);
1212 g_variant_builder_init (&builder, type);
1214 for (i = 0; i < dict->n_children; i++)
1218 g_variant_builder_open (&builder, entry);
1220 if (!(subvalue = ast_get_value (dict->keys[i], key, error)))
1222 g_variant_builder_clear (&builder);
1225 g_variant_builder_add_value (&builder, subvalue);
1227 if (!(subvalue = ast_get_value (dict->values[i], val, error)))
1229 g_variant_builder_clear (&builder);
1232 g_variant_builder_add_value (&builder, subvalue);
1233 g_variant_builder_close (&builder);
1236 return g_variant_builder_end (&builder);
1241 dictionary_free (AST *ast)
1243 Dictionary *dict = (Dictionary *) ast;
1246 if (dict->n_children > -1)
1247 n_children = dict->n_children;
1251 ast_array_free (dict->keys, n_children);
1252 ast_array_free (dict->values, n_children);
1253 g_slice_free (Dictionary, dict);
1257 dictionary_parse (TokenStream *stream,
1261 static const ASTClass dictionary_class = {
1262 dictionary_get_pattern,
1263 maybe_wrapper, dictionary_get_value,
1266 gint n_keys, n_values;
1271 dict = g_slice_new (Dictionary);
1272 dict->ast.class = &dictionary_class;
1274 dict->values = NULL;
1275 n_keys = n_values = 0;
1277 token_stream_assert (stream, "{");
1279 if (token_stream_consume (stream, "}"))
1281 dict->n_children = 0;
1282 return (AST *) dict;
1285 if ((first = parse (stream, app, error)) == NULL)
1288 ast_array_append (&dict->keys, &n_keys, first);
1290 only_one = token_stream_consume (stream, ",");
1292 !token_stream_require (stream, ":",
1293 " or `,' to follow dictionary entry key",
1297 if ((first = parse (stream, app, error)) == NULL)
1300 ast_array_append (&dict->values, &n_values, first);
1304 if (!token_stream_require (stream, "}", " at end of dictionary entry",
1308 g_assert (n_keys == 1 && n_values == 1);
1309 dict->n_children = -1;
1311 return (AST *) dict;
1314 while (!token_stream_consume (stream, "}"))
1318 if (!token_stream_require (stream, ",",
1319 " or `}' to follow dictionary entry", error))
1322 child = parse (stream, app, error);
1327 ast_array_append (&dict->keys, &n_keys, child);
1329 if (!token_stream_require (stream, ":",
1330 " to follow dictionary entry key", error))
1333 child = parse (stream, app, error);
1338 ast_array_append (&dict->values, &n_values, child);
1341 g_assert (n_keys == n_values);
1342 dict->n_children = n_keys;
1344 return (AST *) dict;
1347 ast_array_free (dict->keys, n_keys);
1348 ast_array_free (dict->values, n_values);
1349 g_slice_free (Dictionary, dict);
1361 string_get_pattern (AST *ast,
1364 return g_strdup ("MS");
1368 string_get_value (AST *ast,
1369 const GVariantType *type,
1372 String *string = (String *) ast;
1374 if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
1375 return g_variant_new_string (string->string);
1377 else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
1379 if (!g_variant_is_object_path (string->string))
1381 ast_set_error (ast, error, NULL, "not a valid object path");
1385 return g_variant_new_object_path (string->string);
1388 else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
1390 if (!g_variant_is_signature (string->string))
1392 ast_set_error (ast, error, NULL, "not a valid signature");
1396 return g_variant_new_signature (string->string);
1400 return ast_type_error (ast, type, error);
1404 string_free (AST *ast)
1406 String *string = (String *) ast;
1408 g_free (string->string);
1409 g_slice_free (String, string);
1413 string_parse (TokenStream *stream,
1417 static const ASTClass string_class = {
1419 maybe_wrapper, string_get_value,
1430 token_stream_start_ref (stream, &ref);
1431 token = token_stream_get (stream);
1432 token_stream_end_ref (stream, &ref);
1433 length = strlen (token);
1436 str = g_malloc (length);
1437 g_assert (quote == '"' || quote == '\'');
1440 while (token[i] != quote)
1444 parser_set_error (error, &ref, NULL,
1445 "unterminated string constant");
1453 parser_set_error (error, &ref, NULL,
1454 "unterminated string constant");
1458 case '0': case '1': case '2': case '3':
1459 case '4': case '5': case '6': case '7':
1461 /* up to 3 characters */
1462 guchar val = token[i++] - '0';
1464 if ('0' <= token[i] && token[i] < '8')
1465 val = (val << 3) | (token[i++] - '0');
1467 if ('0' <= token[i] && token[i] < '8')
1468 val = (val << 3) | (token[i++] - '0');
1474 case 'b': str[j++] = '\b'; i++; continue;
1475 case 'f': str[j++] = '\f'; i++; continue;
1476 case 'n': str[j++] = '\n'; i++; continue;
1477 case 'r': str[j++] = '\r'; i++; continue;
1478 case 't': str[j++] = '\t'; i++; continue;
1479 case '\n': i++; continue;
1483 str[j++] = token[i++];
1488 string = g_slice_new (String);
1489 string->ast.class = &string_class;
1490 string->string = str;
1492 token_stream_next (stream);
1494 return (AST *) string;
1505 number_get_pattern (AST *ast,
1508 Number *number = (Number *) ast;
1510 if (strchr (number->token, '.') ||
1511 (!g_str_has_prefix (number->token, "0x") &&
1512 strchr (number->token, 'e')))
1513 return g_strdup ("Md");
1515 return g_strdup ("MN");
1519 number_overflow (AST *ast,
1520 const GVariantType *type,
1523 ast_set_error (ast, error, NULL, "number out of range for type `%c'",
1524 g_variant_type_peek_string (type)[0]);
1529 number_get_value (AST *ast,
1530 const GVariantType *type,
1533 Number *number = (Number *) ast;
1541 token = number->token;
1543 if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
1548 dbl_val = g_ascii_strtod (token, &end);
1549 if (dbl_val != 0.0 && errno == ERANGE)
1551 ast_set_error (ast, error, NULL, "number too big for any type");
1555 /* silence uninitialised warnings... */
1562 negative = token[0] == '-';
1563 if (token[0] == '-')
1567 abs_val = g_ascii_strtoull (token, &end, 0);
1568 if (abs_val == G_MAXUINT64 && errno == ERANGE)
1570 ast_set_error (ast, error, NULL, "integer too big for any type");
1577 /* silence uninitialised warning... */
1585 ref = ast->source_ref;
1586 ref.start += end - number->token;
1587 ref.end = ref.start + 1;
1589 parser_set_error (error, &ref, NULL,
1590 "invalid character in number");
1595 return g_variant_new_double (dbl_val);
1597 switch (*g_variant_type_peek_string (type))
1600 if (negative || abs_val > G_MAXUINT8)
1601 return number_overflow (ast, type, error);
1602 return g_variant_new_byte (abs_val);
1605 if (abs_val - negative > G_MAXINT16)
1606 return number_overflow (ast, type, error);
1607 return g_variant_new_int16 (negative ? -abs_val : abs_val);
1610 if (negative || abs_val > G_MAXUINT16)
1611 return number_overflow (ast, type, error);
1612 return g_variant_new_uint16 (negative ? -abs_val : abs_val);
1615 if (abs_val - negative > G_MAXINT32)
1616 return number_overflow (ast, type, error);
1617 return g_variant_new_int32 (negative ? -abs_val : abs_val);
1620 if (negative || abs_val > G_MAXUINT32)
1621 return number_overflow (ast, type, error);
1622 return g_variant_new_uint32 (negative ? -abs_val : abs_val);
1625 if (abs_val - negative > G_MAXINT64)
1626 return number_overflow (ast, type, error);
1627 return g_variant_new_int64 (negative ? -abs_val : abs_val);
1631 return number_overflow (ast, type, error);
1632 return g_variant_new_uint64 (negative ? -abs_val : abs_val);
1635 if (abs_val - negative > G_MAXINT32)
1636 return number_overflow (ast, type, error);
1637 return g_variant_new_handle (negative ? -abs_val : abs_val);
1640 return ast_type_error (ast, type, error);
1645 number_free (AST *ast)
1647 Number *number = (Number *) ast;
1649 g_free (number->token);
1650 g_slice_free (Number, number);
1654 number_parse (TokenStream *stream,
1658 static const ASTClass number_class = {
1660 maybe_wrapper, number_get_value,
1665 number = g_slice_new (Number);
1666 number->ast.class = &number_class;
1667 number->token = token_stream_get (stream);
1668 token_stream_next (stream);
1670 return (AST *) number;
1680 boolean_get_pattern (AST *ast,
1683 return g_strdup ("Mb");
1687 boolean_get_value (AST *ast,
1688 const GVariantType *type,
1691 Boolean *boolean = (Boolean *) ast;
1693 if (!g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
1694 return ast_type_error (ast, type, error);
1696 return g_variant_new_boolean (boolean->value);
1700 boolean_free (AST *ast)
1702 Boolean *boolean = (Boolean *) ast;
1704 g_slice_free (Boolean, boolean);
1708 boolean_new (gboolean value)
1710 static const ASTClass boolean_class = {
1711 boolean_get_pattern,
1712 maybe_wrapper, boolean_get_value,
1717 boolean = g_slice_new (Boolean);
1718 boolean->ast.class = &boolean_class;
1719 boolean->value = value;
1721 return (AST *) boolean;
1732 positional_get_pattern (AST *ast,
1735 Positional *positional = (Positional *) ast;
1737 return g_strdup (g_variant_get_type_string (positional->value));
1741 positional_get_value (AST *ast,
1742 const GVariantType *type,
1745 Positional *positional = (Positional *) ast;
1748 g_assert (positional->value != NULL);
1750 if G_UNLIKELY (!g_variant_is_of_type (positional->value, type))
1751 return ast_type_error (ast, type, error);
1753 /* NOTE: if _get is called more than once then
1754 * things get messed up with respect to floating refs.
1756 * fortunately, this function should only ever get called once.
1758 g_assert (positional->value != NULL);
1759 value = positional->value;
1760 positional->value = NULL;
1766 positional_free (AST *ast)
1768 Positional *positional = (Positional *) ast;
1770 /* if positional->value is set, just leave it.
1771 * memory management doesn't matter in case of programmer error.
1773 g_slice_free (Positional, positional);
1777 positional_parse (TokenStream *stream,
1781 static const ASTClass positional_class = {
1782 positional_get_pattern,
1783 positional_get_value, NULL,
1786 Positional *positional;
1787 const gchar *endptr;
1790 token = token_stream_get (stream);
1791 g_assert (token[0] == '%');
1793 positional = g_slice_new (Positional);
1794 positional->ast.class = &positional_class;
1795 positional->value = g_variant_new_va (token + 1, &endptr, app);
1797 if (*endptr || positional->value == NULL)
1799 token_stream_set_error (stream, error, TRUE,
1800 "invalid GVariant format string");
1801 /* memory management doesn't matter in case of programmer error. */
1805 token_stream_next (stream);
1808 return (AST *) positional;
1820 typedecl_get_pattern (AST *ast,
1823 TypeDecl *decl = (TypeDecl *) ast;
1825 return g_variant_type_dup_string (decl->type);
1829 typedecl_get_value (AST *ast,
1830 const GVariantType *type,
1833 TypeDecl *decl = (TypeDecl *) ast;
1835 return ast_get_value (decl->child, type, error);
1839 typedecl_free (AST *ast)
1841 TypeDecl *decl = (TypeDecl *) ast;
1843 ast_free (decl->child);
1844 g_variant_type_free (decl->type);
1845 g_slice_free (TypeDecl, decl);
1849 typedecl_parse (TokenStream *stream,
1853 static const ASTClass typedecl_class = {
1854 typedecl_get_pattern,
1855 typedecl_get_value, NULL,
1862 if (token_stream_peek (stream, '@'))
1866 token = token_stream_get (stream);
1868 if (!g_variant_type_string_is_valid (token + 1))
1870 token_stream_set_error (stream, error, TRUE,
1871 "invalid type declaration");
1877 type = g_variant_type_new (token + 1);
1879 if (!g_variant_type_is_definite (type))
1881 token_stream_set_error (stream, error, TRUE,
1882 "type declarations must be definite");
1883 g_variant_type_free (type);
1889 token_stream_next (stream);
1894 if (token_stream_consume (stream, "boolean"))
1895 type = g_variant_type_copy (G_VARIANT_TYPE_BOOLEAN);
1897 else if (token_stream_consume (stream, "byte"))
1898 type = g_variant_type_copy (G_VARIANT_TYPE_BYTE);
1900 else if (token_stream_consume (stream, "int16"))
1901 type = g_variant_type_copy (G_VARIANT_TYPE_INT16);
1903 else if (token_stream_consume (stream, "uint16"))
1904 type = g_variant_type_copy (G_VARIANT_TYPE_UINT16);
1906 else if (token_stream_consume (stream, "int32"))
1907 type = g_variant_type_copy (G_VARIANT_TYPE_INT32);
1909 else if (token_stream_consume (stream, "handle"))
1910 type = g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
1912 else if (token_stream_consume (stream, "uint32"))
1913 type = g_variant_type_copy (G_VARIANT_TYPE_UINT32);
1915 else if (token_stream_consume (stream, "int64"))
1916 type = g_variant_type_copy (G_VARIANT_TYPE_INT64);
1918 else if (token_stream_consume (stream, "uint64"))
1919 type = g_variant_type_copy (G_VARIANT_TYPE_UINT64);
1921 else if (token_stream_consume (stream, "double"))
1922 type = g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
1924 else if (token_stream_consume (stream, "string"))
1925 type = g_variant_type_copy (G_VARIANT_TYPE_STRING);
1927 else if (token_stream_consume (stream, "objectpath"))
1928 type = g_variant_type_copy (G_VARIANT_TYPE_OBJECT_PATH);
1930 else if (token_stream_consume (stream, "signature"))
1931 type = g_variant_type_copy (G_VARIANT_TYPE_SIGNATURE);
1935 token_stream_set_error (stream, error, TRUE, "unknown keyword");
1940 if ((child = parse (stream, app, error)) == NULL)
1942 g_variant_type_free (type);
1946 decl = g_slice_new (TypeDecl);
1947 decl->ast.class = &typedecl_class;
1949 decl->child = child;
1951 return (AST *) decl;
1955 parse (TokenStream *stream,
1959 SourceRef source_ref;
1962 token_stream_prepare (stream);
1963 token_stream_start_ref (stream, &source_ref);
1965 if (token_stream_peek (stream, '['))
1966 result = array_parse (stream, app, error);
1968 else if (token_stream_peek (stream, '('))
1969 result = tuple_parse (stream, app, error);
1971 else if (token_stream_peek (stream, '<'))
1972 result = variant_parse (stream, app, error);
1974 else if (token_stream_peek (stream, '{'))
1975 result = dictionary_parse (stream, app, error);
1977 else if (app && token_stream_peek (stream, '%'))
1978 result = positional_parse (stream, app, error);
1980 else if (token_stream_consume (stream, "true"))
1981 result = boolean_new (TRUE);
1983 else if (token_stream_consume (stream, "false"))
1984 result = boolean_new (FALSE);
1986 else if (token_stream_peek (stream, 'n') ||
1987 token_stream_peek (stream, 'j'))
1988 result = maybe_parse (stream, app, error);
1990 else if (token_stream_peek (stream, '@') ||
1991 token_stream_is_keyword (stream))
1992 result = typedecl_parse (stream, app, error);
1994 else if (token_stream_is_numeric (stream))
1995 result = number_parse (stream, app, error);
1997 else if (token_stream_peek (stream, '\'') ||
1998 token_stream_peek (stream, '"'))
1999 result = string_parse (stream, app, error);
2003 token_stream_set_error (stream, error, FALSE, "expected value");
2009 token_stream_end_ref (stream, &source_ref);
2010 result->source_ref = source_ref;
2018 * @type: a #GVariantType, or %NULL
2019 * @text: a string containing a GVariant in text form
2020 * @limit: a pointer to the end of @text, or %NULL
2021 * @endptr: a location to store the end pointer, or %NULL
2022 * @error: a pointer to a %NULL #GError pointer, or %NULL
2023 * @Returns: a reference to a #GVariant, or %NULL
2025 * Parses a #GVariant from a text representation.
2027 * A single #GVariant is parsed from the content of @text.
2029 * The memory at @limit will never be accessed and the parser behaves as
2030 * if the character at @limit is the nul terminator. This has the
2031 * effect of bounding @text.
2033 * If @endptr is non-%NULL then @text is permitted to contain data
2034 * following the value that this function parses and @endptr will be
2035 * updated to point to the first character past the end of the text
2036 * parsed by this function. If @endptr is %NULL and there is extra data
2037 * then an error is returned.
2039 * If @type is non-%NULL then the value will be parsed to have that
2040 * type. This may result in additional parse errors (in the case that
2041 * the parsed value doesn't fit the type) but may also result in fewer
2042 * errors (in the case that the type would have been ambiguous, such as
2043 * with empty arrays).
2045 * In the event that the parsing is successful, the resulting #GVariant
2048 * In case of any error, %NULL will be returned. If @error is non-%NULL
2049 * then it will be set to reflect the error that occured.
2051 * Officially, the language understood by the parser is "any string
2052 * produced by g_variant_print()".
2055 g_variant_parse (const GVariantType *type,
2058 const gchar **endptr,
2061 TokenStream stream = { 0, };
2062 GVariant *result = NULL;
2065 g_return_val_if_fail (text != NULL, NULL);
2066 g_return_val_if_fail (text == limit || text != NULL, NULL);
2068 stream.start = text;
2069 stream.stream = text;
2072 if ((ast = parse (&stream, NULL, error)))
2075 result = ast_resolve (ast, error);
2077 result = ast_get_value (ast, type, error);
2081 g_variant_ref_sink (result);
2085 while (stream.stream != limit &&
2086 g_ascii_isspace (*stream.stream))
2089 if (stream.stream != limit && *stream.stream != '\0')
2091 SourceRef ref = { stream.stream - text,
2092 stream.stream - text };
2094 parser_set_error (error, &ref, NULL,
2095 "expected end of input");
2096 g_variant_unref (result);
2102 *endptr = stream.stream;
2112 * g_variant_new_parsed_va:
2113 * @format: a text format #GVariant
2114 * @app: a pointer to a #va_list
2115 * @returns: a new, usually floating, #GVariant
2117 * Parses @format and returns the result.
2119 * This is the version of g_variant_new_parsed() intended to be used
2122 * The return value will be floating if it was a newly created GVariant
2123 * instance. In the case that @format simply specified the collection
2124 * of a #GVariant pointer (eg: @format was "%*") then the collected
2125 * #GVariant pointer will be returned unmodified, without adding any
2126 * additional references.
2128 * In order to behave correctly in all cases it is necessary for the
2129 * calling function to g_variant_ref_sink() the return result before
2130 * returning control to the user that originally provided the pointer.
2131 * At this point, the caller will have their own full reference to the
2132 * result. This can also be done by adding the result to a container,
2133 * or by passing it to another g_variant_new() call.
2136 g_variant_new_parsed_va (const gchar *format,
2139 TokenStream stream = { 0, };
2140 GVariant *result = NULL;
2141 GError *error = NULL;
2144 g_return_val_if_fail (format != NULL, NULL);
2145 g_return_val_if_fail (app != NULL, NULL);
2147 stream.start = format;
2148 stream.stream = format;
2151 if ((ast = parse (&stream, app, &error)))
2153 result = ast_resolve (ast, &error);
2158 g_error ("g_variant_new_parsed: %s", error->message);
2161 g_error ("g_variant_new_parsed: trailing text after value");
2167 * g_variant_new_parsed:
2168 * @format: a text format #GVariant
2169 * @...: arguments as per @format
2170 * @returns: a new floating #GVariant instance
2172 * Parses @format and returns the result.
2174 * @format must be a text format #GVariant with one extention: at any
2175 * point that a value may appear in the text, a '%' character followed
2176 * by a GVariant format string (as per g_variant_new()) may appear. In
2177 * that case, the same arguments are collected from the argument list as
2178 * g_variant_new() would have collected.
2180 * Consider this simple example:
2182 * <informalexample><programlisting>
2183 * g_variant_new_parsed ("[('one', 1), ('two', %i), (%s, 3)]", 2, "three");
2184 * </programlisting></informalexample>
2186 * In the example, the variable argument parameters are collected and
2187 * filled in as if they were part of the original string to produce the
2188 * result of <code>[('one', 1), ('two', 2), ('three', 3)]</code>.
2190 * This function is intended only to be used with @format as a string
2191 * literal. Any parse error is fatal to the calling process. If you
2192 * want to parse data from untrusted sources, use g_variant_parse().
2194 * You may not use this function to return, unmodified, a single
2195 * #GVariant pointer from the argument list. ie: @format may not solely
2196 * be anything along the lines of "%*", "%?", "%r", or anything starting
2200 g_variant_new_parsed (const gchar *format,
2206 va_start (ap, format);
2207 result = g_variant_new_parsed_va (format, &ap);
2213 #define __G_VARIANT_PARSER_C__
2214 #include "galiasdef.c"