Imported Upstream version 2.58.0
[platform/upstream/glib.git] / glib / gvariant-parser.c
1 /*
2  * Copyright © 2009, 2010 Codethink Limited
3  *
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.
8  *
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.
13  *
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/>.
16  *
17  * Author: Ryan Lortie <desrt@desrt.ca>
18  */
19
20 #include "config.h"
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25
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"
35
36 /*
37  * two-pass algorithm
38  * designed by ryan lortie and william hua
39  * designed in itb-229 and at ghazi's, 2009.
40  */
41
42 /**
43  * G_VARIANT_PARSE_ERROR:
44  *
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
69  *
70  * Error codes returned by parsing text-format GVariants.
71  **/
72 G_DEFINE_QUARK (g-variant-parse-error-quark, g_variant_parse_error)
73
74 /**
75  * g_variant_parser_get_error_quark:
76  *
77  * Same as g_variant_error_quark().
78  *
79  * Deprecated: Use g_variant_parse_error_quark() instead.
80  */
81 GQuark
82 g_variant_parser_get_error_quark (void)
83 {
84   return g_variant_parse_error_quark ();
85 }
86
87 typedef struct
88 {
89   gint start, end;
90 } SourceRef;
91
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)
100 {
101   GString *msg = g_string_new (NULL);
102
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);
107
108   if (other != NULL)
109     {
110       g_assert (other->start != other->end);
111       g_string_append_printf (msg, ",%d-%d", other->start, other->end);
112     }
113   g_string_append_c (msg, ':');
114
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);
118 }
119
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                   ...)
128 {
129   va_list ap;
130
131   va_start (ap, format);
132   parser_set_error_va (error, location, other, code, format, ap);
133   va_end (ap);
134 }
135
136 typedef struct
137 {
138   const gchar *start;
139   const gchar *stream;
140   const gchar *end;
141
142   const gchar *this;
143 } TokenStream;
144
145
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                         ...)
154 {
155   SourceRef ref;
156   va_list ap;
157
158   ref.start = stream->this - stream->start;
159
160   if (this_token)
161     ref.end = stream->stream - stream->start;
162   else
163     ref.end = ref.start;
164
165   va_start (ap, format);
166   parser_set_error_va (error, &ref, NULL, code, format, ap);
167   va_end (ap);
168 }
169
170 static gboolean
171 token_stream_prepare (TokenStream *stream)
172 {
173   gint brackets = 0;
174   const gchar *end;
175
176   if (stream->this != NULL)
177     return TRUE;
178
179   while (stream->stream != stream->end && g_ascii_isspace (*stream->stream))
180     stream->stream++;
181
182   if (stream->stream == stream->end || *stream->stream == '\0')
183     {
184       stream->this = stream->stream;
185       return FALSE;
186     }
187
188   switch (stream->stream[0])
189     {
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;
198
199     case 'b':
200       if (stream->stream + 1 != stream->end &&
201           (stream->stream[1] == '\'' || stream->stream[1] == '"'))
202         {
203           for (end = stream->stream + 2; end != stream->end; end++)
204             if (*end == stream->stream[1] || *end == '\0' ||
205                 (*end == '\\' && (++end == stream->end || *end == '\0')))
206               break;
207
208           if (end != stream->end && *end)
209             end++;
210           break;
211         }
212
213       else
214         {
215           /* ↓↓↓ */
216         }
217
218     case 'a': /* 'b' */ case 'c': case 'd': case 'e': case 'f':
219     case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
220     case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
221     case 's': case 't': case 'u': case 'v': case 'w': case 'x':
222     case 'y': case 'z':
223       for (end = stream->stream; end != stream->end; end++)
224         if (!g_ascii_isalnum (*end))
225           break;
226       break;
227
228     case '\'': case '"':
229       for (end = stream->stream + 1; end != stream->end; end++)
230         if (*end == stream->stream[0] || *end == '\0' ||
231             (*end == '\\' && (++end == stream->end || *end == '\0')))
232           break;
233
234       if (end != stream->end && *end)
235         end++;
236       break;
237
238     case '@': case '%':
239       /* stop at the first space, comma, colon or unmatched bracket.
240        * deals nicely with cases like (%i, %i) or {%i: %i}.
241        * Also: ] and > are never in format strings.
242        */
243       for (end = stream->stream + 1;
244            end != stream->end && *end != '\0' && *end != ',' &&
245            *end != ':' && *end != '>' && *end != ']' && !g_ascii_isspace (*end);
246            end++)
247
248         if (*end == '(' || *end == '{')
249           brackets++;
250
251         else if ((*end == ')' || *end == '}') && !brackets--)
252           break;
253
254       break;
255
256     default:
257       end = stream->stream + 1;
258       break;
259     }
260
261   stream->this = stream->stream;
262   stream->stream = end;
263
264   /* We must have at least one byte in a token. */
265   g_assert (stream->stream - stream->this >= 1);
266
267   return TRUE;
268 }
269
270 static void
271 token_stream_next (TokenStream *stream)
272 {
273   stream->this = NULL;
274 }
275
276 static gboolean
277 token_stream_peek (TokenStream *stream,
278                    gchar        first_char)
279 {
280   if (!token_stream_prepare (stream))
281     return FALSE;
282
283   return stream->stream - stream->this >= 1 &&
284          stream->this[0] == first_char;
285 }
286
287 static gboolean
288 token_stream_peek2 (TokenStream *stream,
289                     gchar        first_char,
290                     gchar        second_char)
291 {
292   if (!token_stream_prepare (stream))
293     return FALSE;
294
295   return stream->stream - stream->this >= 2 &&
296          stream->this[0] == first_char &&
297          stream->this[1] == second_char;
298 }
299
300 static gboolean
301 token_stream_is_keyword (TokenStream *stream)
302 {
303   if (!token_stream_prepare (stream))
304     return FALSE;
305
306   return stream->stream - stream->this >= 2 &&
307          g_ascii_isalpha (stream->this[0]) &&
308          g_ascii_isalpha (stream->this[1]);
309 }
310
311 static gboolean
312 token_stream_is_numeric (TokenStream *stream)
313 {
314   if (!token_stream_prepare (stream))
315     return FALSE;
316
317   return (stream->stream - stream->this >= 1 &&
318           (g_ascii_isdigit (stream->this[0]) ||
319            stream->this[0] == '-' ||
320            stream->this[0] == '+' ||
321            stream->this[0] == '.'));
322 }
323
324 static gboolean
325 token_stream_peek_string (TokenStream *stream,
326                           const gchar *token)
327 {
328   gint length = strlen (token);
329
330   return token_stream_prepare (stream) &&
331          stream->stream - stream->this == length &&
332          memcmp (stream->this, token, length) == 0;
333 }
334
335 static gboolean
336 token_stream_consume (TokenStream *stream,
337                       const gchar *token)
338 {
339   if (!token_stream_peek_string (stream, token))
340     return FALSE;
341
342   token_stream_next (stream);
343   return TRUE;
344 }
345
346 static gboolean
347 token_stream_require (TokenStream  *stream,
348                       const gchar  *token,
349                       const gchar  *purpose,
350                       GError      **error)
351 {
352
353   if (!token_stream_consume (stream, token))
354     {
355       token_stream_set_error (stream, error, FALSE,
356                               G_VARIANT_PARSE_ERROR_UNEXPECTED_TOKEN,
357                               "expected '%s'%s", token, purpose);
358       return FALSE;
359     }
360
361   return TRUE;
362 }
363
364 static void
365 token_stream_assert (TokenStream *stream,
366                      const gchar *token)
367 {
368   gboolean correct_token;
369
370   correct_token = token_stream_consume (stream, token);
371   g_assert (correct_token);
372 }
373
374 static gchar *
375 token_stream_get (TokenStream *stream)
376 {
377   gchar *result;
378
379   if (!token_stream_prepare (stream))
380     return NULL;
381
382   result = g_strndup (stream->this, stream->stream - stream->this);
383
384   return result;
385 }
386
387 static void
388 token_stream_start_ref (TokenStream *stream,
389                         SourceRef   *ref)
390 {
391   token_stream_prepare (stream);
392   ref->start = stream->this - stream->start;
393 }
394
395 static void
396 token_stream_end_ref (TokenStream *stream,
397                       SourceRef   *ref)
398 {
399   ref->end = stream->stream - stream->start;
400 }
401
402 static void
403 pattern_copy (gchar       **out,
404               const gchar **in)
405 {
406   gint brackets = 0;
407
408   while (**in == 'a' || **in == 'm' || **in == 'M')
409     *(*out)++ = *(*in)++;
410
411   do
412     {
413       if (**in == '(' || **in == '{')
414         brackets++;
415
416       else if (**in == ')' || **in == '}')
417         brackets--;
418
419       *(*out)++ = *(*in)++;
420     }
421   while (brackets);
422 }
423
424 static gchar *
425 pattern_coalesce (const gchar *left,
426                   const gchar *right)
427 {
428   gchar *result;
429   gchar *out;
430
431   /* the length of the output is loosely bound by the sum of the input
432    * lengths, not simply the greater of the two lengths.
433    *
434    *   (*(iii)) + ((iii)*) ((iii)(iii))
435    *
436    *      8     +    8    =  12
437    */
438   out = result = g_malloc (strlen (left) + strlen (right));
439
440   while (*left && *right)
441     {
442       if (*left == *right)
443         {
444           *out++ = *left++;
445           right++;
446         }
447
448       else
449         {
450           const gchar **one = &left, **the_other = &right;
451
452          again:
453           if (**one == '*' && **the_other != ')')
454             {
455               pattern_copy (&out, the_other);
456               (*one)++;
457             }
458
459           else if (**one == 'M' && **the_other == 'm')
460             {
461               *out++ = *(*the_other)++;
462             }
463
464           else if (**one == 'M' && **the_other != 'm')
465             {
466               (*one)++;
467             }
468
469           else if (**one == 'N' && strchr ("ynqiuxthd", **the_other))
470             {
471               *out++ = *(*the_other)++;
472               (*one)++;
473             }
474
475           else if (**one == 'S' && strchr ("sog", **the_other))
476             {
477               *out++ = *(*the_other)++;
478               (*one)++;
479             }
480
481           else if (one == &left)
482             {
483               one = &right, the_other = &left;
484               goto again;
485             }
486
487           else
488             break;
489         }
490     }
491
492   if (*left || *right)
493     {
494       g_free (result);
495       result = NULL;
496     }
497   else
498     *out++ = '\0';
499
500   return result;
501 }
502
503 typedef struct _AST AST;
504 typedef gchar *    (*get_pattern_func)    (AST                 *ast,
505                                            GError             **error);
506 typedef GVariant * (*get_value_func)      (AST                 *ast,
507                                            const GVariantType  *type,
508                                            GError             **error);
509 typedef GVariant * (*get_base_value_func) (AST                 *ast,
510                                            const GVariantType  *type,
511                                            GError             **error);
512 typedef void       (*free_func)           (AST                 *ast);
513
514 typedef struct
515 {
516   gchar *    (* get_pattern)    (AST                 *ast,
517                                  GError             **error);
518   GVariant * (* get_value)      (AST                 *ast,
519                                  const GVariantType  *type,
520                                  GError             **error);
521   GVariant * (* get_base_value) (AST                 *ast,
522                                  const GVariantType  *type,
523                                  GError             **error);
524   void       (* free)           (AST                 *ast);
525 } ASTClass;
526
527 struct _AST
528 {
529   const ASTClass *class;
530   SourceRef source_ref;
531 };
532
533 static gchar *
534 ast_get_pattern (AST     *ast,
535                  GError **error)
536 {
537   return ast->class->get_pattern (ast, error);
538 }
539
540 static GVariant *
541 ast_get_value (AST                 *ast,
542                const GVariantType  *type,
543                GError             **error)
544 {
545   return ast->class->get_value (ast, type, error);
546 }
547
548 static void
549 ast_free (AST *ast)
550 {
551   ast->class->free (ast);
552 }
553
554 G_GNUC_PRINTF(5, 6)
555 static void
556 ast_set_error (AST          *ast,
557                GError      **error,
558                AST          *other_ast,
559                gint          code,
560                const gchar  *format,
561                ...)
562 {
563   va_list ap;
564
565   va_start (ap, format);
566   parser_set_error_va (error, &ast->source_ref,
567                        other_ast ? & other_ast->source_ref : NULL,
568                        code,
569                        format, ap);
570   va_end (ap);
571 }
572
573 static GVariant *
574 ast_type_error (AST                 *ast,
575                 const GVariantType  *type,
576                 GError             **error)
577 {
578   gchar *typestr;
579
580   typestr = g_variant_type_dup_string (type);
581   ast_set_error (ast, error, NULL,
582                  G_VARIANT_PARSE_ERROR_TYPE_ERROR,
583                  "can not parse as value of type '%s'",
584                  typestr);
585   g_free (typestr);
586
587   return NULL;
588 }
589
590 static GVariant *
591 ast_resolve (AST     *ast,
592              GError **error)
593 {
594   GVariant *value;
595   gchar *pattern;
596   gint i, j = 0;
597
598   pattern = ast_get_pattern (ast, error);
599
600   if (pattern == NULL)
601     return NULL;
602
603   /* choose reasonable defaults
604    *
605    *   1) favour non-maybe values where possible
606    *   2) default type for strings is 's'
607    *   3) default type for integers is 'i'
608    */
609   for (i = 0; pattern[i]; i++)
610     switch (pattern[i])
611       {
612       case '*':
613         ast_set_error (ast, error, NULL,
614                        G_VARIANT_PARSE_ERROR_CANNOT_INFER_TYPE,
615                        "unable to infer type");
616         g_free (pattern);
617         return NULL;
618
619       case 'M':
620         break;
621
622       case 'S':
623         pattern[j++] = 's';
624         break;
625
626       case 'N':
627         pattern[j++] = 'i';
628         break;
629
630       default:
631         pattern[j++] = pattern[i];
632         break;
633       }
634   pattern[j++] = '\0';
635
636   value = ast_get_value (ast, G_VARIANT_TYPE (pattern), error);
637   g_free (pattern);
638
639   return value;
640 }
641
642
643 static AST *parse (TokenStream  *stream,
644                    va_list      *app,
645                    GError      **error);
646
647 static void
648 ast_array_append (AST  ***array,
649                   gint   *n_items,
650                   AST    *ast)
651 {
652   if ((*n_items & (*n_items - 1)) == 0)
653     *array = g_renew (AST *, *array, *n_items ? 2 ** n_items : 1);
654
655   (*array)[(*n_items)++] = ast;
656 }
657
658 static void
659 ast_array_free (AST  **array,
660                 gint   n_items)
661 {
662   gint i;
663
664   for (i = 0; i < n_items; i++)
665     ast_free (array[i]);
666   g_free (array);
667 }
668
669 static gchar *
670 ast_array_get_pattern (AST    **array,
671                        gint     n_items,
672                        GError **error)
673 {
674   gchar *pattern;
675   gint i;
676
677   pattern = ast_get_pattern (array[0], error);
678
679   if (pattern == NULL)
680     return NULL;
681
682   for (i = 1; i < n_items; i++)
683     {
684       gchar *tmp, *merged;
685
686       tmp = ast_get_pattern (array[i], error);
687
688       if (tmp == NULL)
689         {
690           g_free (pattern);
691           return NULL;
692         }
693
694       merged = pattern_coalesce (pattern, tmp);
695       g_free (pattern);
696       pattern = merged;
697
698       if (merged == NULL)
699         /* set coalescence implies pairwise coalescence (i think).
700          * we should therefore be able to trace the failure to a single
701          * pair of values.
702          */
703         {
704           int j = 0;
705
706           while (TRUE)
707             {
708               gchar *tmp2;
709               gchar *m;
710
711               /* if 'j' reaches 'i' then we failed to find the pair */
712               g_assert (j < i);
713
714               tmp2 = ast_get_pattern (array[j], NULL);
715               g_assert (tmp2 != NULL);
716
717               m = pattern_coalesce (tmp, tmp2);
718               g_free (tmp2);
719               g_free (m);
720
721               if (m == NULL)
722                 {
723                   /* we found a conflict between 'i' and 'j'.
724                    *
725                    * report the error.  note: 'j' is first.
726                    */
727                   ast_set_error (array[j], error, array[i],
728                                  G_VARIANT_PARSE_ERROR_NO_COMMON_TYPE,
729                                  "unable to find a common type");
730                   g_free (tmp);
731                   return NULL;
732                 }
733
734               j++;
735             }
736
737         }
738
739       g_free (tmp);
740     }
741
742   return pattern;
743 }
744
745 typedef struct
746 {
747   AST ast;
748
749   AST *child;
750 } Maybe;
751
752 static gchar *
753 maybe_get_pattern (AST     *ast,
754                    GError **error)
755 {
756   Maybe *maybe = (Maybe *) ast;
757
758   if (maybe->child != NULL)
759     {
760       gchar *child_pattern;
761       gchar *pattern;
762
763       child_pattern = ast_get_pattern (maybe->child, error);
764
765       if (child_pattern == NULL)
766         return NULL;
767
768       pattern = g_strdup_printf ("m%s", child_pattern);
769       g_free (child_pattern);
770
771       return pattern;
772     }
773
774   return g_strdup ("m*");
775 }
776
777 static GVariant *
778 maybe_get_value (AST                 *ast,
779                  const GVariantType  *type,
780                  GError             **error)
781 {
782   Maybe *maybe = (Maybe *) ast;
783   GVariant *value;
784
785   if (!g_variant_type_is_maybe (type))
786     return ast_type_error (ast, type, error);
787
788   type = g_variant_type_element (type);
789
790   if (maybe->child)
791     {
792       value = ast_get_value (maybe->child, type, error);
793
794       if (value == NULL)
795         return NULL;
796     }
797   else
798     value = NULL;
799
800   return g_variant_new_maybe (type, value);
801 }
802
803 static void
804 maybe_free (AST *ast)
805 {
806   Maybe *maybe = (Maybe *) ast;
807
808   if (maybe->child != NULL)
809     ast_free (maybe->child);
810
811   g_slice_free (Maybe, maybe);
812 }
813
814 static AST *
815 maybe_parse (TokenStream  *stream,
816              va_list      *app,
817              GError      **error)
818 {
819   static const ASTClass maybe_class = {
820     maybe_get_pattern,
821     maybe_get_value, NULL,
822     maybe_free
823   };
824   AST *child = NULL;
825   Maybe *maybe;
826
827   if (token_stream_consume (stream, "just"))
828     {
829       child = parse (stream, app, error);
830       if (child == NULL)
831         return NULL;
832     }
833
834   else if (!token_stream_consume (stream, "nothing"))
835     {
836       token_stream_set_error (stream, error, TRUE,
837                               G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD,
838                               "unknown keyword");
839       return NULL;
840     }
841
842   maybe = g_slice_new (Maybe);
843   maybe->ast.class = &maybe_class;
844   maybe->child = child;
845
846   return (AST *) maybe;
847 }
848
849 static GVariant *
850 maybe_wrapper (AST                 *ast,
851                const GVariantType  *type,
852                GError             **error)
853 {
854   const GVariantType *t;
855   GVariant *value;
856   int depth;
857
858   for (depth = 0, t = type;
859        g_variant_type_is_maybe (t);
860        depth++, t = g_variant_type_element (t));
861
862   value = ast->class->get_base_value (ast, t, error);
863
864   if (value == NULL)
865     return NULL;
866
867   while (depth--)
868     value = g_variant_new_maybe (NULL, value);
869
870   return value;
871 }
872
873 typedef struct
874 {
875   AST ast;
876
877   AST **children;
878   gint n_children;
879 } Array;
880
881 static gchar *
882 array_get_pattern (AST     *ast,
883                    GError **error)
884 {
885   Array *array = (Array *) ast;
886   gchar *pattern;
887   gchar *result;
888
889   if (array->n_children == 0)
890     return g_strdup ("Ma*");
891
892   pattern = ast_array_get_pattern (array->children, array->n_children, error);
893
894   if (pattern == NULL)
895     return NULL;
896
897   result = g_strdup_printf ("Ma%s", pattern);
898   g_free (pattern);
899
900   return result;
901 }
902
903 static GVariant *
904 array_get_value (AST                 *ast,
905                  const GVariantType  *type,
906                  GError             **error)
907 {
908   Array *array = (Array *) ast;
909   const GVariantType *childtype;
910   GVariantBuilder builder;
911   gint i;
912
913   if (!g_variant_type_is_array (type))
914     return ast_type_error (ast, type, error);
915
916   g_variant_builder_init (&builder, type);
917   childtype = g_variant_type_element (type);
918
919   for (i = 0; i < array->n_children; i++)
920     {
921       GVariant *child;
922
923       if (!(child = ast_get_value (array->children[i], childtype, error)))
924         {
925           g_variant_builder_clear (&builder);
926           return NULL;
927         }
928
929       g_variant_builder_add_value (&builder, child);
930     }
931
932   return g_variant_builder_end (&builder);
933 }
934
935 static void
936 array_free (AST *ast)
937 {
938   Array *array = (Array *) ast;
939
940   ast_array_free (array->children, array->n_children);
941   g_slice_free (Array, array);
942 }
943
944 static AST *
945 array_parse (TokenStream  *stream,
946              va_list      *app,
947              GError      **error)
948 {
949   static const ASTClass array_class = {
950     array_get_pattern,
951     maybe_wrapper, array_get_value,
952     array_free
953   };
954   gboolean need_comma = FALSE;
955   Array *array;
956
957   array = g_slice_new (Array);
958   array->ast.class = &array_class;
959   array->children = NULL;
960   array->n_children = 0;
961
962   token_stream_assert (stream, "[");
963   while (!token_stream_consume (stream, "]"))
964     {
965       AST *child;
966
967       if (need_comma &&
968           !token_stream_require (stream, ",",
969                                  " or ']' to follow array element",
970                                  error))
971         goto error;
972
973       child = parse (stream, app, error);
974
975       if (!child)
976         goto error;
977
978       ast_array_append (&array->children, &array->n_children, child);
979       need_comma = TRUE;
980     }
981
982   return (AST *) array;
983
984  error:
985   ast_array_free (array->children, array->n_children);
986   g_slice_free (Array, array);
987
988   return NULL;
989 }
990
991 typedef struct
992 {
993   AST ast;
994
995   AST **children;
996   gint n_children;
997 } Tuple;
998
999 static gchar *
1000 tuple_get_pattern (AST     *ast,
1001                    GError **error)
1002 {
1003   Tuple *tuple = (Tuple *) ast;
1004   gchar *result = NULL;
1005   gchar **parts;
1006   gint i;
1007
1008   parts = g_new (gchar *, tuple->n_children + 4);
1009   parts[tuple->n_children + 1] = (gchar *) ")";
1010   parts[tuple->n_children + 2] = NULL;
1011   parts[0] = (gchar *) "M(";
1012
1013   for (i = 0; i < tuple->n_children; i++)
1014     if (!(parts[i + 1] = ast_get_pattern (tuple->children[i], error)))
1015       break;
1016
1017   if (i == tuple->n_children)
1018     result = g_strjoinv ("", parts);
1019
1020   /* parts[0] should not be freed */
1021   while (i)
1022     g_free (parts[i--]);
1023   g_free (parts);
1024
1025   return result;
1026 }
1027
1028 static GVariant *
1029 tuple_get_value (AST                 *ast,
1030                  const GVariantType  *type,
1031                  GError             **error)
1032 {
1033   Tuple *tuple = (Tuple *) ast;
1034   const GVariantType *childtype;
1035   GVariantBuilder builder;
1036   gint i;
1037
1038   if (!g_variant_type_is_tuple (type))
1039     return ast_type_error (ast, type, error);
1040
1041   g_variant_builder_init (&builder, type);
1042   childtype = g_variant_type_first (type);
1043
1044   for (i = 0; i < tuple->n_children; i++)
1045     {
1046       GVariant *child;
1047
1048       if (childtype == NULL)
1049         {
1050           g_variant_builder_clear (&builder);
1051           return ast_type_error (ast, type, error);
1052         }
1053
1054       if (!(child = ast_get_value (tuple->children[i], childtype, error)))
1055         {
1056           g_variant_builder_clear (&builder);
1057           return FALSE;
1058         }
1059
1060       g_variant_builder_add_value (&builder, child);
1061       childtype = g_variant_type_next (childtype);
1062     }
1063
1064   if (childtype != NULL)
1065     {
1066       g_variant_builder_clear (&builder);
1067       return ast_type_error (ast, type, error);
1068     }
1069
1070   return g_variant_builder_end (&builder);
1071 }
1072
1073 static void
1074 tuple_free (AST *ast)
1075 {
1076   Tuple *tuple = (Tuple *) ast;
1077
1078   ast_array_free (tuple->children, tuple->n_children);
1079   g_slice_free (Tuple, tuple);
1080 }
1081
1082 static AST *
1083 tuple_parse (TokenStream  *stream,
1084              va_list      *app,
1085              GError      **error)
1086 {
1087   static const ASTClass tuple_class = {
1088     tuple_get_pattern,
1089     maybe_wrapper, tuple_get_value,
1090     tuple_free
1091   };
1092   gboolean need_comma = FALSE;
1093   gboolean first = TRUE;
1094   Tuple *tuple;
1095
1096   tuple = g_slice_new (Tuple);
1097   tuple->ast.class = &tuple_class;
1098   tuple->children = NULL;
1099   tuple->n_children = 0;
1100
1101   token_stream_assert (stream, "(");
1102   while (!token_stream_consume (stream, ")"))
1103     {
1104       AST *child;
1105
1106       if (need_comma &&
1107           !token_stream_require (stream, ",",
1108                                  " or ')' to follow tuple element",
1109                                  error))
1110         goto error;
1111
1112       child = parse (stream, app, error);
1113
1114       if (!child)
1115         goto error;
1116
1117       ast_array_append (&tuple->children, &tuple->n_children, child);
1118
1119       /* the first time, we absolutely require a comma, so grab it here
1120        * and leave need_comma = FALSE so that the code above doesn't
1121        * require a second comma.
1122        *
1123        * the second and remaining times, we set need_comma = TRUE.
1124        */
1125       if (first)
1126         {
1127           if (!token_stream_require (stream, ",",
1128                                      " after first tuple element", error))
1129             goto error;
1130
1131           first = FALSE;
1132         }
1133       else
1134         need_comma = TRUE;
1135     }
1136
1137   return (AST *) tuple;
1138
1139  error:
1140   ast_array_free (tuple->children, tuple->n_children);
1141   g_slice_free (Tuple, tuple);
1142
1143   return NULL;
1144 }
1145
1146 typedef struct
1147 {
1148   AST ast;
1149
1150   AST *value;
1151 } Variant;
1152
1153 static gchar *
1154 variant_get_pattern (AST     *ast,
1155                      GError **error)
1156 {
1157   return g_strdup ("Mv");
1158 }
1159
1160 static GVariant *
1161 variant_get_value (AST                 *ast,
1162                    const GVariantType  *type,
1163                    GError             **error)
1164 {
1165   Variant *variant = (Variant *) ast;
1166   GVariant *child;
1167
1168   if (!g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
1169     return ast_type_error (ast, type, error);
1170
1171   child = ast_resolve (variant->value, error);
1172
1173   if (child == NULL)
1174     return NULL;
1175
1176   return g_variant_new_variant (child);
1177 }
1178
1179 static void
1180 variant_free (AST *ast)
1181 {
1182   Variant *variant = (Variant *) ast;
1183
1184   ast_free (variant->value);
1185   g_slice_free (Variant, variant);
1186 }
1187
1188 static AST *
1189 variant_parse (TokenStream  *stream,
1190                va_list      *app,
1191                GError      **error)
1192 {
1193   static const ASTClass variant_class = {
1194     variant_get_pattern,
1195     maybe_wrapper, variant_get_value,
1196     variant_free
1197   };
1198   Variant *variant;
1199   AST *value;
1200
1201   token_stream_assert (stream, "<");
1202   value = parse (stream, app, error);
1203
1204   if (!value)
1205     return NULL;
1206
1207   if (!token_stream_require (stream, ">", " to follow variant value", error))
1208     {
1209       ast_free (value);
1210       return NULL;
1211     }
1212
1213   variant = g_slice_new (Variant);
1214   variant->ast.class = &variant_class;
1215   variant->value = value;
1216
1217   return (AST *) variant;
1218 }
1219
1220 typedef struct
1221 {
1222   AST ast;
1223
1224   AST **keys;
1225   AST **values;
1226   gint n_children;
1227 } Dictionary;
1228
1229 static gchar *
1230 dictionary_get_pattern (AST     *ast,
1231                         GError **error)
1232 {
1233   Dictionary *dict = (Dictionary *) ast;
1234   gchar *value_pattern;
1235   gchar *key_pattern;
1236   gchar key_char;
1237   gchar *result;
1238
1239   if (dict->n_children == 0)
1240     return g_strdup ("Ma{**}");
1241
1242   key_pattern = ast_array_get_pattern (dict->keys,
1243                                        abs (dict->n_children),
1244                                        error);
1245
1246   if (key_pattern == NULL)
1247     return NULL;
1248
1249   /* we can not have maybe keys */
1250   if (key_pattern[0] == 'M')
1251     key_char = key_pattern[1];
1252   else
1253     key_char = key_pattern[0];
1254
1255   g_free (key_pattern);
1256
1257   /* the basic types,
1258    * plus undetermined number type and undetermined string type.
1259    */
1260   if (!strchr ("bynqiuxthdsogNS", key_char))
1261     {
1262       ast_set_error (ast, error, NULL,
1263                      G_VARIANT_PARSE_ERROR_BASIC_TYPE_EXPECTED,
1264                      "dictionary keys must have basic types");
1265       return NULL;
1266     }
1267
1268   value_pattern = ast_get_pattern (dict->values[0], error);
1269
1270   if (value_pattern == NULL)
1271     return NULL;
1272
1273   result = g_strdup_printf ("M%s{%c%s}",
1274                             dict->n_children > 0 ? "a" : "",
1275                             key_char, value_pattern);
1276   g_free (value_pattern);
1277
1278   return result;
1279 }
1280
1281 static GVariant *
1282 dictionary_get_value (AST                 *ast,
1283                       const GVariantType  *type,
1284                       GError             **error)
1285 {
1286   Dictionary *dict = (Dictionary *) ast;
1287
1288   if (dict->n_children == -1)
1289     {
1290       const GVariantType *subtype;
1291       GVariantBuilder builder;
1292       GVariant *subvalue;
1293
1294       if (!g_variant_type_is_dict_entry (type))
1295         return ast_type_error (ast, type, error);
1296
1297       g_variant_builder_init (&builder, type);
1298
1299       subtype = g_variant_type_key (type);
1300       if (!(subvalue = ast_get_value (dict->keys[0], subtype, error)))
1301         {
1302           g_variant_builder_clear (&builder);
1303           return NULL;
1304         }
1305       g_variant_builder_add_value (&builder, subvalue);
1306
1307       subtype = g_variant_type_value (type);
1308       if (!(subvalue = ast_get_value (dict->values[0], subtype, error)))
1309         {
1310           g_variant_builder_clear (&builder);
1311           return NULL;
1312         }
1313       g_variant_builder_add_value (&builder, subvalue);
1314
1315       return g_variant_builder_end (&builder);
1316     }
1317   else
1318     {
1319       const GVariantType *entry, *key, *val;
1320       GVariantBuilder builder;
1321       gint i;
1322
1323       if (!g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_DICTIONARY))
1324         return ast_type_error (ast, type, error);
1325
1326       entry = g_variant_type_element (type);
1327       key = g_variant_type_key (entry);
1328       val = g_variant_type_value (entry);
1329
1330       g_variant_builder_init (&builder, type);
1331
1332       for (i = 0; i < dict->n_children; i++)
1333         {
1334           GVariant *subvalue;
1335
1336           g_variant_builder_open (&builder, entry);
1337
1338           if (!(subvalue = ast_get_value (dict->keys[i], key, error)))
1339             {
1340               g_variant_builder_clear (&builder);
1341               return NULL;
1342             }
1343           g_variant_builder_add_value (&builder, subvalue);
1344
1345           if (!(subvalue = ast_get_value (dict->values[i], val, error)))
1346             {
1347               g_variant_builder_clear (&builder);
1348               return NULL;
1349             }
1350           g_variant_builder_add_value (&builder, subvalue);
1351           g_variant_builder_close (&builder);
1352         }
1353
1354       return g_variant_builder_end (&builder);
1355     }
1356 }
1357
1358 static void
1359 dictionary_free (AST *ast)
1360 {
1361   Dictionary *dict = (Dictionary *) ast;
1362   gint n_children;
1363
1364   if (dict->n_children > -1)
1365     n_children = dict->n_children;
1366   else
1367     n_children = 1;
1368
1369   ast_array_free (dict->keys, n_children);
1370   ast_array_free (dict->values, n_children);
1371   g_slice_free (Dictionary, dict);
1372 }
1373
1374 static AST *
1375 dictionary_parse (TokenStream  *stream,
1376                   va_list      *app,
1377                   GError      **error)
1378 {
1379   static const ASTClass dictionary_class = {
1380     dictionary_get_pattern,
1381     maybe_wrapper, dictionary_get_value,
1382     dictionary_free
1383   };
1384   gint n_keys, n_values;
1385   gboolean only_one;
1386   Dictionary *dict;
1387   AST *first;
1388
1389   dict = g_slice_new (Dictionary);
1390   dict->ast.class = &dictionary_class;
1391   dict->keys = NULL;
1392   dict->values = NULL;
1393   n_keys = n_values = 0;
1394
1395   token_stream_assert (stream, "{");
1396
1397   if (token_stream_consume (stream, "}"))
1398     {
1399       dict->n_children = 0;
1400       return (AST *) dict;
1401     }
1402
1403   if ((first = parse (stream, app, error)) == NULL)
1404     goto error;
1405
1406   ast_array_append (&dict->keys, &n_keys, first);
1407
1408   only_one = token_stream_consume (stream, ",");
1409   if (!only_one &&
1410       !token_stream_require (stream, ":",
1411                              " or ',' to follow dictionary entry key",
1412                              error))
1413     goto error;
1414
1415   if ((first = parse (stream, app, error)) == NULL)
1416     goto error;
1417
1418   ast_array_append (&dict->values, &n_values, first);
1419
1420   if (only_one)
1421     {
1422       if (!token_stream_require (stream, "}", " at end of dictionary entry",
1423                                  error))
1424         goto error;
1425
1426       g_assert (n_keys == 1 && n_values == 1);
1427       dict->n_children = -1;
1428
1429       return (AST *) dict;
1430     }
1431
1432   while (!token_stream_consume (stream, "}"))
1433     {
1434       AST *child;
1435
1436       if (!token_stream_require (stream, ",",
1437                                  " or '}' to follow dictionary entry", error))
1438         goto error;
1439
1440       child = parse (stream, app, error);
1441
1442       if (!child)
1443         goto error;
1444
1445       ast_array_append (&dict->keys, &n_keys, child);
1446
1447       if (!token_stream_require (stream, ":",
1448                                  " to follow dictionary entry key", error))
1449         goto error;
1450
1451       child = parse (stream, app, error);
1452
1453       if (!child)
1454         goto error;
1455
1456       ast_array_append (&dict->values, &n_values, child);
1457     }
1458
1459   g_assert (n_keys == n_values);
1460   dict->n_children = n_keys;
1461
1462   return (AST *) dict;
1463
1464  error:
1465   ast_array_free (dict->keys, n_keys);
1466   ast_array_free (dict->values, n_values);
1467   g_slice_free (Dictionary, dict);
1468
1469   return NULL;
1470 }
1471
1472 typedef struct
1473 {
1474   AST ast;
1475   gchar *string;
1476 } String;
1477
1478 static gchar *
1479 string_get_pattern (AST     *ast,
1480                     GError **error)
1481 {
1482   return g_strdup ("MS");
1483 }
1484
1485 static GVariant *
1486 string_get_value (AST                 *ast,
1487                   const GVariantType  *type,
1488                   GError             **error)
1489 {
1490   String *string = (String *) ast;
1491
1492   if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
1493     return g_variant_new_string (string->string);
1494
1495   else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
1496     {
1497       if (!g_variant_is_object_path (string->string))
1498         {
1499           ast_set_error (ast, error, NULL,
1500                          G_VARIANT_PARSE_ERROR_INVALID_OBJECT_PATH,
1501                          "not a valid object path");
1502           return NULL;
1503         }
1504
1505       return g_variant_new_object_path (string->string);
1506     }
1507
1508   else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
1509     {
1510       if (!g_variant_is_signature (string->string))
1511         {
1512           ast_set_error (ast, error, NULL,
1513                          G_VARIANT_PARSE_ERROR_INVALID_SIGNATURE,
1514                          "not a valid signature");
1515           return NULL;
1516         }
1517
1518       return g_variant_new_signature (string->string);
1519     }
1520
1521   else
1522     return ast_type_error (ast, type, error);
1523 }
1524
1525 static void
1526 string_free (AST *ast)
1527 {
1528   String *string = (String *) ast;
1529
1530   g_free (string->string);
1531   g_slice_free (String, string);
1532 }
1533
1534 static gboolean
1535 unicode_unescape (const gchar  *src,
1536                   gint         *src_ofs,
1537                   gchar        *dest,
1538                   gint         *dest_ofs,
1539                   gint          length,
1540                   SourceRef    *ref,
1541                   GError      **error)
1542 {
1543   gchar buffer[9];
1544   guint64 value;
1545   gchar *end;
1546
1547   (*src_ofs)++;
1548
1549   g_assert (length < sizeof (buffer));
1550   strncpy (buffer, src + *src_ofs, length);
1551   buffer[length] = '\0';
1552
1553   value = g_ascii_strtoull (buffer, &end, 0x10);
1554
1555   if (value == 0 || end != buffer + length)
1556     {
1557       parser_set_error (error, ref, NULL,
1558                         G_VARIANT_PARSE_ERROR_INVALID_CHARACTER,
1559                         "invalid %d-character unicode escape", length);
1560       return FALSE;
1561     }
1562
1563   g_assert (value <= G_MAXUINT32);
1564
1565   *dest_ofs += g_unichar_to_utf8 (value, dest + *dest_ofs);
1566   *src_ofs += length;
1567
1568   return TRUE;
1569 }
1570
1571 static AST *
1572 string_parse (TokenStream  *stream,
1573               va_list      *app,
1574               GError      **error)
1575 {
1576   static const ASTClass string_class = {
1577     string_get_pattern,
1578     maybe_wrapper, string_get_value,
1579     string_free
1580   };
1581   String *string;
1582   SourceRef ref;
1583   gchar *token;
1584   gsize length;
1585   gchar quote;
1586   gchar *str;
1587   gint i, j;
1588
1589   token_stream_start_ref (stream, &ref);
1590   token = token_stream_get (stream);
1591   token_stream_end_ref (stream, &ref);
1592   length = strlen (token);
1593   quote = token[0];
1594
1595   str = g_malloc (length);
1596   g_assert (quote == '"' || quote == '\'');
1597   j = 0;
1598   i = 1;
1599   while (token[i] != quote)
1600     switch (token[i])
1601       {
1602       case '\0':
1603         parser_set_error (error, &ref, NULL,
1604                           G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1605                           "unterminated string constant");
1606         g_free (token);
1607         g_free (str);
1608         return NULL;
1609
1610       case '\\':
1611         switch (token[++i])
1612           {
1613           case '\0':
1614             parser_set_error (error, &ref, NULL,
1615                               G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1616                               "unterminated string constant");
1617             g_free (token);
1618             g_free (str);
1619             return NULL;
1620
1621           case 'u':
1622             if (!unicode_unescape (token, &i, str, &j, 4, &ref, error))
1623               {
1624                 g_free (token);
1625                 g_free (str);
1626                 return NULL;
1627               }
1628             continue;
1629
1630           case 'U':
1631             if (!unicode_unescape (token, &i, str, &j, 8, &ref, error))
1632               {
1633                 g_free (token);
1634                 g_free (str);
1635                 return NULL;
1636               }
1637             continue;
1638
1639           case 'a': str[j++] = '\a'; i++; continue;
1640           case 'b': str[j++] = '\b'; i++; continue;
1641           case 'f': str[j++] = '\f'; i++; continue;
1642           case 'n': str[j++] = '\n'; i++; continue;
1643           case 'r': str[j++] = '\r'; i++; continue;
1644           case 't': str[j++] = '\t'; i++; continue;
1645           case 'v': str[j++] = '\v'; i++; continue;
1646           case '\n': i++; continue;
1647           }
1648
1649       default:
1650         str[j++] = token[i++];
1651       }
1652   str[j++] = '\0';
1653   g_free (token);
1654
1655   string = g_slice_new (String);
1656   string->ast.class = &string_class;
1657   string->string = str;
1658
1659   token_stream_next (stream);
1660
1661   return (AST *) string;
1662 }
1663
1664 typedef struct
1665 {
1666   AST ast;
1667   gchar *string;
1668 } ByteString;
1669
1670 static gchar *
1671 bytestring_get_pattern (AST     *ast,
1672                         GError **error)
1673 {
1674   return g_strdup ("May");
1675 }
1676
1677 static GVariant *
1678 bytestring_get_value (AST                 *ast,
1679                       const GVariantType  *type,
1680                       GError             **error)
1681 {
1682   ByteString *string = (ByteString *) ast;
1683
1684   if (!g_variant_type_equal (type, G_VARIANT_TYPE_BYTESTRING))
1685     return ast_type_error (ast, type, error);
1686
1687   return g_variant_new_bytestring (string->string);
1688 }
1689
1690 static void
1691 bytestring_free (AST *ast)
1692 {
1693   ByteString *string = (ByteString *) ast;
1694
1695   g_free (string->string);
1696   g_slice_free (ByteString, string);
1697 }
1698
1699 static AST *
1700 bytestring_parse (TokenStream  *stream,
1701                   va_list      *app,
1702                   GError      **error)
1703 {
1704   static const ASTClass bytestring_class = {
1705     bytestring_get_pattern,
1706     maybe_wrapper, bytestring_get_value,
1707     bytestring_free
1708   };
1709   ByteString *string;
1710   SourceRef ref;
1711   gchar *token;
1712   gsize length;
1713   gchar quote;
1714   gchar *str;
1715   gint i, j;
1716
1717   token_stream_start_ref (stream, &ref);
1718   token = token_stream_get (stream);
1719   token_stream_end_ref (stream, &ref);
1720   g_assert (token[0] == 'b');
1721   length = strlen (token);
1722   quote = token[1];
1723
1724   str = g_malloc (length);
1725   g_assert (quote == '"' || quote == '\'');
1726   j = 0;
1727   i = 2;
1728   while (token[i] != quote)
1729     switch (token[i])
1730       {
1731       case '\0':
1732         parser_set_error (error, &ref, NULL,
1733                           G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1734                           "unterminated string constant");
1735         g_free (str);
1736         g_free (token);
1737         return NULL;
1738
1739       case '\\':
1740         switch (token[++i])
1741           {
1742           case '\0':
1743             parser_set_error (error, &ref, NULL,
1744                               G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1745                               "unterminated string constant");
1746             g_free (str);
1747             g_free (token);
1748             return NULL;
1749
1750           case '0': case '1': case '2': case '3':
1751           case '4': case '5': case '6': case '7':
1752             {
1753               /* up to 3 characters */
1754               guchar val = token[i++] - '0';
1755
1756               if ('0' <= token[i] && token[i] < '8')
1757                 val = (val << 3) | (token[i++] - '0');
1758
1759               if ('0' <= token[i] && token[i] < '8')
1760                 val = (val << 3) | (token[i++] - '0');
1761
1762               str[j++] = val;
1763             }
1764             continue;
1765
1766           case 'a': str[j++] = '\a'; i++; continue;
1767           case 'b': str[j++] = '\b'; i++; continue;
1768           case 'f': str[j++] = '\f'; i++; continue;
1769           case 'n': str[j++] = '\n'; i++; continue;
1770           case 'r': str[j++] = '\r'; i++; continue;
1771           case 't': str[j++] = '\t'; i++; continue;
1772           case 'v': str[j++] = '\v'; i++; continue;
1773           case '\n': i++; continue;
1774           }
1775
1776       default:
1777         str[j++] = token[i++];
1778       }
1779   str[j++] = '\0';
1780   g_free (token);
1781
1782   string = g_slice_new (ByteString);
1783   string->ast.class = &bytestring_class;
1784   string->string = str;
1785
1786   token_stream_next (stream);
1787
1788   return (AST *) string;
1789 }
1790
1791 typedef struct
1792 {
1793   AST ast;
1794
1795   gchar *token;
1796 } Number;
1797
1798 static gchar *
1799 number_get_pattern (AST     *ast,
1800                     GError **error)
1801 {
1802   Number *number = (Number *) ast;
1803
1804   if (strchr (number->token, '.') ||
1805       (!g_str_has_prefix (number->token, "0x") && strchr (number->token, 'e')) ||
1806       strstr (number->token, "inf") ||
1807       strstr (number->token, "nan"))
1808     return g_strdup ("Md");
1809
1810   return g_strdup ("MN");
1811 }
1812
1813 static GVariant *
1814 number_overflow (AST                 *ast,
1815                  const GVariantType  *type,
1816                  GError             **error)
1817 {
1818   ast_set_error (ast, error, NULL,
1819                  G_VARIANT_PARSE_ERROR_NUMBER_OUT_OF_RANGE,
1820                  "number out of range for type '%c'",
1821                  g_variant_type_peek_string (type)[0]);
1822   return NULL;
1823 }
1824
1825 static GVariant *
1826 number_get_value (AST                 *ast,
1827                   const GVariantType  *type,
1828                   GError             **error)
1829 {
1830   Number *number = (Number *) ast;
1831   const gchar *token;
1832   gboolean negative;
1833   gboolean floating;
1834   guint64 abs_val;
1835   gdouble dbl_val;
1836   gchar *end;
1837
1838   token = number->token;
1839
1840   if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
1841     {
1842       floating = TRUE;
1843
1844       errno = 0;
1845       dbl_val = g_ascii_strtod (token, &end);
1846       if (dbl_val != 0.0 && errno == ERANGE)
1847         {
1848           ast_set_error (ast, error, NULL,
1849                          G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG,
1850                          "number too big for any type");
1851           return NULL;
1852         }
1853
1854       /* silence uninitialised warnings... */
1855       negative = FALSE;
1856       abs_val = 0;
1857     }
1858   else
1859     {
1860       floating = FALSE;
1861       negative = token[0] == '-';
1862       if (token[0] == '-')
1863         token++;
1864
1865       errno = 0;
1866       abs_val = g_ascii_strtoull (token, &end, 0);
1867       if (abs_val == G_MAXUINT64 && errno == ERANGE)
1868         {
1869           ast_set_error (ast, error, NULL,
1870                          G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG,
1871                          "integer too big for any type");
1872           return NULL;
1873         }
1874
1875       if (abs_val == 0)
1876         negative = FALSE;
1877
1878       /* silence uninitialised warning... */
1879       dbl_val = 0.0;
1880     }
1881
1882   if (*end != '\0')
1883     {
1884       SourceRef ref;
1885
1886       ref = ast->source_ref;
1887       ref.start += end - number->token;
1888       ref.end = ref.start + 1;
1889
1890       parser_set_error (error, &ref, NULL,
1891                         G_VARIANT_PARSE_ERROR_INVALID_CHARACTER,
1892                         "invalid character in number");
1893       return NULL;
1894      }
1895
1896   if (floating)
1897     return g_variant_new_double (dbl_val);
1898
1899   switch (*g_variant_type_peek_string (type))
1900     {
1901     case 'y':
1902       if (negative || abs_val > G_MAXUINT8)
1903         return number_overflow (ast, type, error);
1904       return g_variant_new_byte (abs_val);
1905
1906     case 'n':
1907       if (abs_val - negative > G_MAXINT16)
1908         return number_overflow (ast, type, error);
1909       return g_variant_new_int16 (negative ? -abs_val : abs_val);
1910
1911     case 'q':
1912       if (negative || abs_val > G_MAXUINT16)
1913         return number_overflow (ast, type, error);
1914       return g_variant_new_uint16 (abs_val);
1915
1916     case 'i':
1917       if (abs_val - negative > G_MAXINT32)
1918         return number_overflow (ast, type, error);
1919       return g_variant_new_int32 (negative ? -abs_val : abs_val);
1920
1921     case 'u':
1922       if (negative || abs_val > G_MAXUINT32)
1923         return number_overflow (ast, type, error);
1924       return g_variant_new_uint32 (abs_val);
1925
1926     case 'x':
1927       if (abs_val - negative > G_MAXINT64)
1928         return number_overflow (ast, type, error);
1929       return g_variant_new_int64 (negative ? -abs_val : abs_val);
1930
1931     case 't':
1932       if (negative)
1933         return number_overflow (ast, type, error);
1934       return g_variant_new_uint64 (abs_val);
1935
1936     case 'h':
1937       if (abs_val - negative > G_MAXINT32)
1938         return number_overflow (ast, type, error);
1939       return g_variant_new_handle (negative ? -abs_val : abs_val);
1940
1941     default:
1942       return ast_type_error (ast, type, error);
1943     }
1944 }
1945
1946 static void
1947 number_free (AST *ast)
1948 {
1949   Number *number = (Number *) ast;
1950
1951   g_free (number->token);
1952   g_slice_free (Number, number);
1953 }
1954
1955 static AST *
1956 number_parse (TokenStream  *stream,
1957               va_list      *app,
1958               GError      **error)
1959 {
1960   static const ASTClass number_class = {
1961     number_get_pattern,
1962     maybe_wrapper, number_get_value,
1963     number_free
1964   };
1965   Number *number;
1966
1967   number = g_slice_new (Number);
1968   number->ast.class = &number_class;
1969   number->token = token_stream_get (stream);
1970   token_stream_next (stream);
1971
1972   return (AST *) number;
1973 }
1974
1975 typedef struct
1976 {
1977   AST ast;
1978   gboolean value;
1979 } Boolean;
1980
1981 static gchar *
1982 boolean_get_pattern (AST     *ast,
1983                      GError **error)
1984 {
1985   return g_strdup ("Mb");
1986 }
1987
1988 static GVariant *
1989 boolean_get_value (AST                 *ast,
1990                    const GVariantType  *type,
1991                    GError             **error)
1992 {
1993   Boolean *boolean = (Boolean *) ast;
1994
1995   if (!g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
1996     return ast_type_error (ast, type, error);
1997
1998   return g_variant_new_boolean (boolean->value);
1999 }
2000
2001 static void
2002 boolean_free (AST *ast)
2003 {
2004   Boolean *boolean = (Boolean *) ast;
2005
2006   g_slice_free (Boolean, boolean);
2007 }
2008
2009 static AST *
2010 boolean_new (gboolean value)
2011 {
2012   static const ASTClass boolean_class = {
2013     boolean_get_pattern,
2014     maybe_wrapper, boolean_get_value,
2015     boolean_free
2016   };
2017   Boolean *boolean;
2018
2019   boolean = g_slice_new (Boolean);
2020   boolean->ast.class = &boolean_class;
2021   boolean->value = value;
2022
2023   return (AST *) boolean;
2024 }
2025
2026 typedef struct
2027 {
2028   AST ast;
2029
2030   GVariant *value;
2031 } Positional;
2032
2033 static gchar *
2034 positional_get_pattern (AST     *ast,
2035                         GError **error)
2036 {
2037   Positional *positional = (Positional *) ast;
2038
2039   return g_strdup (g_variant_get_type_string (positional->value));
2040 }
2041
2042 static GVariant *
2043 positional_get_value (AST                 *ast,
2044                       const GVariantType  *type,
2045                       GError             **error)
2046 {
2047   Positional *positional = (Positional *) ast;
2048   GVariant *value;
2049
2050   g_assert (positional->value != NULL);
2051
2052   if G_UNLIKELY (!g_variant_is_of_type (positional->value, type))
2053     return ast_type_error (ast, type, error);
2054
2055   /* NOTE: if _get is called more than once then
2056    * things get messed up with respect to floating refs.
2057    *
2058    * fortunately, this function should only ever get called once.
2059    */
2060   g_assert (positional->value != NULL);
2061   value = positional->value;
2062   positional->value = NULL;
2063
2064   return value;
2065 }
2066
2067 static void
2068 positional_free (AST *ast)
2069 {
2070   Positional *positional = (Positional *) ast;
2071
2072   /* if positional->value is set, just leave it.
2073    * memory management doesn't matter in case of programmer error.
2074    */
2075   g_slice_free (Positional, positional);
2076 }
2077
2078 static AST *
2079 positional_parse (TokenStream  *stream,
2080                   va_list      *app,
2081                   GError      **error)
2082 {
2083   static const ASTClass positional_class = {
2084     positional_get_pattern,
2085     positional_get_value, NULL,
2086     positional_free
2087   };
2088   Positional *positional;
2089   const gchar *endptr;
2090   gchar *token;
2091
2092   token = token_stream_get (stream);
2093   g_assert (token[0] == '%');
2094
2095   positional = g_slice_new (Positional);
2096   positional->ast.class = &positional_class;
2097   positional->value = g_variant_new_va (token + 1, &endptr, app);
2098
2099   if (*endptr || positional->value == NULL)
2100     {
2101       token_stream_set_error (stream, error, TRUE,
2102                               G_VARIANT_PARSE_ERROR_INVALID_FORMAT_STRING,
2103                               "invalid GVariant format string");
2104       /* memory management doesn't matter in case of programmer error. */
2105       return NULL;
2106     }
2107
2108   token_stream_next (stream);
2109   g_free (token);
2110
2111   return (AST *) positional;
2112 }
2113
2114 typedef struct
2115 {
2116   AST ast;
2117
2118   GVariantType *type;
2119   AST *child;
2120 } TypeDecl;
2121
2122 static gchar *
2123 typedecl_get_pattern (AST     *ast,
2124                       GError **error)
2125 {
2126   TypeDecl *decl = (TypeDecl *) ast;
2127
2128   return g_variant_type_dup_string (decl->type);
2129 }
2130
2131 static GVariant *
2132 typedecl_get_value (AST                 *ast,
2133                     const GVariantType  *type,
2134                     GError             **error)
2135 {
2136   TypeDecl *decl = (TypeDecl *) ast;
2137
2138   return ast_get_value (decl->child, type, error);
2139 }
2140
2141 static void
2142 typedecl_free (AST *ast)
2143 {
2144   TypeDecl *decl = (TypeDecl *) ast;
2145
2146   ast_free (decl->child);
2147   g_variant_type_free (decl->type);
2148   g_slice_free (TypeDecl, decl);
2149 }
2150
2151 static AST *
2152 typedecl_parse (TokenStream  *stream,
2153                 va_list      *app,
2154                 GError      **error)
2155 {
2156   static const ASTClass typedecl_class = {
2157     typedecl_get_pattern,
2158     typedecl_get_value, NULL,
2159     typedecl_free
2160   };
2161   GVariantType *type;
2162   TypeDecl *decl;
2163   AST *child;
2164
2165   if (token_stream_peek (stream, '@'))
2166     {
2167       gchar *token;
2168
2169       token = token_stream_get (stream);
2170
2171       if (!g_variant_type_string_is_valid (token + 1))
2172         {
2173           token_stream_set_error (stream, error, TRUE,
2174                                   G_VARIANT_PARSE_ERROR_INVALID_TYPE_STRING,
2175                                   "invalid type declaration");
2176           g_free (token);
2177
2178           return NULL;
2179         }
2180
2181       type = g_variant_type_new (token + 1);
2182
2183       if (!g_variant_type_is_definite (type))
2184         {
2185           token_stream_set_error (stream, error, TRUE,
2186                                   G_VARIANT_PARSE_ERROR_DEFINITE_TYPE_EXPECTED,
2187                                   "type declarations must be definite");
2188           g_variant_type_free (type);
2189           g_free (token);
2190
2191           return NULL;
2192         }
2193
2194       token_stream_next (stream);
2195       g_free (token);
2196     }
2197   else
2198     {
2199       if (token_stream_consume (stream, "boolean"))
2200         type = g_variant_type_copy (G_VARIANT_TYPE_BOOLEAN);
2201
2202       else if (token_stream_consume (stream, "byte"))
2203         type = g_variant_type_copy (G_VARIANT_TYPE_BYTE);
2204
2205       else if (token_stream_consume (stream, "int16"))
2206         type = g_variant_type_copy (G_VARIANT_TYPE_INT16);
2207
2208       else if (token_stream_consume (stream, "uint16"))
2209         type = g_variant_type_copy (G_VARIANT_TYPE_UINT16);
2210
2211       else if (token_stream_consume (stream, "int32"))
2212         type = g_variant_type_copy (G_VARIANT_TYPE_INT32);
2213
2214       else if (token_stream_consume (stream, "handle"))
2215         type = g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
2216
2217       else if (token_stream_consume (stream, "uint32"))
2218         type = g_variant_type_copy (G_VARIANT_TYPE_UINT32);
2219
2220       else if (token_stream_consume (stream, "int64"))
2221         type = g_variant_type_copy (G_VARIANT_TYPE_INT64);
2222
2223       else if (token_stream_consume (stream, "uint64"))
2224         type = g_variant_type_copy (G_VARIANT_TYPE_UINT64);
2225
2226       else if (token_stream_consume (stream, "double"))
2227         type = g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
2228
2229       else if (token_stream_consume (stream, "string"))
2230         type = g_variant_type_copy (G_VARIANT_TYPE_STRING);
2231
2232       else if (token_stream_consume (stream, "objectpath"))
2233         type = g_variant_type_copy (G_VARIANT_TYPE_OBJECT_PATH);
2234
2235       else if (token_stream_consume (stream, "signature"))
2236         type = g_variant_type_copy (G_VARIANT_TYPE_SIGNATURE);
2237
2238       else
2239         {
2240           token_stream_set_error (stream, error, TRUE,
2241                                   G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD,
2242                                   "unknown keyword");
2243           return NULL;
2244         }
2245     }
2246
2247   if ((child = parse (stream, app, error)) == NULL)
2248     {
2249       g_variant_type_free (type);
2250       return NULL;
2251     }
2252
2253   decl = g_slice_new (TypeDecl);
2254   decl->ast.class = &typedecl_class;
2255   decl->type = type;
2256   decl->child = child;
2257
2258   return (AST *) decl;
2259 }
2260
2261 static AST *
2262 parse (TokenStream  *stream,
2263        va_list      *app,
2264        GError      **error)
2265 {
2266   SourceRef source_ref;
2267   AST *result;
2268
2269   token_stream_prepare (stream);
2270   token_stream_start_ref (stream, &source_ref);
2271
2272   if (token_stream_peek (stream, '['))
2273     result = array_parse (stream, app, error);
2274
2275   else if (token_stream_peek (stream, '('))
2276     result = tuple_parse (stream, app, error);
2277
2278   else if (token_stream_peek (stream, '<'))
2279     result = variant_parse (stream, app, error);
2280
2281   else if (token_stream_peek (stream, '{'))
2282     result = dictionary_parse (stream, app, error);
2283
2284   else if (app && token_stream_peek (stream, '%'))
2285     result = positional_parse (stream, app, error);
2286
2287   else if (token_stream_consume (stream, "true"))
2288     result = boolean_new (TRUE);
2289
2290   else if (token_stream_consume (stream, "false"))
2291     result = boolean_new (FALSE);
2292
2293   else if (token_stream_is_numeric (stream) ||
2294            token_stream_peek_string (stream, "inf") ||
2295            token_stream_peek_string (stream, "nan"))
2296     result = number_parse (stream, app, error);
2297
2298   else if (token_stream_peek (stream, 'n') ||
2299            token_stream_peek (stream, 'j'))
2300     result = maybe_parse (stream, app, error);
2301
2302   else if (token_stream_peek (stream, '@') ||
2303            token_stream_is_keyword (stream))
2304     result = typedecl_parse (stream, app, error);
2305
2306   else if (token_stream_peek (stream, '\'') ||
2307            token_stream_peek (stream, '"'))
2308     result = string_parse (stream, app, error);
2309
2310   else if (token_stream_peek2 (stream, 'b', '\'') ||
2311            token_stream_peek2 (stream, 'b', '"'))
2312     result = bytestring_parse (stream, app, error);
2313
2314   else
2315     {
2316       token_stream_set_error (stream, error, FALSE,
2317                               G_VARIANT_PARSE_ERROR_VALUE_EXPECTED,
2318                               "expected value");
2319       return NULL;
2320     }
2321
2322   if (result != NULL)
2323     {
2324       token_stream_end_ref (stream, &source_ref);
2325       result->source_ref = source_ref;
2326     }
2327
2328   return result;
2329 }
2330
2331 /**
2332  * g_variant_parse:
2333  * @type: (nullable): a #GVariantType, or %NULL
2334  * @text: a string containing a GVariant in text form
2335  * @limit: (nullable): a pointer to the end of @text, or %NULL
2336  * @endptr: (nullable): a location to store the end pointer, or %NULL
2337  * @error: (nullable): a pointer to a %NULL #GError pointer, or %NULL
2338  *
2339  * Parses a #GVariant from a text representation.
2340  *
2341  * A single #GVariant is parsed from the content of @text.
2342  *
2343  * The format is described [here][gvariant-text].
2344  *
2345  * The memory at @limit will never be accessed and the parser behaves as
2346  * if the character at @limit is the nul terminator.  This has the
2347  * effect of bounding @text.
2348  *
2349  * If @endptr is non-%NULL then @text is permitted to contain data
2350  * following the value that this function parses and @endptr will be
2351  * updated to point to the first character past the end of the text
2352  * parsed by this function.  If @endptr is %NULL and there is extra data
2353  * then an error is returned.
2354  *
2355  * If @type is non-%NULL then the value will be parsed to have that
2356  * type.  This may result in additional parse errors (in the case that
2357  * the parsed value doesn't fit the type) but may also result in fewer
2358  * errors (in the case that the type would have been ambiguous, such as
2359  * with empty arrays).
2360  *
2361  * In the event that the parsing is successful, the resulting #GVariant
2362  * is returned. It is never floating, and must be freed with
2363  * g_variant_unref().
2364  *
2365  * In case of any error, %NULL will be returned.  If @error is non-%NULL
2366  * then it will be set to reflect the error that occurred.
2367  *
2368  * Officially, the language understood by the parser is "any string
2369  * produced by g_variant_print()".
2370  *
2371  * Returns: a non-floating reference to a #GVariant, or %NULL
2372  **/
2373 GVariant *
2374 g_variant_parse (const GVariantType  *type,
2375                  const gchar         *text,
2376                  const gchar         *limit,
2377                  const gchar        **endptr,
2378                  GError             **error)
2379 {
2380   TokenStream stream = { 0, };
2381   GVariant *result = NULL;
2382   AST *ast;
2383
2384   g_return_val_if_fail (text != NULL, NULL);
2385   g_return_val_if_fail (text == limit || text != NULL, NULL);
2386
2387   stream.start = text;
2388   stream.stream = text;
2389   stream.end = limit;
2390
2391   if ((ast = parse (&stream, NULL, error)))
2392     {
2393       if (type == NULL)
2394         result = ast_resolve (ast, error);
2395       else
2396         result = ast_get_value (ast, type, error);
2397
2398       if (result != NULL)
2399         {
2400           g_variant_ref_sink (result);
2401
2402           if (endptr == NULL)
2403             {
2404               while (stream.stream != limit &&
2405                      g_ascii_isspace (*stream.stream))
2406                 stream.stream++;
2407
2408               if (stream.stream != limit && *stream.stream != '\0')
2409                 {
2410                   SourceRef ref = { stream.stream - text,
2411                                     stream.stream - text };
2412
2413                   parser_set_error (error, &ref, NULL,
2414                                     G_VARIANT_PARSE_ERROR_INPUT_NOT_AT_END,
2415                                     "expected end of input");
2416                   g_variant_unref (result);
2417
2418                   result = NULL;
2419                 }
2420             }
2421           else
2422             *endptr = stream.stream;
2423         }
2424
2425       ast_free (ast);
2426     }
2427
2428   return result;
2429 }
2430
2431 /**
2432  * g_variant_new_parsed_va:
2433  * @format: a text format #GVariant
2434  * @app: a pointer to a #va_list
2435  *
2436  * Parses @format and returns the result.
2437  *
2438  * This is the version of g_variant_new_parsed() intended to be used
2439  * from libraries.
2440  *
2441  * The return value will be floating if it was a newly created GVariant
2442  * instance.  In the case that @format simply specified the collection
2443  * of a #GVariant pointer (eg: @format was "%*") then the collected
2444  * #GVariant pointer will be returned unmodified, without adding any
2445  * additional references.
2446  *
2447  * Note that the arguments in @app must be of the correct width for their types
2448  * specified in @format when collected into the #va_list. See
2449  * the [GVariant varargs documentation][gvariant-varargs].
2450  *
2451  * In order to behave correctly in all cases it is necessary for the
2452  * calling function to g_variant_ref_sink() the return result before
2453  * returning control to the user that originally provided the pointer.
2454  * At this point, the caller will have their own full reference to the
2455  * result.  This can also be done by adding the result to a container,
2456  * or by passing it to another g_variant_new() call.
2457  *
2458  * Returns: a new, usually floating, #GVariant
2459  **/
2460 GVariant *
2461 g_variant_new_parsed_va (const gchar *format,
2462                          va_list     *app)
2463 {
2464   TokenStream stream = { 0, };
2465   GVariant *result = NULL;
2466   GError *error = NULL;
2467   AST *ast;
2468
2469   g_return_val_if_fail (format != NULL, NULL);
2470   g_return_val_if_fail (app != NULL, NULL);
2471
2472   stream.start = format;
2473   stream.stream = format;
2474   stream.end = NULL;
2475
2476   if ((ast = parse (&stream, app, &error)))
2477     {
2478       result = ast_resolve (ast, &error);
2479       ast_free (ast);
2480     }
2481
2482   if (result == NULL)
2483     g_error ("g_variant_new_parsed: %s", error->message);
2484
2485   if (*stream.stream)
2486     g_error ("g_variant_new_parsed: trailing text after value");
2487
2488   return result;
2489 }
2490
2491 /**
2492  * g_variant_new_parsed:
2493  * @format: a text format #GVariant
2494  * @...: arguments as per @format
2495  *
2496  * Parses @format and returns the result.
2497  *
2498  * @format must be a text format #GVariant with one extension: at any
2499  * point that a value may appear in the text, a '%' character followed
2500  * by a GVariant format string (as per g_variant_new()) may appear.  In
2501  * that case, the same arguments are collected from the argument list as
2502  * g_variant_new() would have collected.
2503  *
2504  * Note that the arguments must be of the correct width for their types
2505  * specified in @format. This can be achieved by casting them. See
2506  * the [GVariant varargs documentation][gvariant-varargs].
2507  *
2508  * Consider this simple example:
2509  * |[<!-- language="C" --> 
2510  *  g_variant_new_parsed ("[('one', 1), ('two', %i), (%s, 3)]", 2, "three");
2511  * ]|
2512  *
2513  * In the example, the variable argument parameters are collected and
2514  * filled in as if they were part of the original string to produce the
2515  * result of
2516  * |[<!-- language="C" --> 
2517  * [('one', 1), ('two', 2), ('three', 3)]
2518  * ]|
2519  *
2520  * This function is intended only to be used with @format as a string
2521  * literal.  Any parse error is fatal to the calling process.  If you
2522  * want to parse data from untrusted sources, use g_variant_parse().
2523  *
2524  * You may not use this function to return, unmodified, a single
2525  * #GVariant pointer from the argument list.  ie: @format may not solely
2526  * be anything along the lines of "%*", "%?", "\%r", or anything starting
2527  * with "%@".
2528  *
2529  * Returns: a new floating #GVariant instance
2530  **/
2531 GVariant *
2532 g_variant_new_parsed (const gchar *format,
2533                       ...)
2534 {
2535   GVariant *result;
2536   va_list ap;
2537
2538   va_start (ap, format);
2539   result = g_variant_new_parsed_va (format, &ap);
2540   va_end (ap);
2541
2542   return result;
2543 }
2544
2545 /**
2546  * g_variant_builder_add_parsed:
2547  * @builder: a #GVariantBuilder
2548  * @format: a text format #GVariant
2549  * @...: arguments as per @format
2550  *
2551  * Adds to a #GVariantBuilder.
2552  *
2553  * This call is a convenience wrapper that is exactly equivalent to
2554  * calling g_variant_new_parsed() followed by
2555  * g_variant_builder_add_value().
2556  *
2557  * Note that the arguments must be of the correct width for their types
2558  * specified in @format_string. This can be achieved by casting them. See
2559  * the [GVariant varargs documentation][gvariant-varargs].
2560  *
2561  * This function might be used as follows:
2562  *
2563  * |[<!-- language="C" --> 
2564  * GVariant *
2565  * make_pointless_dictionary (void)
2566  * {
2567  *   GVariantBuilder builder;
2568  *   int i;
2569  *
2570  *   g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
2571  *   g_variant_builder_add_parsed (&builder, "{'width', <%i>}", 600);
2572  *   g_variant_builder_add_parsed (&builder, "{'title', <%s>}", "foo");
2573  *   g_variant_builder_add_parsed (&builder, "{'transparency', <0.5>}");
2574  *   return g_variant_builder_end (&builder);
2575  * }
2576  * ]|
2577  *
2578  * Since: 2.26
2579  */
2580 void
2581 g_variant_builder_add_parsed (GVariantBuilder *builder,
2582                               const gchar     *format,
2583                               ...)
2584 {
2585   va_list ap;
2586
2587   va_start (ap, format);
2588   g_variant_builder_add_value (builder, g_variant_new_parsed_va (format, &ap));
2589   va_end (ap);
2590 }
2591
2592 static gboolean
2593 parse_num (const gchar *num,
2594            const gchar *limit,
2595            gint        *result)
2596 {
2597   gchar *endptr;
2598   gint64 bignum;
2599
2600   bignum = g_ascii_strtoll (num, &endptr, 10);
2601
2602   if (endptr != limit)
2603     return FALSE;
2604
2605   if (bignum < 0 || bignum > G_MAXINT)
2606     return FALSE;
2607
2608   *result = bignum;
2609
2610   return TRUE;
2611 }
2612
2613 static void
2614 add_last_line (GString     *err,
2615                const gchar *str)
2616 {
2617   const gchar *last_nl;
2618   gchar *chomped;
2619   gint i;
2620
2621   /* This is an error at the end of input.  If we have a file
2622    * with newlines, that's probably the empty string after the
2623    * last newline, which is not the most useful thing to show.
2624    *
2625    * Instead, show the last line of non-whitespace that we have
2626    * and put the pointer at the end of it.
2627    */
2628   chomped = g_strchomp (g_strdup (str));
2629   last_nl = strrchr (chomped, '\n');
2630   if (last_nl == NULL)
2631     last_nl = chomped;
2632   else
2633     last_nl++;
2634
2635   /* Print the last line like so:
2636    *
2637    *   [1, 2, 3,
2638    *            ^
2639    */
2640   g_string_append (err, "  ");
2641   if (last_nl[0])
2642     g_string_append (err, last_nl);
2643   else
2644     g_string_append (err, "(empty input)");
2645   g_string_append (err, "\n  ");
2646   for (i = 0; last_nl[i]; i++)
2647     g_string_append_c (err, ' ');
2648   g_string_append (err, "^\n");
2649   g_free (chomped);
2650 }
2651
2652 static void
2653 add_lines_from_range (GString     *err,
2654                       const gchar *str,
2655                       const gchar *start1,
2656                       const gchar *end1,
2657                       const gchar *start2,
2658                       const gchar *end2)
2659 {
2660   while (str < end1 || str < end2)
2661     {
2662       const gchar *nl;
2663
2664       nl = str + strcspn (str, "\n");
2665
2666       if ((start1 < nl && str < end1) || (start2 < nl && str < end2))
2667         {
2668           const gchar *s;
2669
2670           /* We're going to print this line */
2671           g_string_append (err, "  ");
2672           g_string_append_len (err, str, nl - str);
2673           g_string_append (err, "\n  ");
2674
2675           /* And add underlines... */
2676           for (s = str; s < nl; s++)
2677             {
2678               if ((start1 <= s && s < end1) || (start2 <= s && s < end2))
2679                 g_string_append_c (err, '^');
2680               else
2681                 g_string_append_c (err, ' ');
2682             }
2683           g_string_append_c (err, '\n');
2684         }
2685
2686       if (!*nl)
2687         break;
2688
2689       str = nl + 1;
2690     }
2691 }
2692
2693 /**
2694  * g_variant_parse_error_print_context:
2695  * @error: a #GError from the #GVariantParseError domain
2696  * @source_str: the string that was given to the parser
2697  *
2698  * Pretty-prints a message showing the context of a #GVariant parse
2699  * error within the string for which parsing was attempted.
2700  *
2701  * The resulting string is suitable for output to the console or other
2702  * monospace media where newlines are treated in the usual way.
2703  *
2704  * The message will typically look something like one of the following:
2705  *
2706  * |[
2707  * unterminated string constant:
2708  *   (1, 2, 3, 'abc
2709  *             ^^^^
2710  * ]|
2711  *
2712  * or
2713  *
2714  * |[
2715  * unable to find a common type:
2716  *   [1, 2, 3, 'str']
2717  *    ^        ^^^^^
2718  * ]|
2719  *
2720  * The format of the message may change in a future version.
2721  *
2722  * @error must have come from a failed attempt to g_variant_parse() and
2723  * @source_str must be exactly the same string that caused the error.
2724  * If @source_str was not nul-terminated when you passed it to
2725  * g_variant_parse() then you must add nul termination before using this
2726  * function.
2727  *
2728  * Returns: (transfer full): the printed message
2729  *
2730  * Since: 2.40
2731  **/
2732 gchar *
2733 g_variant_parse_error_print_context (GError      *error,
2734                                      const gchar *source_str)
2735 {
2736   const gchar *colon, *dash, *comma;
2737   gboolean success = FALSE;
2738   GString *err;
2739
2740   g_return_val_if_fail (error->domain == G_VARIANT_PARSE_ERROR, FALSE);
2741
2742   /* We can only have a limited number of possible types of ranges
2743    * emitted from the parser:
2744    *
2745    *  - a:          -- usually errors from the tokeniser (eof, invalid char, etc.)
2746    *  - a-b:        -- usually errors from handling one single token
2747    *  - a-b,c-d:    -- errors involving two tokens (ie: type inferencing)
2748    *
2749    * We never see, for example "a,c".
2750    */
2751
2752   colon = strchr (error->message, ':');
2753   dash = strchr (error->message, '-');
2754   comma = strchr (error->message, ',');
2755
2756   if (!colon)
2757     return NULL;
2758
2759   err = g_string_new (colon + 1);
2760   g_string_append (err, ":\n");
2761
2762   if (dash == NULL || colon < dash)
2763     {
2764       gint point;
2765
2766       /* we have a single point */
2767       if (!parse_num (error->message, colon, &point))
2768         goto out;
2769
2770       if (point >= strlen (source_str))
2771         /* the error is at the end of the input */
2772         add_last_line (err, source_str);
2773       else
2774         /* otherwise just treat it as a error at a thin range */
2775         add_lines_from_range (err, source_str, source_str + point, source_str + point + 1, NULL, NULL);
2776     }
2777   else
2778     {
2779       /* We have one or two ranges... */
2780       if (comma && comma < colon)
2781         {
2782           gint start1, end1, start2, end2;
2783           const gchar *dash2;
2784
2785           /* Two ranges */
2786           dash2 = strchr (comma, '-');
2787
2788           if (!parse_num (error->message, dash, &start1) || !parse_num (dash + 1, comma, &end1) ||
2789               !parse_num (comma + 1, dash2, &start2) || !parse_num (dash2 + 1, colon, &end2))
2790             goto out;
2791
2792           add_lines_from_range (err, source_str,
2793                                 source_str + start1, source_str + end1,
2794                                 source_str + start2, source_str + end2);
2795         }
2796       else
2797         {
2798           gint start, end;
2799
2800           /* One range */
2801           if (!parse_num (error->message, dash, &start) || !parse_num (dash + 1, colon, &end))
2802             goto out;
2803
2804           add_lines_from_range (err, source_str, source_str + start, source_str + end, NULL, NULL);
2805         }
2806     }
2807
2808   success = TRUE;
2809
2810 out:
2811   return g_string_free (err, !success);
2812 }