GObject: substantially rework g_object_new()
[glib.git] / glib / gvariant-parser.c
blobc60bd77bde2faff279bd5627ef40fdd928092abd
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 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>
22 #include "config.h"
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
28 #include "gerror.h"
29 #include "gquark.h"
30 #include "gstring.h"
31 #include "gstrfuncs.h"
32 #include "gtestutils.h"
33 #include "gvariant.h"
34 #include "gvarianttype.h"
35 #include "gslice.h"
36 #include "gthread.h"
39 * two-pass algorithm
40 * designed by ryan lortie and william hua
41 * designed in itb-229 and at ghazi's, 2009.
44 /**
45 * G_VARIANT_PARSE_ERROR:
47 * Error domain for GVariant text format parsing. Specific error codes
48 * are not currently defined for this domain. See #GError for
49 * information on error domains.
50 **/
51 /**
52 * GVariantParseError:
53 * @G_VARIANT_PARSE_ERROR_FAILED: generic error (unused)
54 * @G_VARIANT_PARSE_ERROR_BASIC_TYPE_EXPECTED: a non-basic #GVariantType was given where a basic type was expected
55 * @G_VARIANT_PARSE_ERROR_CANNOT_INFER_TYPE: cannot infer the #GVariantType
56 * @G_VARIANT_PARSE_ERROR_DEFINITE_TYPE_EXPECTED: an indefinite #GVariantType was given where a definite type was expected
57 * @G_VARIANT_PARSE_ERROR_INPUT_NOT_AT_END: extra data after parsing finished
58 * @G_VARIANT_PARSE_ERROR_INVALID_CHARACTER: invalid character in number or unicode escape
59 * @G_VARIANT_PARSE_ERROR_INVALID_FORMAT_STRING: not a valid #GVariant format string
60 * @G_VARIANT_PARSE_ERROR_INVALID_OBJECT_PATH: not a valid object path
61 * @G_VARIANT_PARSE_ERROR_INVALID_SIGNATURE: not a valid type signature
62 * @G_VARIANT_PARSE_ERROR_INVALID_TYPE_STRING: not a valid #GVariant type string
63 * @G_VARIANT_PARSE_ERROR_NO_COMMON_TYPE: could not find a common type for array entries
64 * @G_VARIANT_PARSE_ERROR_NUMBER_OUT_OF_RANGE: the numerical value is out of range of the given type
65 * @G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG: the numerical value is out of range for any type
66 * @G_VARIANT_PARSE_ERROR_TYPE_ERROR: cannot parse as variant of the specified type
67 * @G_VARIANT_PARSE_ERROR_UNEXPECTED_TOKEN: an unexpected token was encountered
68 * @G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD: an unknown keyword was encountered
69 * @G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT: unterminated string constant
70 * @G_VARIANT_PARSE_ERROR_VALUE_EXPECTED: no value given
72 * Error codes returned by parsing text-format GVariants.
73 **/
74 G_DEFINE_QUARK (g-variant-parse-error-quark, g_variant_parser_get_error)
76 typedef struct
78 gint start, end;
79 } SourceRef;
81 G_GNUC_PRINTF(5, 0)
82 static void
83 parser_set_error_va (GError **error,
84 SourceRef *location,
85 SourceRef *other,
86 gint code,
87 const gchar *format,
88 va_list ap)
90 GString *msg = g_string_new (NULL);
92 if (location->start == location->end)
93 g_string_append_printf (msg, "%d", location->start);
94 else
95 g_string_append_printf (msg, "%d-%d", location->start, location->end);
97 if (other != NULL)
99 g_assert (other->start != other->end);
100 g_string_append_printf (msg, ",%d-%d", other->start, other->end);
102 g_string_append_c (msg, ':');
104 g_string_append_vprintf (msg, format, ap);
105 g_set_error_literal (error, G_VARIANT_PARSE_ERROR, code, msg->str);
106 g_string_free (msg, TRUE);
109 G_GNUC_PRINTF(5, 6)
110 static void
111 parser_set_error (GError **error,
112 SourceRef *location,
113 SourceRef *other,
114 gint code,
115 const gchar *format,
116 ...)
118 va_list ap;
120 va_start (ap, format);
121 parser_set_error_va (error, location, other, code, format, ap);
122 va_end (ap);
125 typedef struct
127 const gchar *start;
128 const gchar *stream;
129 const gchar *end;
131 const gchar *this;
132 } TokenStream;
135 G_GNUC_PRINTF(5, 6)
136 static void
137 token_stream_set_error (TokenStream *stream,
138 GError **error,
139 gboolean this_token,
140 gint code,
141 const gchar *format,
142 ...)
144 SourceRef ref;
145 va_list ap;
147 ref.start = stream->this - stream->start;
149 if (this_token)
150 ref.end = stream->stream - stream->start;
151 else
152 ref.end = ref.start;
154 va_start (ap, format);
155 parser_set_error_va (error, &ref, NULL, code, format, ap);
156 va_end (ap);
159 static gboolean
160 token_stream_prepare (TokenStream *stream)
162 gint brackets = 0;
163 const gchar *end;
165 if (stream->this != NULL)
166 return TRUE;
168 while (stream->stream != stream->end && g_ascii_isspace (*stream->stream))
169 stream->stream++;
171 if (stream->stream == stream->end || *stream->stream == '\0')
173 stream->this = stream->stream;
174 return FALSE;
177 switch (stream->stream[0])
179 case '-': case '+': case '.': case '0': case '1': case '2':
180 case '3': case '4': case '5': case '6': case '7': case '8':
181 case '9':
182 for (end = stream->stream; end != stream->end; end++)
183 if (!g_ascii_isalnum (*end) &&
184 *end != '-' && *end != '+' && *end != '.')
185 break;
186 break;
188 case 'b':
189 if (stream->stream[1] == '\'' || stream->stream[1] == '"')
191 for (end = stream->stream + 2; end != stream->end; end++)
192 if (*end == stream->stream[1] || *end == '\0' ||
193 (*end == '\\' && (++end == stream->end || *end == '\0')))
194 break;
196 if (end != stream->end && *end)
197 end++;
198 break;
201 else /* ↓↓↓ */;
203 case 'a': /* 'b' */ case 'c': case 'd': case 'e': case 'f':
204 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
205 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
206 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
207 case 'y': case 'z':
208 for (end = stream->stream; end != stream->end; end++)
209 if (!g_ascii_isalnum (*end))
210 break;
211 break;
213 case '\'': case '"':
214 for (end = stream->stream + 1; end != stream->end; end++)
215 if (*end == stream->stream[0] || *end == '\0' ||
216 (*end == '\\' && (++end == stream->end || *end == '\0')))
217 break;
219 if (end != stream->end && *end)
220 end++;
221 break;
223 case '@': case '%':
224 /* stop at the first space, comma, colon or unmatched bracket.
225 * deals nicely with cases like (%i, %i) or {%i: %i}.
226 * Also: ] and > are never in format strings.
228 for (end = stream->stream + 1;
229 end != stream->end && *end != ',' &&
230 *end != ':' && *end != '>' && *end != ']' && !g_ascii_isspace (*end);
231 end++)
233 if (*end == '(' || *end == '{')
234 brackets++;
236 else if ((*end == ')' || *end == '}') && !brackets--)
237 break;
239 break;
241 default:
242 end = stream->stream + 1;
243 break;
246 stream->this = stream->stream;
247 stream->stream = end;
249 return TRUE;
252 static void
253 token_stream_next (TokenStream *stream)
255 stream->this = NULL;
258 static gboolean
259 token_stream_peek (TokenStream *stream,
260 gchar first_char)
262 if (!token_stream_prepare (stream))
263 return FALSE;
265 return stream->this[0] == first_char;
268 static gboolean
269 token_stream_peek2 (TokenStream *stream,
270 gchar first_char,
271 gchar second_char)
273 if (!token_stream_prepare (stream))
274 return FALSE;
276 return stream->this[0] == first_char &&
277 stream->this[1] == second_char;
280 static gboolean
281 token_stream_is_keyword (TokenStream *stream)
283 if (!token_stream_prepare (stream))
284 return FALSE;
286 return g_ascii_isalpha (stream->this[0]) &&
287 g_ascii_isalpha (stream->this[1]);
290 static gboolean
291 token_stream_is_numeric (TokenStream *stream)
293 if (!token_stream_prepare (stream))
294 return FALSE;
296 return (g_ascii_isdigit (stream->this[0]) ||
297 stream->this[0] == '-' ||
298 stream->this[0] == '+' ||
299 stream->this[0] == '.');
302 static gboolean
303 token_stream_peek_string (TokenStream *stream,
304 const gchar *token)
306 gint length = strlen (token);
308 return token_stream_prepare (stream) &&
309 stream->stream - stream->this == length &&
310 memcmp (stream->this, token, length) == 0;
313 static gboolean
314 token_stream_consume (TokenStream *stream,
315 const gchar *token)
317 if (!token_stream_peek_string (stream, token))
318 return FALSE;
320 token_stream_next (stream);
321 return TRUE;
324 static gboolean
325 token_stream_require (TokenStream *stream,
326 const gchar *token,
327 const gchar *purpose,
328 GError **error)
331 if (!token_stream_consume (stream, token))
333 token_stream_set_error (stream, error, FALSE,
334 G_VARIANT_PARSE_ERROR_UNEXPECTED_TOKEN,
335 "expected `%s'%s", token, purpose);
336 return FALSE;
339 return TRUE;
342 static void
343 token_stream_assert (TokenStream *stream,
344 const gchar *token)
346 gboolean correct_token;
348 correct_token = token_stream_consume (stream, token);
349 g_assert (correct_token);
352 static gchar *
353 token_stream_get (TokenStream *stream)
355 gchar *result;
357 if (!token_stream_prepare (stream))
358 return NULL;
360 result = g_strndup (stream->this, stream->stream - stream->this);
362 return result;
365 static void
366 token_stream_start_ref (TokenStream *stream,
367 SourceRef *ref)
369 token_stream_prepare (stream);
370 ref->start = stream->this - stream->start;
373 static void
374 token_stream_end_ref (TokenStream *stream,
375 SourceRef *ref)
377 ref->end = stream->stream - stream->start;
380 static void
381 pattern_copy (gchar **out,
382 const gchar **in)
384 gint brackets = 0;
386 while (**in == 'a' || **in == 'm' || **in == 'M')
387 *(*out)++ = *(*in)++;
391 if (**in == '(' || **in == '{')
392 brackets++;
394 else if (**in == ')' || **in == '}')
395 brackets--;
397 *(*out)++ = *(*in)++;
399 while (brackets);
402 static gchar *
403 pattern_coalesce (const gchar *left,
404 const gchar *right)
406 gchar *result;
407 gchar *out;
409 /* the length of the output is loosely bound by the sum of the input
410 * lengths, not simply the greater of the two lengths.
412 * (*(iii)) + ((iii)*) ((iii)(iii))
414 * 8 + 8 = 12
416 out = result = g_malloc (strlen (left) + strlen (right));
418 while (*left && *right)
420 if (*left == *right)
422 *out++ = *left++;
423 right++;
426 else
428 const gchar **one = &left, **the_other = &right;
430 again:
431 if (**one == '*' && **the_other != ')')
433 pattern_copy (&out, the_other);
434 (*one)++;
437 else if (**one == 'M' && **the_other == 'm')
439 *out++ = *(*the_other)++;
442 else if (**one == 'M' && **the_other != 'm')
444 (*one)++;
447 else if (**one == 'N' && strchr ("ynqiuxthd", **the_other))
449 *out++ = *(*the_other)++;
450 (*one)++;
453 else if (**one == 'S' && strchr ("sog", **the_other))
455 *out++ = *(*the_other)++;
456 (*one)++;
459 else if (one == &left)
461 one = &right, the_other = &left;
462 goto again;
465 else
466 break;
470 if (*left || *right)
472 g_free (result);
473 result = NULL;
475 else
476 *out++ = '\0';
478 return result;
481 typedef struct _AST AST;
482 typedef gchar * (*get_pattern_func) (AST *ast,
483 GError **error);
484 typedef GVariant * (*get_value_func) (AST *ast,
485 const GVariantType *type,
486 GError **error);
487 typedef GVariant * (*get_base_value_func) (AST *ast,
488 const GVariantType *type,
489 GError **error);
490 typedef void (*free_func) (AST *ast);
492 typedef struct
494 gchar * (* get_pattern) (AST *ast,
495 GError **error);
496 GVariant * (* get_value) (AST *ast,
497 const GVariantType *type,
498 GError **error);
499 GVariant * (* get_base_value) (AST *ast,
500 const GVariantType *type,
501 GError **error);
502 void (* free) (AST *ast);
503 } ASTClass;
505 struct _AST
507 const ASTClass *class;
508 SourceRef source_ref;
511 static gchar *
512 ast_get_pattern (AST *ast,
513 GError **error)
515 return ast->class->get_pattern (ast, error);
518 static GVariant *
519 ast_get_value (AST *ast,
520 const GVariantType *type,
521 GError **error)
523 return ast->class->get_value (ast, type, error);
526 static void
527 ast_free (AST *ast)
529 ast->class->free (ast);
532 G_GNUC_PRINTF(5, 6)
533 static void
534 ast_set_error (AST *ast,
535 GError **error,
536 AST *other_ast,
537 gint code,
538 const gchar *format,
539 ...)
541 va_list ap;
543 va_start (ap, format);
544 parser_set_error_va (error, &ast->source_ref,
545 other_ast ? & other_ast->source_ref : NULL,
546 code,
547 format, ap);
548 va_end (ap);
551 static GVariant *
552 ast_type_error (AST *ast,
553 const GVariantType *type,
554 GError **error)
556 gchar *typestr;
558 typestr = g_variant_type_dup_string (type);
559 ast_set_error (ast, error, NULL,
560 G_VARIANT_PARSE_ERROR_TYPE_ERROR,
561 "can not parse as value of type `%s'",
562 typestr);
563 g_free (typestr);
565 return NULL;
568 static GVariant *
569 ast_resolve (AST *ast,
570 GError **error)
572 GVariant *value;
573 gchar *pattern;
574 gint i, j = 0;
576 pattern = ast_get_pattern (ast, error);
578 if (pattern == NULL)
579 return NULL;
581 /* choose reasonable defaults
583 * 1) favour non-maybe values where possible
584 * 2) default type for strings is 's'
585 * 3) default type for integers is 'i'
587 for (i = 0; pattern[i]; i++)
588 switch (pattern[i])
590 case '*':
591 ast_set_error (ast, error, NULL,
592 G_VARIANT_PARSE_ERROR_CANNOT_INFER_TYPE,
593 "unable to infer type");
594 g_free (pattern);
595 return NULL;
597 case 'M':
598 break;
600 case 'S':
601 pattern[j++] = 's';
602 break;
604 case 'N':
605 pattern[j++] = 'i';
606 break;
608 default:
609 pattern[j++] = pattern[i];
610 break;
612 pattern[j++] = '\0';
614 value = ast_get_value (ast, G_VARIANT_TYPE (pattern), error);
615 g_free (pattern);
617 return value;
621 static AST *parse (TokenStream *stream,
622 va_list *app,
623 GError **error);
625 static void
626 ast_array_append (AST ***array,
627 gint *n_items,
628 AST *ast)
630 if ((*n_items & (*n_items - 1)) == 0)
631 *array = g_renew (AST *, *array, *n_items ? 2 ** n_items : 1);
633 (*array)[(*n_items)++] = ast;
636 static void
637 ast_array_free (AST **array,
638 gint n_items)
640 gint i;
642 for (i = 0; i < n_items; i++)
643 ast_free (array[i]);
644 g_free (array);
647 static gchar *
648 ast_array_get_pattern (AST **array,
649 gint n_items,
650 GError **error)
652 gchar *pattern;
653 gint i;
655 pattern = ast_get_pattern (array[0], error);
657 if (pattern == NULL)
658 return NULL;
660 for (i = 1; i < n_items; i++)
662 gchar *tmp, *merged;
664 tmp = ast_get_pattern (array[i], error);
666 if (tmp == NULL)
668 g_free (pattern);
669 return NULL;
672 merged = pattern_coalesce (pattern, tmp);
673 g_free (pattern);
674 pattern = merged;
676 if (merged == NULL)
677 /* set coalescence implies pairwise coalescence (i think).
678 * we should therefore be able to trace the failure to a single
679 * pair of values.
682 int j = 0;
684 while (TRUE)
686 gchar *tmp2;
687 gchar *m;
689 /* if 'j' reaches 'i' then we failed to find the pair */
690 g_assert (j < i);
692 tmp2 = ast_get_pattern (array[j], NULL);
693 g_assert (tmp2 != NULL);
695 m = pattern_coalesce (tmp, tmp2);
696 g_free (tmp2);
697 g_free (m);
699 if (m == NULL)
701 /* we found a conflict between 'i' and 'j'.
703 * report the error. note: 'j' is first.
705 ast_set_error (array[j], error, array[i],
706 G_VARIANT_PARSE_ERROR_NO_COMMON_TYPE,
707 "unable to find a common type");
708 g_free (tmp);
709 return NULL;
712 j++;
717 g_free (tmp);
720 return pattern;
723 typedef struct
725 AST ast;
727 AST *child;
728 } Maybe;
730 static gchar *
731 maybe_get_pattern (AST *ast,
732 GError **error)
734 Maybe *maybe = (Maybe *) ast;
736 if (maybe->child != NULL)
738 gchar *child_pattern;
739 gchar *pattern;
741 child_pattern = ast_get_pattern (maybe->child, error);
743 if (child_pattern == NULL)
744 return NULL;
746 pattern = g_strdup_printf ("m%s", child_pattern);
747 g_free (child_pattern);
749 return pattern;
752 return g_strdup ("m*");
755 static GVariant *
756 maybe_get_value (AST *ast,
757 const GVariantType *type,
758 GError **error)
760 Maybe *maybe = (Maybe *) ast;
761 GVariant *value;
763 if (!g_variant_type_is_maybe (type))
764 return ast_type_error (ast, type, error);
766 type = g_variant_type_element (type);
768 if (maybe->child)
770 value = ast_get_value (maybe->child, type, error);
772 if (value == NULL)
773 return NULL;
775 else
776 value = NULL;
778 return g_variant_new_maybe (type, value);
781 static void
782 maybe_free (AST *ast)
784 Maybe *maybe = (Maybe *) ast;
786 if (maybe->child != NULL)
787 ast_free (maybe->child);
789 g_slice_free (Maybe, maybe);
792 static AST *
793 maybe_parse (TokenStream *stream,
794 va_list *app,
795 GError **error)
797 static const ASTClass maybe_class = {
798 maybe_get_pattern,
799 maybe_get_value, NULL,
800 maybe_free
802 AST *child = NULL;
803 Maybe *maybe;
805 if (token_stream_consume (stream, "just"))
807 child = parse (stream, app, error);
808 if (child == NULL)
809 return NULL;
812 else if (!token_stream_consume (stream, "nothing"))
814 token_stream_set_error (stream, error, TRUE,
815 G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD,
816 "unknown keyword");
817 return NULL;
820 maybe = g_slice_new (Maybe);
821 maybe->ast.class = &maybe_class;
822 maybe->child = child;
824 return (AST *) maybe;
827 static GVariant *
828 maybe_wrapper (AST *ast,
829 const GVariantType *type,
830 GError **error)
832 const GVariantType *t;
833 GVariant *value;
834 int depth;
836 for (depth = 0, t = type;
837 g_variant_type_is_maybe (t);
838 depth++, t = g_variant_type_element (t));
840 value = ast->class->get_base_value (ast, t, error);
842 if (value == NULL)
843 return NULL;
845 while (depth--)
846 value = g_variant_new_maybe (NULL, value);
848 return value;
851 typedef struct
853 AST ast;
855 AST **children;
856 gint n_children;
857 } Array;
859 static gchar *
860 array_get_pattern (AST *ast,
861 GError **error)
863 Array *array = (Array *) ast;
864 gchar *pattern;
865 gchar *result;
867 if (array->n_children == 0)
868 return g_strdup ("Ma*");
870 pattern = ast_array_get_pattern (array->children, array->n_children, error);
872 if (pattern == NULL)
873 return NULL;
875 result = g_strdup_printf ("Ma%s", pattern);
876 g_free (pattern);
878 return result;
881 static GVariant *
882 array_get_value (AST *ast,
883 const GVariantType *type,
884 GError **error)
886 Array *array = (Array *) ast;
887 const GVariantType *childtype;
888 GVariantBuilder builder;
889 gint i;
891 if (!g_variant_type_is_array (type))
892 return ast_type_error (ast, type, error);
894 g_variant_builder_init (&builder, type);
895 childtype = g_variant_type_element (type);
897 for (i = 0; i < array->n_children; i++)
899 GVariant *child;
901 if (!(child = ast_get_value (array->children[i], childtype, error)))
903 g_variant_builder_clear (&builder);
904 return NULL;
907 g_variant_builder_add_value (&builder, child);
910 return g_variant_builder_end (&builder);
913 static void
914 array_free (AST *ast)
916 Array *array = (Array *) ast;
918 ast_array_free (array->children, array->n_children);
919 g_slice_free (Array, array);
922 static AST *
923 array_parse (TokenStream *stream,
924 va_list *app,
925 GError **error)
927 static const ASTClass array_class = {
928 array_get_pattern,
929 maybe_wrapper, array_get_value,
930 array_free
932 gboolean need_comma = FALSE;
933 Array *array;
935 array = g_slice_new (Array);
936 array->ast.class = &array_class;
937 array->children = NULL;
938 array->n_children = 0;
940 token_stream_assert (stream, "[");
941 while (!token_stream_consume (stream, "]"))
943 AST *child;
945 if (need_comma &&
946 !token_stream_require (stream, ",",
947 " or `]' to follow array element",
948 error))
949 goto error;
951 child = parse (stream, app, error);
953 if (!child)
954 goto error;
956 ast_array_append (&array->children, &array->n_children, child);
957 need_comma = TRUE;
960 return (AST *) array;
962 error:
963 ast_array_free (array->children, array->n_children);
964 g_slice_free (Array, array);
966 return NULL;
969 typedef struct
971 AST ast;
973 AST **children;
974 gint n_children;
975 } Tuple;
977 static gchar *
978 tuple_get_pattern (AST *ast,
979 GError **error)
981 Tuple *tuple = (Tuple *) ast;
982 gchar *result = NULL;
983 gchar **parts;
984 gint i;
986 parts = g_new (gchar *, tuple->n_children + 4);
987 parts[tuple->n_children + 1] = (gchar *) ")";
988 parts[tuple->n_children + 2] = NULL;
989 parts[0] = (gchar *) "M(";
991 for (i = 0; i < tuple->n_children; i++)
992 if (!(parts[i + 1] = ast_get_pattern (tuple->children[i], error)))
993 break;
995 if (i == tuple->n_children)
996 result = g_strjoinv ("", parts);
998 /* parts[0] should not be freed */
999 while (i)
1000 g_free (parts[i--]);
1001 g_free (parts);
1003 return result;
1006 static GVariant *
1007 tuple_get_value (AST *ast,
1008 const GVariantType *type,
1009 GError **error)
1011 Tuple *tuple = (Tuple *) ast;
1012 const GVariantType *childtype;
1013 GVariantBuilder builder;
1014 gint i;
1016 if (!g_variant_type_is_tuple (type))
1017 return ast_type_error (ast, type, error);
1019 g_variant_builder_init (&builder, type);
1020 childtype = g_variant_type_first (type);
1022 for (i = 0; i < tuple->n_children; i++)
1024 GVariant *child;
1026 if (childtype == NULL)
1028 g_variant_builder_clear (&builder);
1029 return ast_type_error (ast, type, error);
1032 if (!(child = ast_get_value (tuple->children[i], childtype, error)))
1034 g_variant_builder_clear (&builder);
1035 return FALSE;
1038 g_variant_builder_add_value (&builder, child);
1039 childtype = g_variant_type_next (childtype);
1042 if (childtype != NULL)
1044 g_variant_builder_clear (&builder);
1045 return ast_type_error (ast, type, error);
1048 return g_variant_builder_end (&builder);
1051 static void
1052 tuple_free (AST *ast)
1054 Tuple *tuple = (Tuple *) ast;
1056 ast_array_free (tuple->children, tuple->n_children);
1057 g_slice_free (Tuple, tuple);
1060 static AST *
1061 tuple_parse (TokenStream *stream,
1062 va_list *app,
1063 GError **error)
1065 static const ASTClass tuple_class = {
1066 tuple_get_pattern,
1067 maybe_wrapper, tuple_get_value,
1068 tuple_free
1070 gboolean need_comma = FALSE;
1071 gboolean first = TRUE;
1072 Tuple *tuple;
1074 tuple = g_slice_new (Tuple);
1075 tuple->ast.class = &tuple_class;
1076 tuple->children = NULL;
1077 tuple->n_children = 0;
1079 token_stream_assert (stream, "(");
1080 while (!token_stream_consume (stream, ")"))
1082 AST *child;
1084 if (need_comma &&
1085 !token_stream_require (stream, ",",
1086 " or `)' to follow tuple element",
1087 error))
1088 goto error;
1090 child = parse (stream, app, error);
1092 if (!child)
1093 goto error;
1095 ast_array_append (&tuple->children, &tuple->n_children, child);
1097 /* the first time, we absolutely require a comma, so grab it here
1098 * and leave need_comma = FALSE so that the code above doesn't
1099 * require a second comma.
1101 * the second and remaining times, we set need_comma = TRUE.
1103 if (first)
1105 if (!token_stream_require (stream, ",",
1106 " after first tuple element", error))
1107 goto error;
1109 first = FALSE;
1111 else
1112 need_comma = TRUE;
1115 return (AST *) tuple;
1117 error:
1118 ast_array_free (tuple->children, tuple->n_children);
1119 g_slice_free (Tuple, tuple);
1121 return NULL;
1124 typedef struct
1126 AST ast;
1128 AST *value;
1129 } Variant;
1131 static gchar *
1132 variant_get_pattern (AST *ast,
1133 GError **error)
1135 return g_strdup ("Mv");
1138 static GVariant *
1139 variant_get_value (AST *ast,
1140 const GVariantType *type,
1141 GError **error)
1143 Variant *variant = (Variant *) ast;
1144 GVariant *child;
1146 if (!g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
1147 return ast_type_error (ast, type, error);
1149 child = ast_resolve (variant->value, error);
1151 if (child == NULL)
1152 return NULL;
1154 return g_variant_new_variant (child);
1157 static void
1158 variant_free (AST *ast)
1160 Variant *variant = (Variant *) ast;
1162 ast_free (variant->value);
1163 g_slice_free (Variant, variant);
1166 static AST *
1167 variant_parse (TokenStream *stream,
1168 va_list *app,
1169 GError **error)
1171 static const ASTClass variant_class = {
1172 variant_get_pattern,
1173 maybe_wrapper, variant_get_value,
1174 variant_free
1176 Variant *variant;
1177 AST *value;
1179 token_stream_assert (stream, "<");
1180 value = parse (stream, app, error);
1182 if (!value)
1183 return NULL;
1185 if (!token_stream_require (stream, ">", " to follow variant value", error))
1187 ast_free (value);
1188 return NULL;
1191 variant = g_slice_new (Variant);
1192 variant->ast.class = &variant_class;
1193 variant->value = value;
1195 return (AST *) variant;
1198 typedef struct
1200 AST ast;
1202 AST **keys;
1203 AST **values;
1204 gint n_children;
1205 } Dictionary;
1207 static gchar *
1208 dictionary_get_pattern (AST *ast,
1209 GError **error)
1211 Dictionary *dict = (Dictionary *) ast;
1212 gchar *value_pattern;
1213 gchar *key_pattern;
1214 gchar key_char;
1215 gchar *result;
1217 if (dict->n_children == 0)
1218 return g_strdup ("Ma{**}");
1220 key_pattern = ast_array_get_pattern (dict->keys,
1221 abs (dict->n_children),
1222 error);
1224 if (key_pattern == NULL)
1225 return NULL;
1227 /* we can not have maybe keys */
1228 if (key_pattern[0] == 'M')
1229 key_char = key_pattern[1];
1230 else
1231 key_char = key_pattern[0];
1233 g_free (key_pattern);
1235 /* the basic types,
1236 * plus undetermined number type and undetermined string type.
1238 if (!strchr ("bynqiuxthdsogNS", key_char))
1240 ast_set_error (ast, error, NULL,
1241 G_VARIANT_PARSE_ERROR_BASIC_TYPE_EXPECTED,
1242 "dictionary keys must have basic types");
1243 return NULL;
1246 value_pattern = ast_get_pattern (dict->values[0], error);
1248 if (value_pattern == NULL)
1249 return NULL;
1251 result = g_strdup_printf ("M%s{%c%s}",
1252 dict->n_children > 0 ? "a" : "",
1253 key_char, value_pattern);
1254 g_free (value_pattern);
1256 return result;
1259 static GVariant *
1260 dictionary_get_value (AST *ast,
1261 const GVariantType *type,
1262 GError **error)
1264 Dictionary *dict = (Dictionary *) ast;
1266 if (dict->n_children == -1)
1268 const GVariantType *subtype;
1269 GVariantBuilder builder;
1270 GVariant *subvalue;
1272 if (!g_variant_type_is_dict_entry (type))
1273 return ast_type_error (ast, type, error);
1275 g_variant_builder_init (&builder, type);
1277 subtype = g_variant_type_key (type);
1278 if (!(subvalue = ast_get_value (dict->keys[0], subtype, error)))
1280 g_variant_builder_clear (&builder);
1281 return NULL;
1283 g_variant_builder_add_value (&builder, subvalue);
1285 subtype = g_variant_type_value (type);
1286 if (!(subvalue = ast_get_value (dict->values[0], subtype, error)))
1288 g_variant_builder_clear (&builder);
1289 return NULL;
1291 g_variant_builder_add_value (&builder, subvalue);
1293 return g_variant_builder_end (&builder);
1295 else
1297 const GVariantType *entry, *key, *val;
1298 GVariantBuilder builder;
1299 gint i;
1301 if (!g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_DICTIONARY))
1302 return ast_type_error (ast, type, error);
1304 entry = g_variant_type_element (type);
1305 key = g_variant_type_key (entry);
1306 val = g_variant_type_value (entry);
1308 g_variant_builder_init (&builder, type);
1310 for (i = 0; i < dict->n_children; i++)
1312 GVariant *subvalue;
1314 g_variant_builder_open (&builder, entry);
1316 if (!(subvalue = ast_get_value (dict->keys[i], key, error)))
1318 g_variant_builder_clear (&builder);
1319 return NULL;
1321 g_variant_builder_add_value (&builder, subvalue);
1323 if (!(subvalue = ast_get_value (dict->values[i], val, error)))
1325 g_variant_builder_clear (&builder);
1326 return NULL;
1328 g_variant_builder_add_value (&builder, subvalue);
1329 g_variant_builder_close (&builder);
1332 return g_variant_builder_end (&builder);
1336 static void
1337 dictionary_free (AST *ast)
1339 Dictionary *dict = (Dictionary *) ast;
1340 gint n_children;
1342 if (dict->n_children > -1)
1343 n_children = dict->n_children;
1344 else
1345 n_children = 1;
1347 ast_array_free (dict->keys, n_children);
1348 ast_array_free (dict->values, n_children);
1349 g_slice_free (Dictionary, dict);
1352 static AST *
1353 dictionary_parse (TokenStream *stream,
1354 va_list *app,
1355 GError **error)
1357 static const ASTClass dictionary_class = {
1358 dictionary_get_pattern,
1359 maybe_wrapper, dictionary_get_value,
1360 dictionary_free
1362 gint n_keys, n_values;
1363 gboolean only_one;
1364 Dictionary *dict;
1365 AST *first;
1367 dict = g_slice_new (Dictionary);
1368 dict->ast.class = &dictionary_class;
1369 dict->keys = NULL;
1370 dict->values = NULL;
1371 n_keys = n_values = 0;
1373 token_stream_assert (stream, "{");
1375 if (token_stream_consume (stream, "}"))
1377 dict->n_children = 0;
1378 return (AST *) dict;
1381 if ((first = parse (stream, app, error)) == NULL)
1382 goto error;
1384 ast_array_append (&dict->keys, &n_keys, first);
1386 only_one = token_stream_consume (stream, ",");
1387 if (!only_one &&
1388 !token_stream_require (stream, ":",
1389 " or `,' to follow dictionary entry key",
1390 error))
1391 goto error;
1393 if ((first = parse (stream, app, error)) == NULL)
1394 goto error;
1396 ast_array_append (&dict->values, &n_values, first);
1398 if (only_one)
1400 if (!token_stream_require (stream, "}", " at end of dictionary entry",
1401 error))
1402 goto error;
1404 g_assert (n_keys == 1 && n_values == 1);
1405 dict->n_children = -1;
1407 return (AST *) dict;
1410 while (!token_stream_consume (stream, "}"))
1412 AST *child;
1414 if (!token_stream_require (stream, ",",
1415 " or `}' to follow dictionary entry", error))
1416 goto error;
1418 child = parse (stream, app, error);
1420 if (!child)
1421 goto error;
1423 ast_array_append (&dict->keys, &n_keys, child);
1425 if (!token_stream_require (stream, ":",
1426 " to follow dictionary entry key", error))
1427 goto error;
1429 child = parse (stream, app, error);
1431 if (!child)
1432 goto error;
1434 ast_array_append (&dict->values, &n_values, child);
1437 g_assert (n_keys == n_values);
1438 dict->n_children = n_keys;
1440 return (AST *) dict;
1442 error:
1443 ast_array_free (dict->keys, n_keys);
1444 ast_array_free (dict->values, n_values);
1445 g_slice_free (Dictionary, dict);
1447 return NULL;
1450 typedef struct
1452 AST ast;
1453 gchar *string;
1454 } String;
1456 static gchar *
1457 string_get_pattern (AST *ast,
1458 GError **error)
1460 return g_strdup ("MS");
1463 static GVariant *
1464 string_get_value (AST *ast,
1465 const GVariantType *type,
1466 GError **error)
1468 String *string = (String *) ast;
1470 if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
1471 return g_variant_new_string (string->string);
1473 else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
1475 if (!g_variant_is_object_path (string->string))
1477 ast_set_error (ast, error, NULL,
1478 G_VARIANT_PARSE_ERROR_INVALID_OBJECT_PATH,
1479 "not a valid object path");
1480 return NULL;
1483 return g_variant_new_object_path (string->string);
1486 else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
1488 if (!g_variant_is_signature (string->string))
1490 ast_set_error (ast, error, NULL,
1491 G_VARIANT_PARSE_ERROR_INVALID_SIGNATURE,
1492 "not a valid signature");
1493 return NULL;
1496 return g_variant_new_signature (string->string);
1499 else
1500 return ast_type_error (ast, type, error);
1503 static void
1504 string_free (AST *ast)
1506 String *string = (String *) ast;
1508 g_free (string->string);
1509 g_slice_free (String, string);
1512 static gboolean
1513 unicode_unescape (const gchar *src,
1514 gint *src_ofs,
1515 gchar *dest,
1516 gint *dest_ofs,
1517 gint length,
1518 SourceRef *ref,
1519 GError **error)
1521 gchar buffer[9];
1522 guint64 value;
1523 gchar *end;
1525 (*src_ofs)++;
1527 g_assert (length < sizeof (buffer));
1528 strncpy (buffer, src + *src_ofs, length);
1529 buffer[length] = '\0';
1531 value = g_ascii_strtoull (buffer, &end, 0x10);
1533 if (value == 0 || end != buffer + length)
1535 parser_set_error (error, ref, NULL,
1536 G_VARIANT_PARSE_ERROR_INVALID_CHARACTER,
1537 "invalid %d-character unicode escape", length);
1538 return FALSE;
1541 g_assert (value <= G_MAXUINT32);
1543 *dest_ofs += g_unichar_to_utf8 (value, dest + *dest_ofs);
1544 *src_ofs += length;
1546 return TRUE;
1549 static AST *
1550 string_parse (TokenStream *stream,
1551 va_list *app,
1552 GError **error)
1554 static const ASTClass string_class = {
1555 string_get_pattern,
1556 maybe_wrapper, string_get_value,
1557 string_free
1559 String *string;
1560 SourceRef ref;
1561 gchar *token;
1562 gsize length;
1563 gchar quote;
1564 gchar *str;
1565 gint i, j;
1567 token_stream_start_ref (stream, &ref);
1568 token = token_stream_get (stream);
1569 token_stream_end_ref (stream, &ref);
1570 length = strlen (token);
1571 quote = token[0];
1573 str = g_malloc (length);
1574 g_assert (quote == '"' || quote == '\'');
1575 j = 0;
1576 i = 1;
1577 while (token[i] != quote)
1578 switch (token[i])
1580 case '\0':
1581 parser_set_error (error, &ref, NULL,
1582 G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1583 "unterminated string constant");
1584 g_free (token);
1585 g_free (str);
1586 return NULL;
1588 case '\\':
1589 switch (token[++i])
1591 case '\0':
1592 parser_set_error (error, &ref, NULL,
1593 G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1594 "unterminated string constant");
1595 g_free (token);
1596 g_free (str);
1597 return NULL;
1599 case 'u':
1600 if (!unicode_unescape (token, &i, str, &j, 4, &ref, error))
1602 g_free (token);
1603 g_free (str);
1604 return NULL;
1606 continue;
1608 case 'U':
1609 if (!unicode_unescape (token, &i, str, &j, 8, &ref, error))
1611 g_free (token);
1612 g_free (str);
1613 return NULL;
1615 continue;
1617 case 'a': str[j++] = '\a'; i++; continue;
1618 case 'b': str[j++] = '\b'; i++; continue;
1619 case 'f': str[j++] = '\f'; i++; continue;
1620 case 'n': str[j++] = '\n'; i++; continue;
1621 case 'r': str[j++] = '\r'; i++; continue;
1622 case 't': str[j++] = '\t'; i++; continue;
1623 case 'v': str[j++] = '\v'; i++; continue;
1624 case '\n': i++; continue;
1627 default:
1628 str[j++] = token[i++];
1630 str[j++] = '\0';
1631 g_free (token);
1633 string = g_slice_new (String);
1634 string->ast.class = &string_class;
1635 string->string = str;
1637 token_stream_next (stream);
1639 return (AST *) string;
1642 typedef struct
1644 AST ast;
1645 gchar *string;
1646 } ByteString;
1648 static gchar *
1649 bytestring_get_pattern (AST *ast,
1650 GError **error)
1652 return g_strdup ("May");
1655 static GVariant *
1656 bytestring_get_value (AST *ast,
1657 const GVariantType *type,
1658 GError **error)
1660 ByteString *string = (ByteString *) ast;
1662 if (!g_variant_type_equal (type, G_VARIANT_TYPE_BYTESTRING))
1663 return ast_type_error (ast, type, error);
1665 return g_variant_new_bytestring (string->string);
1668 static void
1669 bytestring_free (AST *ast)
1671 ByteString *string = (ByteString *) ast;
1673 g_free (string->string);
1674 g_slice_free (ByteString, string);
1677 static AST *
1678 bytestring_parse (TokenStream *stream,
1679 va_list *app,
1680 GError **error)
1682 static const ASTClass bytestring_class = {
1683 bytestring_get_pattern,
1684 maybe_wrapper, bytestring_get_value,
1685 bytestring_free
1687 ByteString *string;
1688 SourceRef ref;
1689 gchar *token;
1690 gsize length;
1691 gchar quote;
1692 gchar *str;
1693 gint i, j;
1695 token_stream_start_ref (stream, &ref);
1696 token = token_stream_get (stream);
1697 token_stream_end_ref (stream, &ref);
1698 g_assert (token[0] == 'b');
1699 length = strlen (token);
1700 quote = token[1];
1702 str = g_malloc (length);
1703 g_assert (quote == '"' || quote == '\'');
1704 j = 0;
1705 i = 2;
1706 while (token[i] != quote)
1707 switch (token[i])
1709 case '\0':
1710 parser_set_error (error, &ref, NULL,
1711 G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1712 "unterminated string constant");
1713 g_free (token);
1714 return NULL;
1716 case '\\':
1717 switch (token[++i])
1719 case '\0':
1720 parser_set_error (error, &ref, NULL,
1721 G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1722 "unterminated string constant");
1723 g_free (token);
1724 return NULL;
1726 case '0': case '1': case '2': case '3':
1727 case '4': case '5': case '6': case '7':
1729 /* up to 3 characters */
1730 guchar val = token[i++] - '0';
1732 if ('0' <= token[i] && token[i] < '8')
1733 val = (val << 3) | (token[i++] - '0');
1735 if ('0' <= token[i] && token[i] < '8')
1736 val = (val << 3) | (token[i++] - '0');
1738 str[j++] = val;
1740 continue;
1742 case 'a': str[j++] = '\a'; i++; continue;
1743 case 'b': str[j++] = '\b'; i++; continue;
1744 case 'f': str[j++] = '\f'; i++; continue;
1745 case 'n': str[j++] = '\n'; i++; continue;
1746 case 'r': str[j++] = '\r'; i++; continue;
1747 case 't': str[j++] = '\t'; i++; continue;
1748 case 'v': str[j++] = '\v'; i++; continue;
1749 case '\n': i++; continue;
1752 default:
1753 str[j++] = token[i++];
1755 str[j++] = '\0';
1756 g_free (token);
1758 string = g_slice_new (ByteString);
1759 string->ast.class = &bytestring_class;
1760 string->string = str;
1762 token_stream_next (stream);
1764 return (AST *) string;
1767 typedef struct
1769 AST ast;
1771 gchar *token;
1772 } Number;
1774 static gchar *
1775 number_get_pattern (AST *ast,
1776 GError **error)
1778 Number *number = (Number *) ast;
1780 if (strchr (number->token, '.') ||
1781 (!g_str_has_prefix (number->token, "0x") && strchr (number->token, 'e')) ||
1782 strstr (number->token, "inf") ||
1783 strstr (number->token, "nan"))
1784 return g_strdup ("Md");
1786 return g_strdup ("MN");
1789 static GVariant *
1790 number_overflow (AST *ast,
1791 const GVariantType *type,
1792 GError **error)
1794 ast_set_error (ast, error, NULL,
1795 G_VARIANT_PARSE_ERROR_NUMBER_OUT_OF_RANGE,
1796 "number out of range for type `%c'",
1797 g_variant_type_peek_string (type)[0]);
1798 return NULL;
1801 static GVariant *
1802 number_get_value (AST *ast,
1803 const GVariantType *type,
1804 GError **error)
1806 Number *number = (Number *) ast;
1807 const gchar *token;
1808 gboolean negative;
1809 gboolean floating;
1810 guint64 abs_val;
1811 gdouble dbl_val;
1812 gchar *end;
1814 token = number->token;
1816 if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
1818 floating = TRUE;
1820 errno = 0;
1821 dbl_val = g_ascii_strtod (token, &end);
1822 if (dbl_val != 0.0 && errno == ERANGE)
1824 ast_set_error (ast, error, NULL,
1825 G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG,
1826 "number too big for any type");
1827 return NULL;
1830 /* silence uninitialised warnings... */
1831 negative = FALSE;
1832 abs_val = 0;
1834 else
1836 floating = FALSE;
1837 negative = token[0] == '-';
1838 if (token[0] == '-')
1839 token++;
1841 errno = 0;
1842 abs_val = g_ascii_strtoull (token, &end, 0);
1843 if (abs_val == G_MAXUINT64 && errno == ERANGE)
1845 ast_set_error (ast, error, NULL,
1846 G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG,
1847 "integer too big for any type");
1848 return NULL;
1851 if (abs_val == 0)
1852 negative = FALSE;
1854 /* silence uninitialised warning... */
1855 dbl_val = 0.0;
1858 if (*end != '\0')
1860 SourceRef ref;
1862 ref = ast->source_ref;
1863 ref.start += end - number->token;
1864 ref.end = ref.start + 1;
1866 parser_set_error (error, &ref, NULL,
1867 G_VARIANT_PARSE_ERROR_INVALID_CHARACTER,
1868 "invalid character in number");
1869 return NULL;
1872 if (floating)
1873 return g_variant_new_double (dbl_val);
1875 switch (*g_variant_type_peek_string (type))
1877 case 'y':
1878 if (negative || abs_val > G_MAXUINT8)
1879 return number_overflow (ast, type, error);
1880 return g_variant_new_byte (abs_val);
1882 case 'n':
1883 if (abs_val - negative > G_MAXINT16)
1884 return number_overflow (ast, type, error);
1885 return g_variant_new_int16 (negative ? -abs_val : abs_val);
1887 case 'q':
1888 if (negative || abs_val > G_MAXUINT16)
1889 return number_overflow (ast, type, error);
1890 return g_variant_new_uint16 (abs_val);
1892 case 'i':
1893 if (abs_val - negative > G_MAXINT32)
1894 return number_overflow (ast, type, error);
1895 return g_variant_new_int32 (negative ? -abs_val : abs_val);
1897 case 'u':
1898 if (negative || abs_val > G_MAXUINT32)
1899 return number_overflow (ast, type, error);
1900 return g_variant_new_uint32 (abs_val);
1902 case 'x':
1903 if (abs_val - negative > G_MAXINT64)
1904 return number_overflow (ast, type, error);
1905 return g_variant_new_int64 (negative ? -abs_val : abs_val);
1907 case 't':
1908 if (negative)
1909 return number_overflow (ast, type, error);
1910 return g_variant_new_uint64 (abs_val);
1912 case 'h':
1913 if (abs_val - negative > G_MAXINT32)
1914 return number_overflow (ast, type, error);
1915 return g_variant_new_handle (negative ? -abs_val : abs_val);
1917 default:
1918 return ast_type_error (ast, type, error);
1922 static void
1923 number_free (AST *ast)
1925 Number *number = (Number *) ast;
1927 g_free (number->token);
1928 g_slice_free (Number, number);
1931 static AST *
1932 number_parse (TokenStream *stream,
1933 va_list *app,
1934 GError **error)
1936 static const ASTClass number_class = {
1937 number_get_pattern,
1938 maybe_wrapper, number_get_value,
1939 number_free
1941 Number *number;
1943 number = g_slice_new (Number);
1944 number->ast.class = &number_class;
1945 number->token = token_stream_get (stream);
1946 token_stream_next (stream);
1948 return (AST *) number;
1951 typedef struct
1953 AST ast;
1954 gboolean value;
1955 } Boolean;
1957 static gchar *
1958 boolean_get_pattern (AST *ast,
1959 GError **error)
1961 return g_strdup ("Mb");
1964 static GVariant *
1965 boolean_get_value (AST *ast,
1966 const GVariantType *type,
1967 GError **error)
1969 Boolean *boolean = (Boolean *) ast;
1971 if (!g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
1972 return ast_type_error (ast, type, error);
1974 return g_variant_new_boolean (boolean->value);
1977 static void
1978 boolean_free (AST *ast)
1980 Boolean *boolean = (Boolean *) ast;
1982 g_slice_free (Boolean, boolean);
1985 static AST *
1986 boolean_new (gboolean value)
1988 static const ASTClass boolean_class = {
1989 boolean_get_pattern,
1990 maybe_wrapper, boolean_get_value,
1991 boolean_free
1993 Boolean *boolean;
1995 boolean = g_slice_new (Boolean);
1996 boolean->ast.class = &boolean_class;
1997 boolean->value = value;
1999 return (AST *) boolean;
2002 typedef struct
2004 AST ast;
2006 GVariant *value;
2007 } Positional;
2009 static gchar *
2010 positional_get_pattern (AST *ast,
2011 GError **error)
2013 Positional *positional = (Positional *) ast;
2015 return g_strdup (g_variant_get_type_string (positional->value));
2018 static GVariant *
2019 positional_get_value (AST *ast,
2020 const GVariantType *type,
2021 GError **error)
2023 Positional *positional = (Positional *) ast;
2024 GVariant *value;
2026 g_assert (positional->value != NULL);
2028 if G_UNLIKELY (!g_variant_is_of_type (positional->value, type))
2029 return ast_type_error (ast, type, error);
2031 /* NOTE: if _get is called more than once then
2032 * things get messed up with respect to floating refs.
2034 * fortunately, this function should only ever get called once.
2036 g_assert (positional->value != NULL);
2037 value = positional->value;
2038 positional->value = NULL;
2040 return value;
2043 static void
2044 positional_free (AST *ast)
2046 Positional *positional = (Positional *) ast;
2048 /* if positional->value is set, just leave it.
2049 * memory management doesn't matter in case of programmer error.
2051 g_slice_free (Positional, positional);
2054 static AST *
2055 positional_parse (TokenStream *stream,
2056 va_list *app,
2057 GError **error)
2059 static const ASTClass positional_class = {
2060 positional_get_pattern,
2061 positional_get_value, NULL,
2062 positional_free
2064 Positional *positional;
2065 const gchar *endptr;
2066 gchar *token;
2068 token = token_stream_get (stream);
2069 g_assert (token[0] == '%');
2071 positional = g_slice_new (Positional);
2072 positional->ast.class = &positional_class;
2073 positional->value = g_variant_new_va (token + 1, &endptr, app);
2075 if (*endptr || positional->value == NULL)
2077 token_stream_set_error (stream, error, TRUE,
2078 G_VARIANT_PARSE_ERROR_INVALID_FORMAT_STRING,
2079 "invalid GVariant format string");
2080 /* memory management doesn't matter in case of programmer error. */
2081 return NULL;
2084 token_stream_next (stream);
2085 g_free (token);
2087 return (AST *) positional;
2090 typedef struct
2092 AST ast;
2094 GVariantType *type;
2095 AST *child;
2096 } TypeDecl;
2098 static gchar *
2099 typedecl_get_pattern (AST *ast,
2100 GError **error)
2102 TypeDecl *decl = (TypeDecl *) ast;
2104 return g_variant_type_dup_string (decl->type);
2107 static GVariant *
2108 typedecl_get_value (AST *ast,
2109 const GVariantType *type,
2110 GError **error)
2112 TypeDecl *decl = (TypeDecl *) ast;
2114 return ast_get_value (decl->child, type, error);
2117 static void
2118 typedecl_free (AST *ast)
2120 TypeDecl *decl = (TypeDecl *) ast;
2122 ast_free (decl->child);
2123 g_variant_type_free (decl->type);
2124 g_slice_free (TypeDecl, decl);
2127 static AST *
2128 typedecl_parse (TokenStream *stream,
2129 va_list *app,
2130 GError **error)
2132 static const ASTClass typedecl_class = {
2133 typedecl_get_pattern,
2134 typedecl_get_value, NULL,
2135 typedecl_free
2137 GVariantType *type;
2138 TypeDecl *decl;
2139 AST *child;
2141 if (token_stream_peek (stream, '@'))
2143 gchar *token;
2145 token = token_stream_get (stream);
2147 if (!g_variant_type_string_is_valid (token + 1))
2149 token_stream_set_error (stream, error, TRUE,
2150 G_VARIANT_PARSE_ERROR_INVALID_TYPE_STRING,
2151 "invalid type declaration");
2152 g_free (token);
2154 return NULL;
2157 type = g_variant_type_new (token + 1);
2159 if (!g_variant_type_is_definite (type))
2161 token_stream_set_error (stream, error, TRUE,
2162 G_VARIANT_PARSE_ERROR_DEFINITE_TYPE_EXPECTED,
2163 "type declarations must be definite");
2164 g_variant_type_free (type);
2165 g_free (token);
2167 return NULL;
2170 token_stream_next (stream);
2171 g_free (token);
2173 else
2175 if (token_stream_consume (stream, "boolean"))
2176 type = g_variant_type_copy (G_VARIANT_TYPE_BOOLEAN);
2178 else if (token_stream_consume (stream, "byte"))
2179 type = g_variant_type_copy (G_VARIANT_TYPE_BYTE);
2181 else if (token_stream_consume (stream, "int16"))
2182 type = g_variant_type_copy (G_VARIANT_TYPE_INT16);
2184 else if (token_stream_consume (stream, "uint16"))
2185 type = g_variant_type_copy (G_VARIANT_TYPE_UINT16);
2187 else if (token_stream_consume (stream, "int32"))
2188 type = g_variant_type_copy (G_VARIANT_TYPE_INT32);
2190 else if (token_stream_consume (stream, "handle"))
2191 type = g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
2193 else if (token_stream_consume (stream, "uint32"))
2194 type = g_variant_type_copy (G_VARIANT_TYPE_UINT32);
2196 else if (token_stream_consume (stream, "int64"))
2197 type = g_variant_type_copy (G_VARIANT_TYPE_INT64);
2199 else if (token_stream_consume (stream, "uint64"))
2200 type = g_variant_type_copy (G_VARIANT_TYPE_UINT64);
2202 else if (token_stream_consume (stream, "double"))
2203 type = g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
2205 else if (token_stream_consume (stream, "string"))
2206 type = g_variant_type_copy (G_VARIANT_TYPE_STRING);
2208 else if (token_stream_consume (stream, "objectpath"))
2209 type = g_variant_type_copy (G_VARIANT_TYPE_OBJECT_PATH);
2211 else if (token_stream_consume (stream, "signature"))
2212 type = g_variant_type_copy (G_VARIANT_TYPE_SIGNATURE);
2214 else
2216 token_stream_set_error (stream, error, TRUE,
2217 G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD,
2218 "unknown keyword");
2219 return NULL;
2223 if ((child = parse (stream, app, error)) == NULL)
2225 g_variant_type_free (type);
2226 return NULL;
2229 decl = g_slice_new (TypeDecl);
2230 decl->ast.class = &typedecl_class;
2231 decl->type = type;
2232 decl->child = child;
2234 return (AST *) decl;
2237 static AST *
2238 parse (TokenStream *stream,
2239 va_list *app,
2240 GError **error)
2242 SourceRef source_ref;
2243 AST *result;
2245 token_stream_prepare (stream);
2246 token_stream_start_ref (stream, &source_ref);
2248 if (token_stream_peek (stream, '['))
2249 result = array_parse (stream, app, error);
2251 else if (token_stream_peek (stream, '('))
2252 result = tuple_parse (stream, app, error);
2254 else if (token_stream_peek (stream, '<'))
2255 result = variant_parse (stream, app, error);
2257 else if (token_stream_peek (stream, '{'))
2258 result = dictionary_parse (stream, app, error);
2260 else if (app && token_stream_peek (stream, '%'))
2261 result = positional_parse (stream, app, error);
2263 else if (token_stream_consume (stream, "true"))
2264 result = boolean_new (TRUE);
2266 else if (token_stream_consume (stream, "false"))
2267 result = boolean_new (FALSE);
2269 else if (token_stream_is_numeric (stream) ||
2270 token_stream_peek_string (stream, "inf") ||
2271 token_stream_peek_string (stream, "nan"))
2272 result = number_parse (stream, app, error);
2274 else if (token_stream_peek (stream, 'n') ||
2275 token_stream_peek (stream, 'j'))
2276 result = maybe_parse (stream, app, error);
2278 else if (token_stream_peek (stream, '@') ||
2279 token_stream_is_keyword (stream))
2280 result = typedecl_parse (stream, app, error);
2282 else if (token_stream_peek (stream, '\'') ||
2283 token_stream_peek (stream, '"'))
2284 result = string_parse (stream, app, error);
2286 else if (token_stream_peek2 (stream, 'b', '\'') ||
2287 token_stream_peek2 (stream, 'b', '"'))
2288 result = bytestring_parse (stream, app, error);
2290 else
2292 token_stream_set_error (stream, error, FALSE,
2293 G_VARIANT_PARSE_ERROR_VALUE_EXPECTED,
2294 "expected value");
2295 return NULL;
2298 if (result != NULL)
2300 token_stream_end_ref (stream, &source_ref);
2301 result->source_ref = source_ref;
2304 return result;
2308 * g_variant_parse:
2309 * @type: (allow-none): a #GVariantType, or %NULL
2310 * @text: a string containing a GVariant in text form
2311 * @limit: (allow-none): a pointer to the end of @text, or %NULL
2312 * @endptr: (allow-none): a location to store the end pointer, or %NULL
2313 * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
2315 * Parses a #GVariant from a text representation.
2317 * A single #GVariant is parsed from the content of @text.
2319 * The format is described <link linkend='gvariant-text'>here</link>.
2321 * The memory at @limit will never be accessed and the parser behaves as
2322 * if the character at @limit is the nul terminator. This has the
2323 * effect of bounding @text.
2325 * If @endptr is non-%NULL then @text is permitted to contain data
2326 * following the value that this function parses and @endptr will be
2327 * updated to point to the first character past the end of the text
2328 * parsed by this function. If @endptr is %NULL and there is extra data
2329 * then an error is returned.
2331 * If @type is non-%NULL then the value will be parsed to have that
2332 * type. This may result in additional parse errors (in the case that
2333 * the parsed value doesn't fit the type) but may also result in fewer
2334 * errors (in the case that the type would have been ambiguous, such as
2335 * with empty arrays).
2337 * In the event that the parsing is successful, the resulting #GVariant
2338 * is returned.
2340 * In case of any error, %NULL will be returned. If @error is non-%NULL
2341 * then it will be set to reflect the error that occurred.
2343 * Officially, the language understood by the parser is "any string
2344 * produced by g_variant_print()".
2346 * Returns: a reference to a #GVariant, or %NULL
2348 GVariant *
2349 g_variant_parse (const GVariantType *type,
2350 const gchar *text,
2351 const gchar *limit,
2352 const gchar **endptr,
2353 GError **error)
2355 TokenStream stream = { 0, };
2356 GVariant *result = NULL;
2357 AST *ast;
2359 g_return_val_if_fail (text != NULL, NULL);
2360 g_return_val_if_fail (text == limit || text != NULL, NULL);
2362 stream.start = text;
2363 stream.stream = text;
2364 stream.end = limit;
2366 if ((ast = parse (&stream, NULL, error)))
2368 if (type == NULL)
2369 result = ast_resolve (ast, error);
2370 else
2371 result = ast_get_value (ast, type, error);
2373 if (result != NULL)
2375 g_variant_ref_sink (result);
2377 if (endptr == NULL)
2379 while (stream.stream != limit &&
2380 g_ascii_isspace (*stream.stream))
2381 stream.stream++;
2383 if (stream.stream != limit && *stream.stream != '\0')
2385 SourceRef ref = { stream.stream - text,
2386 stream.stream - text };
2388 parser_set_error (error, &ref, NULL,
2389 G_VARIANT_PARSE_ERROR_INPUT_NOT_AT_END,
2390 "expected end of input");
2391 g_variant_unref (result);
2393 result = NULL;
2396 else
2397 *endptr = stream.stream;
2400 ast_free (ast);
2403 return result;
2407 * g_variant_new_parsed_va:
2408 * @format: a text format #GVariant
2409 * @app: a pointer to a #va_list
2411 * Parses @format and returns the result.
2413 * This is the version of g_variant_new_parsed() intended to be used
2414 * from libraries.
2416 * The return value will be floating if it was a newly created GVariant
2417 * instance. In the case that @format simply specified the collection
2418 * of a #GVariant pointer (eg: @format was "%*") then the collected
2419 * #GVariant pointer will be returned unmodified, without adding any
2420 * additional references.
2422 * In order to behave correctly in all cases it is necessary for the
2423 * calling function to g_variant_ref_sink() the return result before
2424 * returning control to the user that originally provided the pointer.
2425 * At this point, the caller will have their own full reference to the
2426 * result. This can also be done by adding the result to a container,
2427 * or by passing it to another g_variant_new() call.
2429 * Returns: a new, usually floating, #GVariant
2431 GVariant *
2432 g_variant_new_parsed_va (const gchar *format,
2433 va_list *app)
2435 TokenStream stream = { 0, };
2436 GVariant *result = NULL;
2437 GError *error = NULL;
2438 AST *ast;
2440 g_return_val_if_fail (format != NULL, NULL);
2441 g_return_val_if_fail (app != NULL, NULL);
2443 stream.start = format;
2444 stream.stream = format;
2445 stream.end = NULL;
2447 if ((ast = parse (&stream, app, &error)))
2449 result = ast_resolve (ast, &error);
2450 ast_free (ast);
2453 if (result == NULL)
2454 g_error ("g_variant_new_parsed: %s", error->message);
2456 if (*stream.stream)
2457 g_error ("g_variant_new_parsed: trailing text after value");
2459 return result;
2463 * g_variant_new_parsed:
2464 * @format: a text format #GVariant
2465 * @...: arguments as per @format
2467 * Parses @format and returns the result.
2469 * @format must be a text format #GVariant with one extension: at any
2470 * point that a value may appear in the text, a '%' character followed
2471 * by a GVariant format string (as per g_variant_new()) may appear. In
2472 * that case, the same arguments are collected from the argument list as
2473 * g_variant_new() would have collected.
2475 * Consider this simple example:
2477 * <informalexample><programlisting>
2478 * g_variant_new_parsed ("[('one', 1), ('two', %i), (%s, 3)]", 2, "three");
2479 * </programlisting></informalexample>
2481 * In the example, the variable argument parameters are collected and
2482 * filled in as if they were part of the original string to produce the
2483 * result of <code>[('one', 1), ('two', 2), ('three', 3)]</code>.
2485 * This function is intended only to be used with @format as a string
2486 * literal. Any parse error is fatal to the calling process. If you
2487 * want to parse data from untrusted sources, use g_variant_parse().
2489 * You may not use this function to return, unmodified, a single
2490 * #GVariant pointer from the argument list. ie: @format may not solely
2491 * be anything along the lines of "%*", "%?", "\%r", or anything starting
2492 * with "%@".
2494 * Returns: a new floating #GVariant instance
2496 GVariant *
2497 g_variant_new_parsed (const gchar *format,
2498 ...)
2500 GVariant *result;
2501 va_list ap;
2503 va_start (ap, format);
2504 result = g_variant_new_parsed_va (format, &ap);
2505 va_end (ap);
2507 return result;
2511 * g_variant_builder_add_parsed:
2512 * @builder: a #GVariantBuilder
2513 * @format: a text format #GVariant
2514 * @...: arguments as per @format
2516 * Adds to a #GVariantBuilder.
2518 * This call is a convenience wrapper that is exactly equivalent to
2519 * calling g_variant_new_parsed() followed by
2520 * g_variant_builder_add_value().
2522 * This function might be used as follows:
2524 * <programlisting>
2525 * GVariant *
2526 * make_pointless_dictionary (void)
2528 * GVariantBuilder *builder;
2529 * int i;
2531 * builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
2532 * g_variant_builder_add_parsed (builder, "{'width', <%i>}", 600);
2533 * g_variant_builder_add_parsed (builder, "{'title', <%s>}", "foo");
2534 * g_variant_builder_add_parsed (builder, "{'transparency', <0.5>}");
2535 * return g_variant_builder_end (builder);
2537 * </programlisting>
2539 * Since: 2.26
2541 void
2542 g_variant_builder_add_parsed (GVariantBuilder *builder,
2543 const gchar *format,
2544 ...)
2546 va_list ap;
2548 va_start (ap, format);
2549 g_variant_builder_add_value (builder, g_variant_new_parsed_va (format, &ap));
2550 va_end (ap);