gmem: Only evaluate pointer argument to g_clear_pointer() once
[glib.git] / glib / gvariant-parser.c
blob233a19f7ca36b55414faffaa9bf14251ce418866
1 /*
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.1 of the License, 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, see <http://www.gnu.org/licenses/>.
17 * Author: Ryan Lortie <desrt@desrt.ca>
20 #include "config.h"
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
26 #include "gerror.h"
27 #include "gquark.h"
28 #include "gstring.h"
29 #include "gstrfuncs.h"
30 #include "gtestutils.h"
31 #include "gvariant.h"
32 #include "gvarianttype.h"
33 #include "gslice.h"
34 #include "gthread.h"
37 * two-pass algorithm
38 * designed by ryan lortie and william hua
39 * designed in itb-229 and at ghazi's, 2009.
42 /**
43 * G_VARIANT_PARSE_ERROR:
45 * Error domain for GVariant text format parsing. Specific error codes
46 * are not currently defined for this domain. See #GError for
47 * information on error domains.
48 **/
49 /**
50 * GVariantParseError:
51 * @G_VARIANT_PARSE_ERROR_FAILED: generic error (unused)
52 * @G_VARIANT_PARSE_ERROR_BASIC_TYPE_EXPECTED: a non-basic #GVariantType was given where a basic type was expected
53 * @G_VARIANT_PARSE_ERROR_CANNOT_INFER_TYPE: cannot infer the #GVariantType
54 * @G_VARIANT_PARSE_ERROR_DEFINITE_TYPE_EXPECTED: an indefinite #GVariantType was given where a definite type was expected
55 * @G_VARIANT_PARSE_ERROR_INPUT_NOT_AT_END: extra data after parsing finished
56 * @G_VARIANT_PARSE_ERROR_INVALID_CHARACTER: invalid character in number or unicode escape
57 * @G_VARIANT_PARSE_ERROR_INVALID_FORMAT_STRING: not a valid #GVariant format string
58 * @G_VARIANT_PARSE_ERROR_INVALID_OBJECT_PATH: not a valid object path
59 * @G_VARIANT_PARSE_ERROR_INVALID_SIGNATURE: not a valid type signature
60 * @G_VARIANT_PARSE_ERROR_INVALID_TYPE_STRING: not a valid #GVariant type string
61 * @G_VARIANT_PARSE_ERROR_NO_COMMON_TYPE: could not find a common type for array entries
62 * @G_VARIANT_PARSE_ERROR_NUMBER_OUT_OF_RANGE: the numerical value is out of range of the given type
63 * @G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG: the numerical value is out of range for any type
64 * @G_VARIANT_PARSE_ERROR_TYPE_ERROR: cannot parse as variant of the specified type
65 * @G_VARIANT_PARSE_ERROR_UNEXPECTED_TOKEN: an unexpected token was encountered
66 * @G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD: an unknown keyword was encountered
67 * @G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT: unterminated string constant
68 * @G_VARIANT_PARSE_ERROR_VALUE_EXPECTED: no value given
70 * Error codes returned by parsing text-format GVariants.
71 **/
72 G_DEFINE_QUARK (g-variant-parse-error-quark, g_variant_parse_error)
74 /**
75 * g_variant_parser_get_error_quark:
77 * Same as g_variant_error_quark().
79 * Deprecated: Use g_variant_parse_error_quark() instead.
81 GQuark
82 g_variant_parser_get_error_quark (void)
84 return g_variant_parse_error_quark ();
87 typedef struct
89 gint start, end;
90 } SourceRef;
92 G_GNUC_PRINTF(5, 0)
93 static void
94 parser_set_error_va (GError **error,
95 SourceRef *location,
96 SourceRef *other,
97 gint code,
98 const gchar *format,
99 va_list ap)
101 GString *msg = g_string_new (NULL);
103 if (location->start == location->end)
104 g_string_append_printf (msg, "%d", location->start);
105 else
106 g_string_append_printf (msg, "%d-%d", location->start, location->end);
108 if (other != NULL)
110 g_assert (other->start != other->end);
111 g_string_append_printf (msg, ",%d-%d", other->start, other->end);
113 g_string_append_c (msg, ':');
115 g_string_append_vprintf (msg, format, ap);
116 g_set_error_literal (error, G_VARIANT_PARSE_ERROR, code, msg->str);
117 g_string_free (msg, TRUE);
120 G_GNUC_PRINTF(5, 6)
121 static void
122 parser_set_error (GError **error,
123 SourceRef *location,
124 SourceRef *other,
125 gint code,
126 const gchar *format,
127 ...)
129 va_list ap;
131 va_start (ap, format);
132 parser_set_error_va (error, location, other, code, format, ap);
133 va_end (ap);
136 typedef struct
138 const gchar *start;
139 const gchar *stream;
140 const gchar *end;
142 const gchar *this;
143 } TokenStream;
146 G_GNUC_PRINTF(5, 6)
147 static void
148 token_stream_set_error (TokenStream *stream,
149 GError **error,
150 gboolean this_token,
151 gint code,
152 const gchar *format,
153 ...)
155 SourceRef ref;
156 va_list ap;
158 ref.start = stream->this - stream->start;
160 if (this_token)
161 ref.end = stream->stream - stream->start;
162 else
163 ref.end = ref.start;
165 va_start (ap, format);
166 parser_set_error_va (error, &ref, NULL, code, format, ap);
167 va_end (ap);
170 static gboolean
171 token_stream_prepare (TokenStream *stream)
173 gint brackets = 0;
174 const gchar *end;
176 if (stream->this != NULL)
177 return TRUE;
179 while (stream->stream != stream->end && g_ascii_isspace (*stream->stream))
180 stream->stream++;
182 if (stream->stream == stream->end || *stream->stream == '\0')
184 stream->this = stream->stream;
185 return FALSE;
188 switch (stream->stream[0])
190 case '-': case '+': case '.': case '0': case '1': case '2':
191 case '3': case '4': case '5': case '6': case '7': case '8':
192 case '9':
193 for (end = stream->stream; end != stream->end; end++)
194 if (!g_ascii_isalnum (*end) &&
195 *end != '-' && *end != '+' && *end != '.')
196 break;
197 break;
199 case 'b':
200 if (stream->stream[1] == '\'' || stream->stream[1] == '"')
202 for (end = stream->stream + 2; end != stream->end; end++)
203 if (*end == stream->stream[1] || *end == '\0' ||
204 (*end == '\\' && (++end == stream->end || *end == '\0')))
205 break;
207 if (end != stream->end && *end)
208 end++;
209 break;
212 else
214 /* ↓↓↓ */
217 case 'a': /* 'b' */ case 'c': case 'd': case 'e': case 'f':
218 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
219 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
220 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
221 case 'y': case 'z':
222 for (end = stream->stream; end != stream->end; end++)
223 if (!g_ascii_isalnum (*end))
224 break;
225 break;
227 case '\'': case '"':
228 for (end = stream->stream + 1; end != stream->end; end++)
229 if (*end == stream->stream[0] || *end == '\0' ||
230 (*end == '\\' && (++end == stream->end || *end == '\0')))
231 break;
233 if (end != stream->end && *end)
234 end++;
235 break;
237 case '@': case '%':
238 /* stop at the first space, comma, colon or unmatched bracket.
239 * deals nicely with cases like (%i, %i) or {%i: %i}.
240 * Also: ] and > are never in format strings.
242 for (end = stream->stream + 1;
243 end != stream->end && *end != '\0' && *end != ',' &&
244 *end != ':' && *end != '>' && *end != ']' && !g_ascii_isspace (*end);
245 end++)
247 if (*end == '(' || *end == '{')
248 brackets++;
250 else if ((*end == ')' || *end == '}') && !brackets--)
251 break;
253 break;
255 default:
256 end = stream->stream + 1;
257 break;
260 stream->this = stream->stream;
261 stream->stream = end;
263 /* We must have at least one byte in a token. */
264 g_assert (stream->stream - stream->this >= 1);
266 return TRUE;
269 static void
270 token_stream_next (TokenStream *stream)
272 stream->this = NULL;
275 static gboolean
276 token_stream_peek (TokenStream *stream,
277 gchar first_char)
279 if (!token_stream_prepare (stream))
280 return FALSE;
282 return stream->stream - stream->this >= 1 &&
283 stream->this[0] == first_char;
286 static gboolean
287 token_stream_peek2 (TokenStream *stream,
288 gchar first_char,
289 gchar second_char)
291 if (!token_stream_prepare (stream))
292 return FALSE;
294 return stream->stream - stream->this >= 2 &&
295 stream->this[0] == first_char &&
296 stream->this[1] == second_char;
299 static gboolean
300 token_stream_is_keyword (TokenStream *stream)
302 if (!token_stream_prepare (stream))
303 return FALSE;
305 return stream->stream - stream->this >= 2 &&
306 g_ascii_isalpha (stream->this[0]) &&
307 g_ascii_isalpha (stream->this[1]);
310 static gboolean
311 token_stream_is_numeric (TokenStream *stream)
313 if (!token_stream_prepare (stream))
314 return FALSE;
316 return (stream->stream - stream->this >= 1 &&
317 (g_ascii_isdigit (stream->this[0]) ||
318 stream->this[0] == '-' ||
319 stream->this[0] == '+' ||
320 stream->this[0] == '.'));
323 static gboolean
324 token_stream_peek_string (TokenStream *stream,
325 const gchar *token)
327 gint length = strlen (token);
329 return token_stream_prepare (stream) &&
330 stream->stream - stream->this == length &&
331 memcmp (stream->this, token, length) == 0;
334 static gboolean
335 token_stream_consume (TokenStream *stream,
336 const gchar *token)
338 if (!token_stream_peek_string (stream, token))
339 return FALSE;
341 token_stream_next (stream);
342 return TRUE;
345 static gboolean
346 token_stream_require (TokenStream *stream,
347 const gchar *token,
348 const gchar *purpose,
349 GError **error)
352 if (!token_stream_consume (stream, token))
354 token_stream_set_error (stream, error, FALSE,
355 G_VARIANT_PARSE_ERROR_UNEXPECTED_TOKEN,
356 "expected '%s'%s", token, purpose);
357 return FALSE;
360 return TRUE;
363 static void
364 token_stream_assert (TokenStream *stream,
365 const gchar *token)
367 gboolean correct_token;
369 correct_token = token_stream_consume (stream, token);
370 g_assert (correct_token);
373 static gchar *
374 token_stream_get (TokenStream *stream)
376 gchar *result;
378 if (!token_stream_prepare (stream))
379 return NULL;
381 result = g_strndup (stream->this, stream->stream - stream->this);
383 return result;
386 static void
387 token_stream_start_ref (TokenStream *stream,
388 SourceRef *ref)
390 token_stream_prepare (stream);
391 ref->start = stream->this - stream->start;
394 static void
395 token_stream_end_ref (TokenStream *stream,
396 SourceRef *ref)
398 ref->end = stream->stream - stream->start;
401 static void
402 pattern_copy (gchar **out,
403 const gchar **in)
405 gint brackets = 0;
407 while (**in == 'a' || **in == 'm' || **in == 'M')
408 *(*out)++ = *(*in)++;
412 if (**in == '(' || **in == '{')
413 brackets++;
415 else if (**in == ')' || **in == '}')
416 brackets--;
418 *(*out)++ = *(*in)++;
420 while (brackets);
423 static gchar *
424 pattern_coalesce (const gchar *left,
425 const gchar *right)
427 gchar *result;
428 gchar *out;
430 /* the length of the output is loosely bound by the sum of the input
431 * lengths, not simply the greater of the two lengths.
433 * (*(iii)) + ((iii)*) ((iii)(iii))
435 * 8 + 8 = 12
437 out = result = g_malloc (strlen (left) + strlen (right));
439 while (*left && *right)
441 if (*left == *right)
443 *out++ = *left++;
444 right++;
447 else
449 const gchar **one = &left, **the_other = &right;
451 again:
452 if (**one == '*' && **the_other != ')')
454 pattern_copy (&out, the_other);
455 (*one)++;
458 else if (**one == 'M' && **the_other == 'm')
460 *out++ = *(*the_other)++;
463 else if (**one == 'M' && **the_other != 'm')
465 (*one)++;
468 else if (**one == 'N' && strchr ("ynqiuxthd", **the_other))
470 *out++ = *(*the_other)++;
471 (*one)++;
474 else if (**one == 'S' && strchr ("sog", **the_other))
476 *out++ = *(*the_other)++;
477 (*one)++;
480 else if (one == &left)
482 one = &right, the_other = &left;
483 goto again;
486 else
487 break;
491 if (*left || *right)
493 g_free (result);
494 result = NULL;
496 else
497 *out++ = '\0';
499 return result;
502 typedef struct _AST AST;
503 typedef gchar * (*get_pattern_func) (AST *ast,
504 GError **error);
505 typedef GVariant * (*get_value_func) (AST *ast,
506 const GVariantType *type,
507 GError **error);
508 typedef GVariant * (*get_base_value_func) (AST *ast,
509 const GVariantType *type,
510 GError **error);
511 typedef void (*free_func) (AST *ast);
513 typedef struct
515 gchar * (* get_pattern) (AST *ast,
516 GError **error);
517 GVariant * (* get_value) (AST *ast,
518 const GVariantType *type,
519 GError **error);
520 GVariant * (* get_base_value) (AST *ast,
521 const GVariantType *type,
522 GError **error);
523 void (* free) (AST *ast);
524 } ASTClass;
526 struct _AST
528 const ASTClass *class;
529 SourceRef source_ref;
532 static gchar *
533 ast_get_pattern (AST *ast,
534 GError **error)
536 return ast->class->get_pattern (ast, error);
539 static GVariant *
540 ast_get_value (AST *ast,
541 const GVariantType *type,
542 GError **error)
544 return ast->class->get_value (ast, type, error);
547 static void
548 ast_free (AST *ast)
550 ast->class->free (ast);
553 G_GNUC_PRINTF(5, 6)
554 static void
555 ast_set_error (AST *ast,
556 GError **error,
557 AST *other_ast,
558 gint code,
559 const gchar *format,
560 ...)
562 va_list ap;
564 va_start (ap, format);
565 parser_set_error_va (error, &ast->source_ref,
566 other_ast ? & other_ast->source_ref : NULL,
567 code,
568 format, ap);
569 va_end (ap);
572 static GVariant *
573 ast_type_error (AST *ast,
574 const GVariantType *type,
575 GError **error)
577 gchar *typestr;
579 typestr = g_variant_type_dup_string (type);
580 ast_set_error (ast, error, NULL,
581 G_VARIANT_PARSE_ERROR_TYPE_ERROR,
582 "can not parse as value of type '%s'",
583 typestr);
584 g_free (typestr);
586 return NULL;
589 static GVariant *
590 ast_resolve (AST *ast,
591 GError **error)
593 GVariant *value;
594 gchar *pattern;
595 gint i, j = 0;
597 pattern = ast_get_pattern (ast, error);
599 if (pattern == NULL)
600 return NULL;
602 /* choose reasonable defaults
604 * 1) favour non-maybe values where possible
605 * 2) default type for strings is 's'
606 * 3) default type for integers is 'i'
608 for (i = 0; pattern[i]; i++)
609 switch (pattern[i])
611 case '*':
612 ast_set_error (ast, error, NULL,
613 G_VARIANT_PARSE_ERROR_CANNOT_INFER_TYPE,
614 "unable to infer type");
615 g_free (pattern);
616 return NULL;
618 case 'M':
619 break;
621 case 'S':
622 pattern[j++] = 's';
623 break;
625 case 'N':
626 pattern[j++] = 'i';
627 break;
629 default:
630 pattern[j++] = pattern[i];
631 break;
633 pattern[j++] = '\0';
635 value = ast_get_value (ast, G_VARIANT_TYPE (pattern), error);
636 g_free (pattern);
638 return value;
642 static AST *parse (TokenStream *stream,
643 va_list *app,
644 GError **error);
646 static void
647 ast_array_append (AST ***array,
648 gint *n_items,
649 AST *ast)
651 if ((*n_items & (*n_items - 1)) == 0)
652 *array = g_renew (AST *, *array, *n_items ? 2 ** n_items : 1);
654 (*array)[(*n_items)++] = ast;
657 static void
658 ast_array_free (AST **array,
659 gint n_items)
661 gint i;
663 for (i = 0; i < n_items; i++)
664 ast_free (array[i]);
665 g_free (array);
668 static gchar *
669 ast_array_get_pattern (AST **array,
670 gint n_items,
671 GError **error)
673 gchar *pattern;
674 gint i;
676 pattern = ast_get_pattern (array[0], error);
678 if (pattern == NULL)
679 return NULL;
681 for (i = 1; i < n_items; i++)
683 gchar *tmp, *merged;
685 tmp = ast_get_pattern (array[i], error);
687 if (tmp == NULL)
689 g_free (pattern);
690 return NULL;
693 merged = pattern_coalesce (pattern, tmp);
694 g_free (pattern);
695 pattern = merged;
697 if (merged == NULL)
698 /* set coalescence implies pairwise coalescence (i think).
699 * we should therefore be able to trace the failure to a single
700 * pair of values.
703 int j = 0;
705 while (TRUE)
707 gchar *tmp2;
708 gchar *m;
710 /* if 'j' reaches 'i' then we failed to find the pair */
711 g_assert (j < i);
713 tmp2 = ast_get_pattern (array[j], NULL);
714 g_assert (tmp2 != NULL);
716 m = pattern_coalesce (tmp, tmp2);
717 g_free (tmp2);
718 g_free (m);
720 if (m == NULL)
722 /* we found a conflict between 'i' and 'j'.
724 * report the error. note: 'j' is first.
726 ast_set_error (array[j], error, array[i],
727 G_VARIANT_PARSE_ERROR_NO_COMMON_TYPE,
728 "unable to find a common type");
729 g_free (tmp);
730 return NULL;
733 j++;
738 g_free (tmp);
741 return pattern;
744 typedef struct
746 AST ast;
748 AST *child;
749 } Maybe;
751 static gchar *
752 maybe_get_pattern (AST *ast,
753 GError **error)
755 Maybe *maybe = (Maybe *) ast;
757 if (maybe->child != NULL)
759 gchar *child_pattern;
760 gchar *pattern;
762 child_pattern = ast_get_pattern (maybe->child, error);
764 if (child_pattern == NULL)
765 return NULL;
767 pattern = g_strdup_printf ("m%s", child_pattern);
768 g_free (child_pattern);
770 return pattern;
773 return g_strdup ("m*");
776 static GVariant *
777 maybe_get_value (AST *ast,
778 const GVariantType *type,
779 GError **error)
781 Maybe *maybe = (Maybe *) ast;
782 GVariant *value;
784 if (!g_variant_type_is_maybe (type))
785 return ast_type_error (ast, type, error);
787 type = g_variant_type_element (type);
789 if (maybe->child)
791 value = ast_get_value (maybe->child, type, error);
793 if (value == NULL)
794 return NULL;
796 else
797 value = NULL;
799 return g_variant_new_maybe (type, value);
802 static void
803 maybe_free (AST *ast)
805 Maybe *maybe = (Maybe *) ast;
807 if (maybe->child != NULL)
808 ast_free (maybe->child);
810 g_slice_free (Maybe, maybe);
813 static AST *
814 maybe_parse (TokenStream *stream,
815 va_list *app,
816 GError **error)
818 static const ASTClass maybe_class = {
819 maybe_get_pattern,
820 maybe_get_value, NULL,
821 maybe_free
823 AST *child = NULL;
824 Maybe *maybe;
826 if (token_stream_consume (stream, "just"))
828 child = parse (stream, app, error);
829 if (child == NULL)
830 return NULL;
833 else if (!token_stream_consume (stream, "nothing"))
835 token_stream_set_error (stream, error, TRUE,
836 G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD,
837 "unknown keyword");
838 return NULL;
841 maybe = g_slice_new (Maybe);
842 maybe->ast.class = &maybe_class;
843 maybe->child = child;
845 return (AST *) maybe;
848 static GVariant *
849 maybe_wrapper (AST *ast,
850 const GVariantType *type,
851 GError **error)
853 const GVariantType *t;
854 GVariant *value;
855 int depth;
857 for (depth = 0, t = type;
858 g_variant_type_is_maybe (t);
859 depth++, t = g_variant_type_element (t));
861 value = ast->class->get_base_value (ast, t, error);
863 if (value == NULL)
864 return NULL;
866 while (depth--)
867 value = g_variant_new_maybe (NULL, value);
869 return value;
872 typedef struct
874 AST ast;
876 AST **children;
877 gint n_children;
878 } Array;
880 static gchar *
881 array_get_pattern (AST *ast,
882 GError **error)
884 Array *array = (Array *) ast;
885 gchar *pattern;
886 gchar *result;
888 if (array->n_children == 0)
889 return g_strdup ("Ma*");
891 pattern = ast_array_get_pattern (array->children, array->n_children, error);
893 if (pattern == NULL)
894 return NULL;
896 result = g_strdup_printf ("Ma%s", pattern);
897 g_free (pattern);
899 return result;
902 static GVariant *
903 array_get_value (AST *ast,
904 const GVariantType *type,
905 GError **error)
907 Array *array = (Array *) ast;
908 const GVariantType *childtype;
909 GVariantBuilder builder;
910 gint i;
912 if (!g_variant_type_is_array (type))
913 return ast_type_error (ast, type, error);
915 g_variant_builder_init (&builder, type);
916 childtype = g_variant_type_element (type);
918 for (i = 0; i < array->n_children; i++)
920 GVariant *child;
922 if (!(child = ast_get_value (array->children[i], childtype, error)))
924 g_variant_builder_clear (&builder);
925 return NULL;
928 g_variant_builder_add_value (&builder, child);
931 return g_variant_builder_end (&builder);
934 static void
935 array_free (AST *ast)
937 Array *array = (Array *) ast;
939 ast_array_free (array->children, array->n_children);
940 g_slice_free (Array, array);
943 static AST *
944 array_parse (TokenStream *stream,
945 va_list *app,
946 GError **error)
948 static const ASTClass array_class = {
949 array_get_pattern,
950 maybe_wrapper, array_get_value,
951 array_free
953 gboolean need_comma = FALSE;
954 Array *array;
956 array = g_slice_new (Array);
957 array->ast.class = &array_class;
958 array->children = NULL;
959 array->n_children = 0;
961 token_stream_assert (stream, "[");
962 while (!token_stream_consume (stream, "]"))
964 AST *child;
966 if (need_comma &&
967 !token_stream_require (stream, ",",
968 " or ']' to follow array element",
969 error))
970 goto error;
972 child = parse (stream, app, error);
974 if (!child)
975 goto error;
977 ast_array_append (&array->children, &array->n_children, child);
978 need_comma = TRUE;
981 return (AST *) array;
983 error:
984 ast_array_free (array->children, array->n_children);
985 g_slice_free (Array, array);
987 return NULL;
990 typedef struct
992 AST ast;
994 AST **children;
995 gint n_children;
996 } Tuple;
998 static gchar *
999 tuple_get_pattern (AST *ast,
1000 GError **error)
1002 Tuple *tuple = (Tuple *) ast;
1003 gchar *result = NULL;
1004 gchar **parts;
1005 gint i;
1007 parts = g_new (gchar *, tuple->n_children + 4);
1008 parts[tuple->n_children + 1] = (gchar *) ")";
1009 parts[tuple->n_children + 2] = NULL;
1010 parts[0] = (gchar *) "M(";
1012 for (i = 0; i < tuple->n_children; i++)
1013 if (!(parts[i + 1] = ast_get_pattern (tuple->children[i], error)))
1014 break;
1016 if (i == tuple->n_children)
1017 result = g_strjoinv ("", parts);
1019 /* parts[0] should not be freed */
1020 while (i)
1021 g_free (parts[i--]);
1022 g_free (parts);
1024 return result;
1027 static GVariant *
1028 tuple_get_value (AST *ast,
1029 const GVariantType *type,
1030 GError **error)
1032 Tuple *tuple = (Tuple *) ast;
1033 const GVariantType *childtype;
1034 GVariantBuilder builder;
1035 gint i;
1037 if (!g_variant_type_is_tuple (type))
1038 return ast_type_error (ast, type, error);
1040 g_variant_builder_init (&builder, type);
1041 childtype = g_variant_type_first (type);
1043 for (i = 0; i < tuple->n_children; i++)
1045 GVariant *child;
1047 if (childtype == NULL)
1049 g_variant_builder_clear (&builder);
1050 return ast_type_error (ast, type, error);
1053 if (!(child = ast_get_value (tuple->children[i], childtype, error)))
1055 g_variant_builder_clear (&builder);
1056 return FALSE;
1059 g_variant_builder_add_value (&builder, child);
1060 childtype = g_variant_type_next (childtype);
1063 if (childtype != NULL)
1065 g_variant_builder_clear (&builder);
1066 return ast_type_error (ast, type, error);
1069 return g_variant_builder_end (&builder);
1072 static void
1073 tuple_free (AST *ast)
1075 Tuple *tuple = (Tuple *) ast;
1077 ast_array_free (tuple->children, tuple->n_children);
1078 g_slice_free (Tuple, tuple);
1081 static AST *
1082 tuple_parse (TokenStream *stream,
1083 va_list *app,
1084 GError **error)
1086 static const ASTClass tuple_class = {
1087 tuple_get_pattern,
1088 maybe_wrapper, tuple_get_value,
1089 tuple_free
1091 gboolean need_comma = FALSE;
1092 gboolean first = TRUE;
1093 Tuple *tuple;
1095 tuple = g_slice_new (Tuple);
1096 tuple->ast.class = &tuple_class;
1097 tuple->children = NULL;
1098 tuple->n_children = 0;
1100 token_stream_assert (stream, "(");
1101 while (!token_stream_consume (stream, ")"))
1103 AST *child;
1105 if (need_comma &&
1106 !token_stream_require (stream, ",",
1107 " or ')' to follow tuple element",
1108 error))
1109 goto error;
1111 child = parse (stream, app, error);
1113 if (!child)
1114 goto error;
1116 ast_array_append (&tuple->children, &tuple->n_children, child);
1118 /* the first time, we absolutely require a comma, so grab it here
1119 * and leave need_comma = FALSE so that the code above doesn't
1120 * require a second comma.
1122 * the second and remaining times, we set need_comma = TRUE.
1124 if (first)
1126 if (!token_stream_require (stream, ",",
1127 " after first tuple element", error))
1128 goto error;
1130 first = FALSE;
1132 else
1133 need_comma = TRUE;
1136 return (AST *) tuple;
1138 error:
1139 ast_array_free (tuple->children, tuple->n_children);
1140 g_slice_free (Tuple, tuple);
1142 return NULL;
1145 typedef struct
1147 AST ast;
1149 AST *value;
1150 } Variant;
1152 static gchar *
1153 variant_get_pattern (AST *ast,
1154 GError **error)
1156 return g_strdup ("Mv");
1159 static GVariant *
1160 variant_get_value (AST *ast,
1161 const GVariantType *type,
1162 GError **error)
1164 Variant *variant = (Variant *) ast;
1165 GVariant *child;
1167 if (!g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
1168 return ast_type_error (ast, type, error);
1170 child = ast_resolve (variant->value, error);
1172 if (child == NULL)
1173 return NULL;
1175 return g_variant_new_variant (child);
1178 static void
1179 variant_free (AST *ast)
1181 Variant *variant = (Variant *) ast;
1183 ast_free (variant->value);
1184 g_slice_free (Variant, variant);
1187 static AST *
1188 variant_parse (TokenStream *stream,
1189 va_list *app,
1190 GError **error)
1192 static const ASTClass variant_class = {
1193 variant_get_pattern,
1194 maybe_wrapper, variant_get_value,
1195 variant_free
1197 Variant *variant;
1198 AST *value;
1200 token_stream_assert (stream, "<");
1201 value = parse (stream, app, error);
1203 if (!value)
1204 return NULL;
1206 if (!token_stream_require (stream, ">", " to follow variant value", error))
1208 ast_free (value);
1209 return NULL;
1212 variant = g_slice_new (Variant);
1213 variant->ast.class = &variant_class;
1214 variant->value = value;
1216 return (AST *) variant;
1219 typedef struct
1221 AST ast;
1223 AST **keys;
1224 AST **values;
1225 gint n_children;
1226 } Dictionary;
1228 static gchar *
1229 dictionary_get_pattern (AST *ast,
1230 GError **error)
1232 Dictionary *dict = (Dictionary *) ast;
1233 gchar *value_pattern;
1234 gchar *key_pattern;
1235 gchar key_char;
1236 gchar *result;
1238 if (dict->n_children == 0)
1239 return g_strdup ("Ma{**}");
1241 key_pattern = ast_array_get_pattern (dict->keys,
1242 abs (dict->n_children),
1243 error);
1245 if (key_pattern == NULL)
1246 return NULL;
1248 /* we can not have maybe keys */
1249 if (key_pattern[0] == 'M')
1250 key_char = key_pattern[1];
1251 else
1252 key_char = key_pattern[0];
1254 g_free (key_pattern);
1256 /* the basic types,
1257 * plus undetermined number type and undetermined string type.
1259 if (!strchr ("bynqiuxthdsogNS", key_char))
1261 ast_set_error (ast, error, NULL,
1262 G_VARIANT_PARSE_ERROR_BASIC_TYPE_EXPECTED,
1263 "dictionary keys must have basic types");
1264 return NULL;
1267 value_pattern = ast_get_pattern (dict->values[0], error);
1269 if (value_pattern == NULL)
1270 return NULL;
1272 result = g_strdup_printf ("M%s{%c%s}",
1273 dict->n_children > 0 ? "a" : "",
1274 key_char, value_pattern);
1275 g_free (value_pattern);
1277 return result;
1280 static GVariant *
1281 dictionary_get_value (AST *ast,
1282 const GVariantType *type,
1283 GError **error)
1285 Dictionary *dict = (Dictionary *) ast;
1287 if (dict->n_children == -1)
1289 const GVariantType *subtype;
1290 GVariantBuilder builder;
1291 GVariant *subvalue;
1293 if (!g_variant_type_is_dict_entry (type))
1294 return ast_type_error (ast, type, error);
1296 g_variant_builder_init (&builder, type);
1298 subtype = g_variant_type_key (type);
1299 if (!(subvalue = ast_get_value (dict->keys[0], subtype, error)))
1301 g_variant_builder_clear (&builder);
1302 return NULL;
1304 g_variant_builder_add_value (&builder, subvalue);
1306 subtype = g_variant_type_value (type);
1307 if (!(subvalue = ast_get_value (dict->values[0], subtype, error)))
1309 g_variant_builder_clear (&builder);
1310 return NULL;
1312 g_variant_builder_add_value (&builder, subvalue);
1314 return g_variant_builder_end (&builder);
1316 else
1318 const GVariantType *entry, *key, *val;
1319 GVariantBuilder builder;
1320 gint i;
1322 if (!g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_DICTIONARY))
1323 return ast_type_error (ast, type, error);
1325 entry = g_variant_type_element (type);
1326 key = g_variant_type_key (entry);
1327 val = g_variant_type_value (entry);
1329 g_variant_builder_init (&builder, type);
1331 for (i = 0; i < dict->n_children; i++)
1333 GVariant *subvalue;
1335 g_variant_builder_open (&builder, entry);
1337 if (!(subvalue = ast_get_value (dict->keys[i], key, error)))
1339 g_variant_builder_clear (&builder);
1340 return NULL;
1342 g_variant_builder_add_value (&builder, subvalue);
1344 if (!(subvalue = ast_get_value (dict->values[i], val, error)))
1346 g_variant_builder_clear (&builder);
1347 return NULL;
1349 g_variant_builder_add_value (&builder, subvalue);
1350 g_variant_builder_close (&builder);
1353 return g_variant_builder_end (&builder);
1357 static void
1358 dictionary_free (AST *ast)
1360 Dictionary *dict = (Dictionary *) ast;
1361 gint n_children;
1363 if (dict->n_children > -1)
1364 n_children = dict->n_children;
1365 else
1366 n_children = 1;
1368 ast_array_free (dict->keys, n_children);
1369 ast_array_free (dict->values, n_children);
1370 g_slice_free (Dictionary, dict);
1373 static AST *
1374 dictionary_parse (TokenStream *stream,
1375 va_list *app,
1376 GError **error)
1378 static const ASTClass dictionary_class = {
1379 dictionary_get_pattern,
1380 maybe_wrapper, dictionary_get_value,
1381 dictionary_free
1383 gint n_keys, n_values;
1384 gboolean only_one;
1385 Dictionary *dict;
1386 AST *first;
1388 dict = g_slice_new (Dictionary);
1389 dict->ast.class = &dictionary_class;
1390 dict->keys = NULL;
1391 dict->values = NULL;
1392 n_keys = n_values = 0;
1394 token_stream_assert (stream, "{");
1396 if (token_stream_consume (stream, "}"))
1398 dict->n_children = 0;
1399 return (AST *) dict;
1402 if ((first = parse (stream, app, error)) == NULL)
1403 goto error;
1405 ast_array_append (&dict->keys, &n_keys, first);
1407 only_one = token_stream_consume (stream, ",");
1408 if (!only_one &&
1409 !token_stream_require (stream, ":",
1410 " or ',' to follow dictionary entry key",
1411 error))
1412 goto error;
1414 if ((first = parse (stream, app, error)) == NULL)
1415 goto error;
1417 ast_array_append (&dict->values, &n_values, first);
1419 if (only_one)
1421 if (!token_stream_require (stream, "}", " at end of dictionary entry",
1422 error))
1423 goto error;
1425 g_assert (n_keys == 1 && n_values == 1);
1426 dict->n_children = -1;
1428 return (AST *) dict;
1431 while (!token_stream_consume (stream, "}"))
1433 AST *child;
1435 if (!token_stream_require (stream, ",",
1436 " or '}' to follow dictionary entry", error))
1437 goto error;
1439 child = parse (stream, app, error);
1441 if (!child)
1442 goto error;
1444 ast_array_append (&dict->keys, &n_keys, child);
1446 if (!token_stream_require (stream, ":",
1447 " to follow dictionary entry key", error))
1448 goto error;
1450 child = parse (stream, app, error);
1452 if (!child)
1453 goto error;
1455 ast_array_append (&dict->values, &n_values, child);
1458 g_assert (n_keys == n_values);
1459 dict->n_children = n_keys;
1461 return (AST *) dict;
1463 error:
1464 ast_array_free (dict->keys, n_keys);
1465 ast_array_free (dict->values, n_values);
1466 g_slice_free (Dictionary, dict);
1468 return NULL;
1471 typedef struct
1473 AST ast;
1474 gchar *string;
1475 } String;
1477 static gchar *
1478 string_get_pattern (AST *ast,
1479 GError **error)
1481 return g_strdup ("MS");
1484 static GVariant *
1485 string_get_value (AST *ast,
1486 const GVariantType *type,
1487 GError **error)
1489 String *string = (String *) ast;
1491 if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
1492 return g_variant_new_string (string->string);
1494 else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
1496 if (!g_variant_is_object_path (string->string))
1498 ast_set_error (ast, error, NULL,
1499 G_VARIANT_PARSE_ERROR_INVALID_OBJECT_PATH,
1500 "not a valid object path");
1501 return NULL;
1504 return g_variant_new_object_path (string->string);
1507 else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
1509 if (!g_variant_is_signature (string->string))
1511 ast_set_error (ast, error, NULL,
1512 G_VARIANT_PARSE_ERROR_INVALID_SIGNATURE,
1513 "not a valid signature");
1514 return NULL;
1517 return g_variant_new_signature (string->string);
1520 else
1521 return ast_type_error (ast, type, error);
1524 static void
1525 string_free (AST *ast)
1527 String *string = (String *) ast;
1529 g_free (string->string);
1530 g_slice_free (String, string);
1533 static gboolean
1534 unicode_unescape (const gchar *src,
1535 gint *src_ofs,
1536 gchar *dest,
1537 gint *dest_ofs,
1538 gint length,
1539 SourceRef *ref,
1540 GError **error)
1542 gchar buffer[9];
1543 guint64 value;
1544 gchar *end;
1546 (*src_ofs)++;
1548 g_assert (length < sizeof (buffer));
1549 strncpy (buffer, src + *src_ofs, length);
1550 buffer[length] = '\0';
1552 value = g_ascii_strtoull (buffer, &end, 0x10);
1554 if (value == 0 || end != buffer + length)
1556 parser_set_error (error, ref, NULL,
1557 G_VARIANT_PARSE_ERROR_INVALID_CHARACTER,
1558 "invalid %d-character unicode escape", length);
1559 return FALSE;
1562 g_assert (value <= G_MAXUINT32);
1564 *dest_ofs += g_unichar_to_utf8 (value, dest + *dest_ofs);
1565 *src_ofs += length;
1567 return TRUE;
1570 static AST *
1571 string_parse (TokenStream *stream,
1572 va_list *app,
1573 GError **error)
1575 static const ASTClass string_class = {
1576 string_get_pattern,
1577 maybe_wrapper, string_get_value,
1578 string_free
1580 String *string;
1581 SourceRef ref;
1582 gchar *token;
1583 gsize length;
1584 gchar quote;
1585 gchar *str;
1586 gint i, j;
1588 token_stream_start_ref (stream, &ref);
1589 token = token_stream_get (stream);
1590 token_stream_end_ref (stream, &ref);
1591 length = strlen (token);
1592 quote = token[0];
1594 str = g_malloc (length);
1595 g_assert (quote == '"' || quote == '\'');
1596 j = 0;
1597 i = 1;
1598 while (token[i] != quote)
1599 switch (token[i])
1601 case '\0':
1602 parser_set_error (error, &ref, NULL,
1603 G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1604 "unterminated string constant");
1605 g_free (token);
1606 g_free (str);
1607 return NULL;
1609 case '\\':
1610 switch (token[++i])
1612 case '\0':
1613 parser_set_error (error, &ref, NULL,
1614 G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1615 "unterminated string constant");
1616 g_free (token);
1617 g_free (str);
1618 return NULL;
1620 case 'u':
1621 if (!unicode_unescape (token, &i, str, &j, 4, &ref, error))
1623 g_free (token);
1624 g_free (str);
1625 return NULL;
1627 continue;
1629 case 'U':
1630 if (!unicode_unescape (token, &i, str, &j, 8, &ref, error))
1632 g_free (token);
1633 g_free (str);
1634 return NULL;
1636 continue;
1638 case 'a': str[j++] = '\a'; i++; continue;
1639 case 'b': str[j++] = '\b'; i++; continue;
1640 case 'f': str[j++] = '\f'; i++; continue;
1641 case 'n': str[j++] = '\n'; i++; continue;
1642 case 'r': str[j++] = '\r'; i++; continue;
1643 case 't': str[j++] = '\t'; i++; continue;
1644 case 'v': str[j++] = '\v'; i++; continue;
1645 case '\n': i++; continue;
1648 default:
1649 str[j++] = token[i++];
1651 str[j++] = '\0';
1652 g_free (token);
1654 string = g_slice_new (String);
1655 string->ast.class = &string_class;
1656 string->string = str;
1658 token_stream_next (stream);
1660 return (AST *) string;
1663 typedef struct
1665 AST ast;
1666 gchar *string;
1667 } ByteString;
1669 static gchar *
1670 bytestring_get_pattern (AST *ast,
1671 GError **error)
1673 return g_strdup ("May");
1676 static GVariant *
1677 bytestring_get_value (AST *ast,
1678 const GVariantType *type,
1679 GError **error)
1681 ByteString *string = (ByteString *) ast;
1683 if (!g_variant_type_equal (type, G_VARIANT_TYPE_BYTESTRING))
1684 return ast_type_error (ast, type, error);
1686 return g_variant_new_bytestring (string->string);
1689 static void
1690 bytestring_free (AST *ast)
1692 ByteString *string = (ByteString *) ast;
1694 g_free (string->string);
1695 g_slice_free (ByteString, string);
1698 static AST *
1699 bytestring_parse (TokenStream *stream,
1700 va_list *app,
1701 GError **error)
1703 static const ASTClass bytestring_class = {
1704 bytestring_get_pattern,
1705 maybe_wrapper, bytestring_get_value,
1706 bytestring_free
1708 ByteString *string;
1709 SourceRef ref;
1710 gchar *token;
1711 gsize length;
1712 gchar quote;
1713 gchar *str;
1714 gint i, j;
1716 token_stream_start_ref (stream, &ref);
1717 token = token_stream_get (stream);
1718 token_stream_end_ref (stream, &ref);
1719 g_assert (token[0] == 'b');
1720 length = strlen (token);
1721 quote = token[1];
1723 str = g_malloc (length);
1724 g_assert (quote == '"' || quote == '\'');
1725 j = 0;
1726 i = 2;
1727 while (token[i] != quote)
1728 switch (token[i])
1730 case '\0':
1731 parser_set_error (error, &ref, NULL,
1732 G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1733 "unterminated string constant");
1734 g_free (str);
1735 g_free (token);
1736 return NULL;
1738 case '\\':
1739 switch (token[++i])
1741 case '\0':
1742 parser_set_error (error, &ref, NULL,
1743 G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1744 "unterminated string constant");
1745 g_free (str);
1746 g_free (token);
1747 return NULL;
1749 case '0': case '1': case '2': case '3':
1750 case '4': case '5': case '6': case '7':
1752 /* up to 3 characters */
1753 guchar val = token[i++] - '0';
1755 if ('0' <= token[i] && token[i] < '8')
1756 val = (val << 3) | (token[i++] - '0');
1758 if ('0' <= token[i] && token[i] < '8')
1759 val = (val << 3) | (token[i++] - '0');
1761 str[j++] = val;
1763 continue;
1765 case 'a': str[j++] = '\a'; i++; continue;
1766 case 'b': str[j++] = '\b'; i++; continue;
1767 case 'f': str[j++] = '\f'; i++; continue;
1768 case 'n': str[j++] = '\n'; i++; continue;
1769 case 'r': str[j++] = '\r'; i++; continue;
1770 case 't': str[j++] = '\t'; i++; continue;
1771 case 'v': str[j++] = '\v'; i++; continue;
1772 case '\n': i++; continue;
1775 default:
1776 str[j++] = token[i++];
1778 str[j++] = '\0';
1779 g_free (token);
1781 string = g_slice_new (ByteString);
1782 string->ast.class = &bytestring_class;
1783 string->string = str;
1785 token_stream_next (stream);
1787 return (AST *) string;
1790 typedef struct
1792 AST ast;
1794 gchar *token;
1795 } Number;
1797 static gchar *
1798 number_get_pattern (AST *ast,
1799 GError **error)
1801 Number *number = (Number *) ast;
1803 if (strchr (number->token, '.') ||
1804 (!g_str_has_prefix (number->token, "0x") && strchr (number->token, 'e')) ||
1805 strstr (number->token, "inf") ||
1806 strstr (number->token, "nan"))
1807 return g_strdup ("Md");
1809 return g_strdup ("MN");
1812 static GVariant *
1813 number_overflow (AST *ast,
1814 const GVariantType *type,
1815 GError **error)
1817 ast_set_error (ast, error, NULL,
1818 G_VARIANT_PARSE_ERROR_NUMBER_OUT_OF_RANGE,
1819 "number out of range for type '%c'",
1820 g_variant_type_peek_string (type)[0]);
1821 return NULL;
1824 static GVariant *
1825 number_get_value (AST *ast,
1826 const GVariantType *type,
1827 GError **error)
1829 Number *number = (Number *) ast;
1830 const gchar *token;
1831 gboolean negative;
1832 gboolean floating;
1833 guint64 abs_val;
1834 gdouble dbl_val;
1835 gchar *end;
1837 token = number->token;
1839 if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
1841 floating = TRUE;
1843 errno = 0;
1844 dbl_val = g_ascii_strtod (token, &end);
1845 if (dbl_val != 0.0 && errno == ERANGE)
1847 ast_set_error (ast, error, NULL,
1848 G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG,
1849 "number too big for any type");
1850 return NULL;
1853 /* silence uninitialised warnings... */
1854 negative = FALSE;
1855 abs_val = 0;
1857 else
1859 floating = FALSE;
1860 negative = token[0] == '-';
1861 if (token[0] == '-')
1862 token++;
1864 errno = 0;
1865 abs_val = g_ascii_strtoull (token, &end, 0);
1866 if (abs_val == G_MAXUINT64 && errno == ERANGE)
1868 ast_set_error (ast, error, NULL,
1869 G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG,
1870 "integer too big for any type");
1871 return NULL;
1874 if (abs_val == 0)
1875 negative = FALSE;
1877 /* silence uninitialised warning... */
1878 dbl_val = 0.0;
1881 if (*end != '\0')
1883 SourceRef ref;
1885 ref = ast->source_ref;
1886 ref.start += end - number->token;
1887 ref.end = ref.start + 1;
1889 parser_set_error (error, &ref, NULL,
1890 G_VARIANT_PARSE_ERROR_INVALID_CHARACTER,
1891 "invalid character in number");
1892 return NULL;
1895 if (floating)
1896 return g_variant_new_double (dbl_val);
1898 switch (*g_variant_type_peek_string (type))
1900 case 'y':
1901 if (negative || abs_val > G_MAXUINT8)
1902 return number_overflow (ast, type, error);
1903 return g_variant_new_byte (abs_val);
1905 case 'n':
1906 if (abs_val - negative > G_MAXINT16)
1907 return number_overflow (ast, type, error);
1908 return g_variant_new_int16 (negative ? -abs_val : abs_val);
1910 case 'q':
1911 if (negative || abs_val > G_MAXUINT16)
1912 return number_overflow (ast, type, error);
1913 return g_variant_new_uint16 (abs_val);
1915 case 'i':
1916 if (abs_val - negative > G_MAXINT32)
1917 return number_overflow (ast, type, error);
1918 return g_variant_new_int32 (negative ? -abs_val : abs_val);
1920 case 'u':
1921 if (negative || abs_val > G_MAXUINT32)
1922 return number_overflow (ast, type, error);
1923 return g_variant_new_uint32 (abs_val);
1925 case 'x':
1926 if (abs_val - negative > G_MAXINT64)
1927 return number_overflow (ast, type, error);
1928 return g_variant_new_int64 (negative ? -abs_val : abs_val);
1930 case 't':
1931 if (negative)
1932 return number_overflow (ast, type, error);
1933 return g_variant_new_uint64 (abs_val);
1935 case 'h':
1936 if (abs_val - negative > G_MAXINT32)
1937 return number_overflow (ast, type, error);
1938 return g_variant_new_handle (negative ? -abs_val : abs_val);
1940 default:
1941 return ast_type_error (ast, type, error);
1945 static void
1946 number_free (AST *ast)
1948 Number *number = (Number *) ast;
1950 g_free (number->token);
1951 g_slice_free (Number, number);
1954 static AST *
1955 number_parse (TokenStream *stream,
1956 va_list *app,
1957 GError **error)
1959 static const ASTClass number_class = {
1960 number_get_pattern,
1961 maybe_wrapper, number_get_value,
1962 number_free
1964 Number *number;
1966 number = g_slice_new (Number);
1967 number->ast.class = &number_class;
1968 number->token = token_stream_get (stream);
1969 token_stream_next (stream);
1971 return (AST *) number;
1974 typedef struct
1976 AST ast;
1977 gboolean value;
1978 } Boolean;
1980 static gchar *
1981 boolean_get_pattern (AST *ast,
1982 GError **error)
1984 return g_strdup ("Mb");
1987 static GVariant *
1988 boolean_get_value (AST *ast,
1989 const GVariantType *type,
1990 GError **error)
1992 Boolean *boolean = (Boolean *) ast;
1994 if (!g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
1995 return ast_type_error (ast, type, error);
1997 return g_variant_new_boolean (boolean->value);
2000 static void
2001 boolean_free (AST *ast)
2003 Boolean *boolean = (Boolean *) ast;
2005 g_slice_free (Boolean, boolean);
2008 static AST *
2009 boolean_new (gboolean value)
2011 static const ASTClass boolean_class = {
2012 boolean_get_pattern,
2013 maybe_wrapper, boolean_get_value,
2014 boolean_free
2016 Boolean *boolean;
2018 boolean = g_slice_new (Boolean);
2019 boolean->ast.class = &boolean_class;
2020 boolean->value = value;
2022 return (AST *) boolean;
2025 typedef struct
2027 AST ast;
2029 GVariant *value;
2030 } Positional;
2032 static gchar *
2033 positional_get_pattern (AST *ast,
2034 GError **error)
2036 Positional *positional = (Positional *) ast;
2038 return g_strdup (g_variant_get_type_string (positional->value));
2041 static GVariant *
2042 positional_get_value (AST *ast,
2043 const GVariantType *type,
2044 GError **error)
2046 Positional *positional = (Positional *) ast;
2047 GVariant *value;
2049 g_assert (positional->value != NULL);
2051 if G_UNLIKELY (!g_variant_is_of_type (positional->value, type))
2052 return ast_type_error (ast, type, error);
2054 /* NOTE: if _get is called more than once then
2055 * things get messed up with respect to floating refs.
2057 * fortunately, this function should only ever get called once.
2059 g_assert (positional->value != NULL);
2060 value = positional->value;
2061 positional->value = NULL;
2063 return value;
2066 static void
2067 positional_free (AST *ast)
2069 Positional *positional = (Positional *) ast;
2071 /* if positional->value is set, just leave it.
2072 * memory management doesn't matter in case of programmer error.
2074 g_slice_free (Positional, positional);
2077 static AST *
2078 positional_parse (TokenStream *stream,
2079 va_list *app,
2080 GError **error)
2082 static const ASTClass positional_class = {
2083 positional_get_pattern,
2084 positional_get_value, NULL,
2085 positional_free
2087 Positional *positional;
2088 const gchar *endptr;
2089 gchar *token;
2091 token = token_stream_get (stream);
2092 g_assert (token[0] == '%');
2094 positional = g_slice_new (Positional);
2095 positional->ast.class = &positional_class;
2096 positional->value = g_variant_new_va (token + 1, &endptr, app);
2098 if (*endptr || positional->value == NULL)
2100 token_stream_set_error (stream, error, TRUE,
2101 G_VARIANT_PARSE_ERROR_INVALID_FORMAT_STRING,
2102 "invalid GVariant format string");
2103 /* memory management doesn't matter in case of programmer error. */
2104 return NULL;
2107 token_stream_next (stream);
2108 g_free (token);
2110 return (AST *) positional;
2113 typedef struct
2115 AST ast;
2117 GVariantType *type;
2118 AST *child;
2119 } TypeDecl;
2121 static gchar *
2122 typedecl_get_pattern (AST *ast,
2123 GError **error)
2125 TypeDecl *decl = (TypeDecl *) ast;
2127 return g_variant_type_dup_string (decl->type);
2130 static GVariant *
2131 typedecl_get_value (AST *ast,
2132 const GVariantType *type,
2133 GError **error)
2135 TypeDecl *decl = (TypeDecl *) ast;
2137 return ast_get_value (decl->child, type, error);
2140 static void
2141 typedecl_free (AST *ast)
2143 TypeDecl *decl = (TypeDecl *) ast;
2145 ast_free (decl->child);
2146 g_variant_type_free (decl->type);
2147 g_slice_free (TypeDecl, decl);
2150 static AST *
2151 typedecl_parse (TokenStream *stream,
2152 va_list *app,
2153 GError **error)
2155 static const ASTClass typedecl_class = {
2156 typedecl_get_pattern,
2157 typedecl_get_value, NULL,
2158 typedecl_free
2160 GVariantType *type;
2161 TypeDecl *decl;
2162 AST *child;
2164 if (token_stream_peek (stream, '@'))
2166 gchar *token;
2168 token = token_stream_get (stream);
2170 if (!g_variant_type_string_is_valid (token + 1))
2172 token_stream_set_error (stream, error, TRUE,
2173 G_VARIANT_PARSE_ERROR_INVALID_TYPE_STRING,
2174 "invalid type declaration");
2175 g_free (token);
2177 return NULL;
2180 type = g_variant_type_new (token + 1);
2182 if (!g_variant_type_is_definite (type))
2184 token_stream_set_error (stream, error, TRUE,
2185 G_VARIANT_PARSE_ERROR_DEFINITE_TYPE_EXPECTED,
2186 "type declarations must be definite");
2187 g_variant_type_free (type);
2188 g_free (token);
2190 return NULL;
2193 token_stream_next (stream);
2194 g_free (token);
2196 else
2198 if (token_stream_consume (stream, "boolean"))
2199 type = g_variant_type_copy (G_VARIANT_TYPE_BOOLEAN);
2201 else if (token_stream_consume (stream, "byte"))
2202 type = g_variant_type_copy (G_VARIANT_TYPE_BYTE);
2204 else if (token_stream_consume (stream, "int16"))
2205 type = g_variant_type_copy (G_VARIANT_TYPE_INT16);
2207 else if (token_stream_consume (stream, "uint16"))
2208 type = g_variant_type_copy (G_VARIANT_TYPE_UINT16);
2210 else if (token_stream_consume (stream, "int32"))
2211 type = g_variant_type_copy (G_VARIANT_TYPE_INT32);
2213 else if (token_stream_consume (stream, "handle"))
2214 type = g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
2216 else if (token_stream_consume (stream, "uint32"))
2217 type = g_variant_type_copy (G_VARIANT_TYPE_UINT32);
2219 else if (token_stream_consume (stream, "int64"))
2220 type = g_variant_type_copy (G_VARIANT_TYPE_INT64);
2222 else if (token_stream_consume (stream, "uint64"))
2223 type = g_variant_type_copy (G_VARIANT_TYPE_UINT64);
2225 else if (token_stream_consume (stream, "double"))
2226 type = g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
2228 else if (token_stream_consume (stream, "string"))
2229 type = g_variant_type_copy (G_VARIANT_TYPE_STRING);
2231 else if (token_stream_consume (stream, "objectpath"))
2232 type = g_variant_type_copy (G_VARIANT_TYPE_OBJECT_PATH);
2234 else if (token_stream_consume (stream, "signature"))
2235 type = g_variant_type_copy (G_VARIANT_TYPE_SIGNATURE);
2237 else
2239 token_stream_set_error (stream, error, TRUE,
2240 G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD,
2241 "unknown keyword");
2242 return NULL;
2246 if ((child = parse (stream, app, error)) == NULL)
2248 g_variant_type_free (type);
2249 return NULL;
2252 decl = g_slice_new (TypeDecl);
2253 decl->ast.class = &typedecl_class;
2254 decl->type = type;
2255 decl->child = child;
2257 return (AST *) decl;
2260 static AST *
2261 parse (TokenStream *stream,
2262 va_list *app,
2263 GError **error)
2265 SourceRef source_ref;
2266 AST *result;
2268 token_stream_prepare (stream);
2269 token_stream_start_ref (stream, &source_ref);
2271 if (token_stream_peek (stream, '['))
2272 result = array_parse (stream, app, error);
2274 else if (token_stream_peek (stream, '('))
2275 result = tuple_parse (stream, app, error);
2277 else if (token_stream_peek (stream, '<'))
2278 result = variant_parse (stream, app, error);
2280 else if (token_stream_peek (stream, '{'))
2281 result = dictionary_parse (stream, app, error);
2283 else if (app && token_stream_peek (stream, '%'))
2284 result = positional_parse (stream, app, error);
2286 else if (token_stream_consume (stream, "true"))
2287 result = boolean_new (TRUE);
2289 else if (token_stream_consume (stream, "false"))
2290 result = boolean_new (FALSE);
2292 else if (token_stream_is_numeric (stream) ||
2293 token_stream_peek_string (stream, "inf") ||
2294 token_stream_peek_string (stream, "nan"))
2295 result = number_parse (stream, app, error);
2297 else if (token_stream_peek (stream, 'n') ||
2298 token_stream_peek (stream, 'j'))
2299 result = maybe_parse (stream, app, error);
2301 else if (token_stream_peek (stream, '@') ||
2302 token_stream_is_keyword (stream))
2303 result = typedecl_parse (stream, app, error);
2305 else if (token_stream_peek (stream, '\'') ||
2306 token_stream_peek (stream, '"'))
2307 result = string_parse (stream, app, error);
2309 else if (token_stream_peek2 (stream, 'b', '\'') ||
2310 token_stream_peek2 (stream, 'b', '"'))
2311 result = bytestring_parse (stream, app, error);
2313 else
2315 token_stream_set_error (stream, error, FALSE,
2316 G_VARIANT_PARSE_ERROR_VALUE_EXPECTED,
2317 "expected value");
2318 return NULL;
2321 if (result != NULL)
2323 token_stream_end_ref (stream, &source_ref);
2324 result->source_ref = source_ref;
2327 return result;
2331 * g_variant_parse:
2332 * @type: (nullable): a #GVariantType, or %NULL
2333 * @text: a string containing a GVariant in text form
2334 * @limit: (nullable): a pointer to the end of @text, or %NULL
2335 * @endptr: (nullable): a location to store the end pointer, or %NULL
2336 * @error: (nullable): a pointer to a %NULL #GError pointer, or %NULL
2338 * Parses a #GVariant from a text representation.
2340 * A single #GVariant is parsed from the content of @text.
2342 * The format is described [here][gvariant-text].
2344 * The memory at @limit will never be accessed and the parser behaves as
2345 * if the character at @limit is the nul terminator. This has the
2346 * effect of bounding @text.
2348 * If @endptr is non-%NULL then @text is permitted to contain data
2349 * following the value that this function parses and @endptr will be
2350 * updated to point to the first character past the end of the text
2351 * parsed by this function. If @endptr is %NULL and there is extra data
2352 * then an error is returned.
2354 * If @type is non-%NULL then the value will be parsed to have that
2355 * type. This may result in additional parse errors (in the case that
2356 * the parsed value doesn't fit the type) but may also result in fewer
2357 * errors (in the case that the type would have been ambiguous, such as
2358 * with empty arrays).
2360 * In the event that the parsing is successful, the resulting #GVariant
2361 * is returned. It is never floating, and must be freed with
2362 * g_variant_unref().
2364 * In case of any error, %NULL will be returned. If @error is non-%NULL
2365 * then it will be set to reflect the error that occurred.
2367 * Officially, the language understood by the parser is "any string
2368 * produced by g_variant_print()".
2370 * Returns: a non-floating reference to a #GVariant, or %NULL
2372 GVariant *
2373 g_variant_parse (const GVariantType *type,
2374 const gchar *text,
2375 const gchar *limit,
2376 const gchar **endptr,
2377 GError **error)
2379 TokenStream stream = { 0, };
2380 GVariant *result = NULL;
2381 AST *ast;
2383 g_return_val_if_fail (text != NULL, NULL);
2384 g_return_val_if_fail (text == limit || text != NULL, NULL);
2386 stream.start = text;
2387 stream.stream = text;
2388 stream.end = limit;
2390 if ((ast = parse (&stream, NULL, error)))
2392 if (type == NULL)
2393 result = ast_resolve (ast, error);
2394 else
2395 result = ast_get_value (ast, type, error);
2397 if (result != NULL)
2399 g_variant_ref_sink (result);
2401 if (endptr == NULL)
2403 while (stream.stream != limit &&
2404 g_ascii_isspace (*stream.stream))
2405 stream.stream++;
2407 if (stream.stream != limit && *stream.stream != '\0')
2409 SourceRef ref = { stream.stream - text,
2410 stream.stream - text };
2412 parser_set_error (error, &ref, NULL,
2413 G_VARIANT_PARSE_ERROR_INPUT_NOT_AT_END,
2414 "expected end of input");
2415 g_variant_unref (result);
2417 result = NULL;
2420 else
2421 *endptr = stream.stream;
2424 ast_free (ast);
2427 return result;
2431 * g_variant_new_parsed_va:
2432 * @format: a text format #GVariant
2433 * @app: a pointer to a #va_list
2435 * Parses @format and returns the result.
2437 * This is the version of g_variant_new_parsed() intended to be used
2438 * from libraries.
2440 * The return value will be floating if it was a newly created GVariant
2441 * instance. In the case that @format simply specified the collection
2442 * of a #GVariant pointer (eg: @format was "%*") then the collected
2443 * #GVariant pointer will be returned unmodified, without adding any
2444 * additional references.
2446 * Note that the arguments in @app must be of the correct width for their types
2447 * specified in @format when collected into the #va_list. See
2448 * the [GVariant varargs documentation][gvariant-varargs].
2450 * In order to behave correctly in all cases it is necessary for the
2451 * calling function to g_variant_ref_sink() the return result before
2452 * returning control to the user that originally provided the pointer.
2453 * At this point, the caller will have their own full reference to the
2454 * result. This can also be done by adding the result to a container,
2455 * or by passing it to another g_variant_new() call.
2457 * Returns: a new, usually floating, #GVariant
2459 GVariant *
2460 g_variant_new_parsed_va (const gchar *format,
2461 va_list *app)
2463 TokenStream stream = { 0, };
2464 GVariant *result = NULL;
2465 GError *error = NULL;
2466 AST *ast;
2468 g_return_val_if_fail (format != NULL, NULL);
2469 g_return_val_if_fail (app != NULL, NULL);
2471 stream.start = format;
2472 stream.stream = format;
2473 stream.end = NULL;
2475 if ((ast = parse (&stream, app, &error)))
2477 result = ast_resolve (ast, &error);
2478 ast_free (ast);
2481 if (result == NULL)
2482 g_error ("g_variant_new_parsed: %s", error->message);
2484 if (*stream.stream)
2485 g_error ("g_variant_new_parsed: trailing text after value");
2487 return result;
2491 * g_variant_new_parsed:
2492 * @format: a text format #GVariant
2493 * @...: arguments as per @format
2495 * Parses @format and returns the result.
2497 * @format must be a text format #GVariant with one extension: at any
2498 * point that a value may appear in the text, a '%' character followed
2499 * by a GVariant format string (as per g_variant_new()) may appear. In
2500 * that case, the same arguments are collected from the argument list as
2501 * g_variant_new() would have collected.
2503 * Note that the arguments must be of the correct width for their types
2504 * specified in @format. This can be achieved by casting them. See
2505 * the [GVariant varargs documentation][gvariant-varargs].
2507 * Consider this simple example:
2508 * |[<!-- language="C" -->
2509 * g_variant_new_parsed ("[('one', 1), ('two', %i), (%s, 3)]", 2, "three");
2510 * ]|
2512 * In the example, the variable argument parameters are collected and
2513 * filled in as if they were part of the original string to produce the
2514 * result of
2515 * |[<!-- language="C" -->
2516 * [('one', 1), ('two', 2), ('three', 3)]
2517 * ]|
2519 * This function is intended only to be used with @format as a string
2520 * literal. Any parse error is fatal to the calling process. If you
2521 * want to parse data from untrusted sources, use g_variant_parse().
2523 * You may not use this function to return, unmodified, a single
2524 * #GVariant pointer from the argument list. ie: @format may not solely
2525 * be anything along the lines of "%*", "%?", "\%r", or anything starting
2526 * with "%@".
2528 * Returns: a new floating #GVariant instance
2530 GVariant *
2531 g_variant_new_parsed (const gchar *format,
2532 ...)
2534 GVariant *result;
2535 va_list ap;
2537 va_start (ap, format);
2538 result = g_variant_new_parsed_va (format, &ap);
2539 va_end (ap);
2541 return result;
2545 * g_variant_builder_add_parsed:
2546 * @builder: a #GVariantBuilder
2547 * @format: a text format #GVariant
2548 * @...: arguments as per @format
2550 * Adds to a #GVariantBuilder.
2552 * This call is a convenience wrapper that is exactly equivalent to
2553 * calling g_variant_new_parsed() followed by
2554 * g_variant_builder_add_value().
2556 * Note that the arguments must be of the correct width for their types
2557 * specified in @format_string. This can be achieved by casting them. See
2558 * the [GVariant varargs documentation][gvariant-varargs].
2560 * This function might be used as follows:
2562 * |[<!-- language="C" -->
2563 * GVariant *
2564 * make_pointless_dictionary (void)
2566 * GVariantBuilder builder;
2567 * int i;
2569 * g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
2570 * g_variant_builder_add_parsed (&builder, "{'width', <%i>}", 600);
2571 * g_variant_builder_add_parsed (&builder, "{'title', <%s>}", "foo");
2572 * g_variant_builder_add_parsed (&builder, "{'transparency', <0.5>}");
2573 * return g_variant_builder_end (&builder);
2575 * ]|
2577 * Since: 2.26
2579 void
2580 g_variant_builder_add_parsed (GVariantBuilder *builder,
2581 const gchar *format,
2582 ...)
2584 va_list ap;
2586 va_start (ap, format);
2587 g_variant_builder_add_value (builder, g_variant_new_parsed_va (format, &ap));
2588 va_end (ap);
2591 static gboolean
2592 parse_num (const gchar *num,
2593 const gchar *limit,
2594 gint *result)
2596 gchar *endptr;
2597 gint64 bignum;
2599 bignum = g_ascii_strtoll (num, &endptr, 10);
2601 if (endptr != limit)
2602 return FALSE;
2604 if (bignum < 0 || bignum > G_MAXINT)
2605 return FALSE;
2607 *result = bignum;
2609 return TRUE;
2612 static void
2613 add_last_line (GString *err,
2614 const gchar *str)
2616 const gchar *last_nl;
2617 gchar *chomped;
2618 gint i;
2620 /* This is an error at the end of input. If we have a file
2621 * with newlines, that's probably the empty string after the
2622 * last newline, which is not the most useful thing to show.
2624 * Instead, show the last line of non-whitespace that we have
2625 * and put the pointer at the end of it.
2627 chomped = g_strchomp (g_strdup (str));
2628 last_nl = strrchr (chomped, '\n');
2629 if (last_nl == NULL)
2630 last_nl = chomped;
2631 else
2632 last_nl++;
2634 /* Print the last line like so:
2636 * [1, 2, 3,
2639 g_string_append (err, " ");
2640 if (last_nl[0])
2641 g_string_append (err, last_nl);
2642 else
2643 g_string_append (err, "(empty input)");
2644 g_string_append (err, "\n ");
2645 for (i = 0; last_nl[i]; i++)
2646 g_string_append_c (err, ' ');
2647 g_string_append (err, "^\n");
2648 g_free (chomped);
2651 static void
2652 add_lines_from_range (GString *err,
2653 const gchar *str,
2654 const gchar *start1,
2655 const gchar *end1,
2656 const gchar *start2,
2657 const gchar *end2)
2659 while (str < end1 || str < end2)
2661 const gchar *nl;
2663 nl = str + strcspn (str, "\n");
2665 if ((start1 < nl && str < end1) || (start2 < nl && str < end2))
2667 const gchar *s;
2669 /* We're going to print this line */
2670 g_string_append (err, " ");
2671 g_string_append_len (err, str, nl - str);
2672 g_string_append (err, "\n ");
2674 /* And add underlines... */
2675 for (s = str; s < nl; s++)
2677 if ((start1 <= s && s < end1) || (start2 <= s && s < end2))
2678 g_string_append_c (err, '^');
2679 else
2680 g_string_append_c (err, ' ');
2682 g_string_append_c (err, '\n');
2685 if (!*nl)
2686 break;
2688 str = nl + 1;
2693 * g_variant_parse_error_print_context:
2694 * @error: a #GError from the #GVariantParseError domain
2695 * @source_str: the string that was given to the parser
2697 * Pretty-prints a message showing the context of a #GVariant parse
2698 * error within the string for which parsing was attempted.
2700 * The resulting string is suitable for output to the console or other
2701 * monospace media where newlines are treated in the usual way.
2703 * The message will typically look something like one of the following:
2705 * |[
2706 * unterminated string constant:
2707 * (1, 2, 3, 'abc
2708 * ^^^^
2709 * ]|
2711 * or
2713 * |[
2714 * unable to find a common type:
2715 * [1, 2, 3, 'str']
2716 * ^ ^^^^^
2717 * ]|
2719 * The format of the message may change in a future version.
2721 * @error must have come from a failed attempt to g_variant_parse() and
2722 * @source_str must be exactly the same string that caused the error.
2723 * If @source_str was not nul-terminated when you passed it to
2724 * g_variant_parse() then you must add nul termination before using this
2725 * function.
2727 * Returns: (transfer full): the printed message
2729 * Since: 2.40
2731 gchar *
2732 g_variant_parse_error_print_context (GError *error,
2733 const gchar *source_str)
2735 const gchar *colon, *dash, *comma;
2736 gboolean success = FALSE;
2737 GString *err;
2739 g_return_val_if_fail (error->domain == G_VARIANT_PARSE_ERROR, FALSE);
2741 /* We can only have a limited number of possible types of ranges
2742 * emitted from the parser:
2744 * - a: -- usually errors from the tokeniser (eof, invalid char, etc.)
2745 * - a-b: -- usually errors from handling one single token
2746 * - a-b,c-d: -- errors involving two tokens (ie: type inferencing)
2748 * We never see, for example "a,c".
2751 colon = strchr (error->message, ':');
2752 dash = strchr (error->message, '-');
2753 comma = strchr (error->message, ',');
2755 if (!colon)
2756 return NULL;
2758 err = g_string_new (colon + 1);
2759 g_string_append (err, ":\n");
2761 if (dash == NULL || colon < dash)
2763 gint point;
2765 /* we have a single point */
2766 if (!parse_num (error->message, colon, &point))
2767 goto out;
2769 if (point >= strlen (source_str))
2770 /* the error is at the end of the input */
2771 add_last_line (err, source_str);
2772 else
2773 /* otherwise just treat it as a error at a thin range */
2774 add_lines_from_range (err, source_str, source_str + point, source_str + point + 1, NULL, NULL);
2776 else
2778 /* We have one or two ranges... */
2779 if (comma && comma < colon)
2781 gint start1, end1, start2, end2;
2782 const gchar *dash2;
2784 /* Two ranges */
2785 dash2 = strchr (comma, '-');
2787 if (!parse_num (error->message, dash, &start1) || !parse_num (dash + 1, comma, &end1) ||
2788 !parse_num (comma + 1, dash2, &start2) || !parse_num (dash2 + 1, colon, &end2))
2789 goto out;
2791 add_lines_from_range (err, source_str,
2792 source_str + start1, source_str + end1,
2793 source_str + start2, source_str + end2);
2795 else
2797 gint start, end;
2799 /* One range */
2800 if (!parse_num (error->message, dash, &start) || !parse_num (dash + 1, colon, &end))
2801 goto out;
2803 add_lines_from_range (err, source_str, source_str + start, source_str + end, NULL, NULL);
2807 success = TRUE;
2809 out:
2810 return g_string_free (err, !success);