GVariant: add support for single precision floats
[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 of the licence, 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->stream[1] == '"')
201         {
202           for (end = stream->stream + 2; end != stream->end; end++)
203             if (*end == stream->stream[1] || *end == '\0' ||
204                 (*end == '\\' && (++end == stream->end || *end == '\0')))
205               break;
206
207           if (end != stream->end && *end)
208             end++;
209           break;
210         }
211
212       else    /* ↓↓↓ */;
213
214     case 'a': /* 'b' */ case 'c': case 'd': case 'e': case 'f':
215     case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
216     case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
217     case 's': case 't': case 'u': case 'v': case 'w': case 'x':
218     case 'y': case 'z':
219       for (end = stream->stream; end != stream->end; end++)
220         if (!g_ascii_isalnum (*end))
221           break;
222       break;
223
224     case '\'': case '"':
225       for (end = stream->stream + 1; end != stream->end; end++)
226         if (*end == stream->stream[0] || *end == '\0' ||
227             (*end == '\\' && (++end == stream->end || *end == '\0')))
228           break;
229
230       if (end != stream->end && *end)
231         end++;
232       break;
233
234     case '@': case '%':
235       /* stop at the first space, comma, colon or unmatched bracket.
236        * deals nicely with cases like (%i, %i) or {%i: %i}.
237        * Also: ] and > are never in format strings.
238        */
239       for (end = stream->stream + 1;
240            end != stream->end && *end != ',' &&
241            *end != ':' && *end != '>' && *end != ']' && !g_ascii_isspace (*end);
242            end++)
243
244         if (*end == '(' || *end == '{')
245           brackets++;
246
247         else if ((*end == ')' || *end == '}') && !brackets--)
248           break;
249
250       break;
251
252     default:
253       end = stream->stream + 1;
254       break;
255     }
256
257   stream->this = stream->stream;
258   stream->stream = end;
259
260   return TRUE;
261 }
262
263 static void
264 token_stream_next (TokenStream *stream)
265 {
266   stream->this = NULL;
267 }
268
269 static gboolean
270 token_stream_peek (TokenStream *stream,
271                    gchar        first_char)
272 {
273   if (!token_stream_prepare (stream))
274     return FALSE;
275
276   return stream->this[0] == first_char;
277 }
278
279 static gboolean
280 token_stream_peek2 (TokenStream *stream,
281                     gchar        first_char,
282                     gchar        second_char)
283 {
284   if (!token_stream_prepare (stream))
285     return FALSE;
286
287   return stream->this[0] == first_char &&
288          stream->this[1] == second_char;
289 }
290
291 static gboolean
292 token_stream_is_keyword (TokenStream *stream)
293 {
294   if (!token_stream_prepare (stream))
295     return FALSE;
296
297   return g_ascii_isalpha (stream->this[0]) &&
298          g_ascii_isalpha (stream->this[1]);
299 }
300
301 static gboolean
302 token_stream_is_numeric (TokenStream *stream)
303 {
304   if (!token_stream_prepare (stream))
305     return FALSE;
306
307   return (g_ascii_isdigit (stream->this[0]) ||
308           stream->this[0] == '-' ||
309           stream->this[0] == '+' ||
310           stream->this[0] == '.');
311 }
312
313 static gboolean
314 token_stream_peek_string (TokenStream *stream,
315                           const gchar *token)
316 {
317   gint length = strlen (token);
318
319   return token_stream_prepare (stream) &&
320          stream->stream - stream->this == length &&
321          memcmp (stream->this, token, length) == 0;
322 }
323
324 static gboolean
325 token_stream_consume (TokenStream *stream,
326                       const gchar *token)
327 {
328   if (!token_stream_peek_string (stream, token))
329     return FALSE;
330
331   token_stream_next (stream);
332   return TRUE;
333 }
334
335 static gboolean
336 token_stream_require (TokenStream  *stream,
337                       const gchar  *token,
338                       const gchar  *purpose,
339                       GError      **error)
340 {
341
342   if (!token_stream_consume (stream, token))
343     {
344       token_stream_set_error (stream, error, FALSE,
345                               G_VARIANT_PARSE_ERROR_UNEXPECTED_TOKEN,
346                               "expected '%s'%s", token, purpose);
347       return FALSE;
348     }
349
350   return TRUE;
351 }
352
353 static void
354 token_stream_assert (TokenStream *stream,
355                      const gchar *token)
356 {
357   gboolean correct_token;
358
359   correct_token = token_stream_consume (stream, token);
360   g_assert (correct_token);
361 }
362
363 static gchar *
364 token_stream_get (TokenStream *stream)
365 {
366   gchar *result;
367
368   if (!token_stream_prepare (stream))
369     return NULL;
370
371   result = g_strndup (stream->this, stream->stream - stream->this);
372
373   return result;
374 }
375
376 static void
377 token_stream_start_ref (TokenStream *stream,
378                         SourceRef   *ref)
379 {
380   token_stream_prepare (stream);
381   ref->start = stream->this - stream->start;
382 }
383
384 static void
385 token_stream_end_ref (TokenStream *stream,
386                       SourceRef   *ref)
387 {
388   ref->end = stream->stream - stream->start;
389 }
390
391 static void
392 pattern_copy (gchar       **out,
393               const gchar **in)
394 {
395   gint brackets = 0;
396
397   while (**in == 'a' || **in == 'm' || **in == 'M')
398     *(*out)++ = *(*in)++;
399
400   do
401     {
402       if (**in == '(' || **in == '{')
403         brackets++;
404
405       else if (**in == ')' || **in == '}')
406         brackets--;
407
408       *(*out)++ = *(*in)++;
409     }
410   while (brackets);
411 }
412
413 static gchar *
414 pattern_coalesce (const gchar *left,
415                   const gchar *right)
416 {
417   gchar *result;
418   gchar *out;
419
420   /* the length of the output is loosely bound by the sum of the input
421    * lengths, not simply the greater of the two lengths.
422    *
423    *   (*(iii)) + ((iii)*) ((iii)(iii))
424    *
425    *      8     +    8    =  12
426    */
427   out = result = g_malloc (strlen (left) + strlen (right));
428
429   while (*left && *right)
430     {
431       if (*left == *right)
432         {
433           *out++ = *left++;
434           right++;
435         }
436
437       else
438         {
439           const gchar **one = &left, **the_other = &right;
440
441          again:
442           if (**one == '*' && **the_other != ')')
443             {
444               pattern_copy (&out, the_other);
445               (*one)++;
446             }
447
448           else if (**one == 'M' && **the_other == 'm')
449             {
450               *out++ = *(*the_other)++;
451             }
452
453           else if (**one == 'M' && **the_other != 'm')
454             {
455               (*one)++;
456             }
457
458           else if (**one == 'N' && strchr ("ynqiuxthfd", **the_other))
459             {
460               *out++ = *(*the_other)++;
461               (*one)++;
462             }
463
464           else if (**one == 'D' && (**the_other == 'f' || **the_other == 'd'))
465             {
466               *out++ = *(*the_other)++;
467               (*one)++;
468             }
469
470           else if (**one == 'S' && strchr ("sog", **the_other))
471             {
472               *out++ = *(*the_other)++;
473               (*one)++;
474             }
475
476           else if (one == &left)
477             {
478               one = &right, the_other = &left;
479               goto again;
480             }
481
482           else
483             break;
484         }
485     }
486
487   if (*left || *right)
488     {
489       g_free (result);
490       result = NULL;
491     }
492   else
493     *out++ = '\0';
494
495   return result;
496 }
497
498 typedef struct _AST AST;
499 typedef gchar *    (*get_pattern_func)    (AST                 *ast,
500                                            GError             **error);
501 typedef GVariant * (*get_value_func)      (AST                 *ast,
502                                            const GVariantType  *type,
503                                            GError             **error);
504 typedef GVariant * (*get_base_value_func) (AST                 *ast,
505                                            const GVariantType  *type,
506                                            GError             **error);
507 typedef void       (*free_func)           (AST                 *ast);
508
509 typedef struct
510 {
511   gchar *    (* get_pattern)    (AST                 *ast,
512                                  GError             **error);
513   GVariant * (* get_value)      (AST                 *ast,
514                                  const GVariantType  *type,
515                                  GError             **error);
516   GVariant * (* get_base_value) (AST                 *ast,
517                                  const GVariantType  *type,
518                                  GError             **error);
519   void       (* free)           (AST                 *ast);
520 } ASTClass;
521
522 struct _AST
523 {
524   const ASTClass *class;
525   SourceRef source_ref;
526 };
527
528 static gchar *
529 ast_get_pattern (AST     *ast,
530                  GError **error)
531 {
532   return ast->class->get_pattern (ast, error);
533 }
534
535 static GVariant *
536 ast_get_value (AST                 *ast,
537                const GVariantType  *type,
538                GError             **error)
539 {
540   return ast->class->get_value (ast, type, error);
541 }
542
543 static void
544 ast_free (AST *ast)
545 {
546   ast->class->free (ast);
547 }
548
549 G_GNUC_PRINTF(5, 6)
550 static void
551 ast_set_error (AST          *ast,
552                GError      **error,
553                AST          *other_ast,
554                gint          code,
555                const gchar  *format,
556                ...)
557 {
558   va_list ap;
559
560   va_start (ap, format);
561   parser_set_error_va (error, &ast->source_ref,
562                        other_ast ? & other_ast->source_ref : NULL,
563                        code,
564                        format, ap);
565   va_end (ap);
566 }
567
568 static GVariant *
569 ast_type_error (AST                 *ast,
570                 const GVariantType  *type,
571                 GError             **error)
572 {
573   gchar *typestr;
574
575   typestr = g_variant_type_dup_string (type);
576   ast_set_error (ast, error, NULL,
577                  G_VARIANT_PARSE_ERROR_TYPE_ERROR,
578                  "can not parse as value of type '%s'",
579                  typestr);
580   g_free (typestr);
581
582   return NULL;
583 }
584
585 static GVariant *
586 ast_resolve (AST     *ast,
587              GError **error)
588 {
589   GVariant *value;
590   gchar *pattern;
591   gint i, j = 0;
592
593   pattern = ast_get_pattern (ast, error);
594
595   if (pattern == NULL)
596     return NULL;
597
598   /* choose reasonable defaults
599    *
600    *   1) favour non-maybe values where possible
601    *   2) default type for strings is 's'
602    *   3) default type for integers is 'i'
603    */
604   for (i = 0; pattern[i]; i++)
605     switch (pattern[i])
606       {
607       case '*':
608         ast_set_error (ast, error, NULL,
609                        G_VARIANT_PARSE_ERROR_CANNOT_INFER_TYPE,
610                        "unable to infer type");
611         g_free (pattern);
612         return NULL;
613
614       case 'M':
615         break;
616
617       case 'S':
618         pattern[j++] = 's';
619         break;
620
621       case 'N':
622         pattern[j++] = 'i';
623         break;
624
625       case 'D':
626         pattern[j++] = 'd';
627         break;
628
629       default:
630         pattern[j++] = pattern[i];
631         break;
632       }
633   pattern[j++] = '\0';
634
635   value = ast_get_value (ast, G_VARIANT_TYPE (pattern), error);
636   g_free (pattern);
637
638   return value;
639 }
640
641
642 static AST *parse (TokenStream  *stream,
643                    va_list      *app,
644                    GError      **error);
645
646 static void
647 ast_array_append (AST  ***array,
648                   gint   *n_items,
649                   AST    *ast)
650 {
651   if ((*n_items & (*n_items - 1)) == 0)
652     *array = g_renew (AST *, *array, *n_items ? 2 ** n_items : 1);
653
654   (*array)[(*n_items)++] = ast;
655 }
656
657 static void
658 ast_array_free (AST  **array,
659                 gint   n_items)
660 {
661   gint i;
662
663   for (i = 0; i < n_items; i++)
664     ast_free (array[i]);
665   g_free (array);
666 }
667
668 static gchar *
669 ast_array_get_pattern (AST    **array,
670                        gint     n_items,
671                        GError **error)
672 {
673   gchar *pattern;
674   gint i;
675
676   pattern = ast_get_pattern (array[0], error);
677
678   if (pattern == NULL)
679     return NULL;
680
681   for (i = 1; i < n_items; i++)
682     {
683       gchar *tmp, *merged;
684
685       tmp = ast_get_pattern (array[i], error);
686
687       if (tmp == NULL)
688         {
689           g_free (pattern);
690           return NULL;
691         }
692
693       merged = pattern_coalesce (pattern, tmp);
694       g_free (pattern);
695       pattern = merged;
696
697       if (merged == NULL)
698         /* set coalescence implies pairwise coalescence (i think).
699          * we should therefore be able to trace the failure to a single
700          * pair of values.
701          */
702         {
703           int j = 0;
704
705           while (TRUE)
706             {
707               gchar *tmp2;
708               gchar *m;
709
710               /* if 'j' reaches 'i' then we failed to find the pair */
711               g_assert (j < i);
712
713               tmp2 = ast_get_pattern (array[j], NULL);
714               g_assert (tmp2 != NULL);
715
716               m = pattern_coalesce (tmp, tmp2);
717               g_free (tmp2);
718               g_free (m);
719
720               if (m == NULL)
721                 {
722                   /* we found a conflict between 'i' and 'j'.
723                    *
724                    * report the error.  note: 'j' is first.
725                    */
726                   ast_set_error (array[j], error, array[i],
727                                  G_VARIANT_PARSE_ERROR_NO_COMMON_TYPE,
728                                  "unable to find a common type");
729                   g_free (tmp);
730                   return NULL;
731                 }
732
733               j++;
734             }
735
736         }
737
738       g_free (tmp);
739     }
740
741   return pattern;
742 }
743
744 typedef struct
745 {
746   AST ast;
747
748   AST *child;
749 } Maybe;
750
751 static gchar *
752 maybe_get_pattern (AST     *ast,
753                    GError **error)
754 {
755   Maybe *maybe = (Maybe *) ast;
756
757   if (maybe->child != NULL)
758     {
759       gchar *child_pattern;
760       gchar *pattern;
761
762       child_pattern = ast_get_pattern (maybe->child, error);
763
764       if (child_pattern == NULL)
765         return NULL;
766
767       pattern = g_strdup_printf ("m%s", child_pattern);
768       g_free (child_pattern);
769
770       return pattern;
771     }
772
773   return g_strdup ("m*");
774 }
775
776 static GVariant *
777 maybe_get_value (AST                 *ast,
778                  const GVariantType  *type,
779                  GError             **error)
780 {
781   Maybe *maybe = (Maybe *) ast;
782   GVariant *value;
783
784   if (!g_variant_type_is_maybe (type))
785     return ast_type_error (ast, type, error);
786
787   type = g_variant_type_element (type);
788
789   if (maybe->child)
790     {
791       value = ast_get_value (maybe->child, type, error);
792
793       if (value == NULL)
794         return NULL;
795     }
796   else
797     value = NULL;
798
799   return g_variant_new_maybe (type, value);
800 }
801
802 static void
803 maybe_free (AST *ast)
804 {
805   Maybe *maybe = (Maybe *) ast;
806
807   if (maybe->child != NULL)
808     ast_free (maybe->child);
809
810   g_slice_free (Maybe, maybe);
811 }
812
813 static AST *
814 maybe_parse (TokenStream  *stream,
815              va_list      *app,
816              GError      **error)
817 {
818   static const ASTClass maybe_class = {
819     maybe_get_pattern,
820     maybe_get_value, NULL,
821     maybe_free
822   };
823   AST *child = NULL;
824   Maybe *maybe;
825
826   if (token_stream_consume (stream, "just"))
827     {
828       child = parse (stream, app, error);
829       if (child == NULL)
830         return NULL;
831     }
832
833   else if (!token_stream_consume (stream, "nothing"))
834     {
835       token_stream_set_error (stream, error, TRUE,
836                               G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD,
837                               "unknown keyword");
838       return NULL;
839     }
840
841   maybe = g_slice_new (Maybe);
842   maybe->ast.class = &maybe_class;
843   maybe->child = child;
844
845   return (AST *) maybe;
846 }
847
848 static GVariant *
849 maybe_wrapper (AST                 *ast,
850                const GVariantType  *type,
851                GError             **error)
852 {
853   const GVariantType *t;
854   GVariant *value;
855   int depth;
856
857   for (depth = 0, t = type;
858        g_variant_type_is_maybe (t);
859        depth++, t = g_variant_type_element (t));
860
861   value = ast->class->get_base_value (ast, t, error);
862
863   if (value == NULL)
864     return NULL;
865
866   while (depth--)
867     value = g_variant_new_maybe (NULL, value);
868
869   return value;
870 }
871
872 typedef struct
873 {
874   AST ast;
875
876   AST **children;
877   gint n_children;
878 } Array;
879
880 static gchar *
881 array_get_pattern (AST     *ast,
882                    GError **error)
883 {
884   Array *array = (Array *) ast;
885   gchar *pattern;
886   gchar *result;
887
888   if (array->n_children == 0)
889     return g_strdup ("Ma*");
890
891   pattern = ast_array_get_pattern (array->children, array->n_children, error);
892
893   if (pattern == NULL)
894     return NULL;
895
896   result = g_strdup_printf ("Ma%s", pattern);
897   g_free (pattern);
898
899   return result;
900 }
901
902 static GVariant *
903 array_get_value (AST                 *ast,
904                  const GVariantType  *type,
905                  GError             **error)
906 {
907   Array *array = (Array *) ast;
908   const GVariantType *childtype;
909   GVariantBuilder builder;
910   gint i;
911
912   if (!g_variant_type_is_array (type))
913     return ast_type_error (ast, type, error);
914
915   g_variant_builder_init (&builder, type);
916   childtype = g_variant_type_element (type);
917
918   for (i = 0; i < array->n_children; i++)
919     {
920       GVariant *child;
921
922       if (!(child = ast_get_value (array->children[i], childtype, error)))
923         {
924           g_variant_builder_clear (&builder);
925           return NULL;
926         }
927
928       g_variant_builder_add_value (&builder, child);
929     }
930
931   return g_variant_builder_end (&builder);
932 }
933
934 static void
935 array_free (AST *ast)
936 {
937   Array *array = (Array *) ast;
938
939   ast_array_free (array->children, array->n_children);
940   g_slice_free (Array, array);
941 }
942
943 static AST *
944 array_parse (TokenStream  *stream,
945              va_list      *app,
946              GError      **error)
947 {
948   static const ASTClass array_class = {
949     array_get_pattern,
950     maybe_wrapper, array_get_value,
951     array_free
952   };
953   gboolean need_comma = FALSE;
954   Array *array;
955
956   array = g_slice_new (Array);
957   array->ast.class = &array_class;
958   array->children = NULL;
959   array->n_children = 0;
960
961   token_stream_assert (stream, "[");
962   while (!token_stream_consume (stream, "]"))
963     {
964       AST *child;
965
966       if (need_comma &&
967           !token_stream_require (stream, ",",
968                                  " or ']' to follow array element",
969                                  error))
970         goto error;
971
972       child = parse (stream, app, error);
973
974       if (!child)
975         goto error;
976
977       ast_array_append (&array->children, &array->n_children, child);
978       need_comma = TRUE;
979     }
980
981   return (AST *) array;
982
983  error:
984   ast_array_free (array->children, array->n_children);
985   g_slice_free (Array, array);
986
987   return NULL;
988 }
989
990 typedef struct
991 {
992   AST ast;
993
994   AST **children;
995   gint n_children;
996 } Tuple;
997
998 static gchar *
999 tuple_get_pattern (AST     *ast,
1000                    GError **error)
1001 {
1002   Tuple *tuple = (Tuple *) ast;
1003   gchar *result = NULL;
1004   gchar **parts;
1005   gint i;
1006
1007   parts = g_new (gchar *, tuple->n_children + 4);
1008   parts[tuple->n_children + 1] = (gchar *) ")";
1009   parts[tuple->n_children + 2] = NULL;
1010   parts[0] = (gchar *) "M(";
1011
1012   for (i = 0; i < tuple->n_children; i++)
1013     if (!(parts[i + 1] = ast_get_pattern (tuple->children[i], error)))
1014       break;
1015
1016   if (i == tuple->n_children)
1017     result = g_strjoinv ("", parts);
1018
1019   /* parts[0] should not be freed */
1020   while (i)
1021     g_free (parts[i--]);
1022   g_free (parts);
1023
1024   return result;
1025 }
1026
1027 static GVariant *
1028 tuple_get_value (AST                 *ast,
1029                  const GVariantType  *type,
1030                  GError             **error)
1031 {
1032   Tuple *tuple = (Tuple *) ast;
1033   const GVariantType *childtype;
1034   GVariantBuilder builder;
1035   gint i;
1036
1037   if (!g_variant_type_is_tuple (type))
1038     return ast_type_error (ast, type, error);
1039
1040   g_variant_builder_init (&builder, type);
1041   childtype = g_variant_type_first (type);
1042
1043   for (i = 0; i < tuple->n_children; i++)
1044     {
1045       GVariant *child;
1046
1047       if (childtype == NULL)
1048         {
1049           g_variant_builder_clear (&builder);
1050           return ast_type_error (ast, type, error);
1051         }
1052
1053       if (!(child = ast_get_value (tuple->children[i], childtype, error)))
1054         {
1055           g_variant_builder_clear (&builder);
1056           return FALSE;
1057         }
1058
1059       g_variant_builder_add_value (&builder, child);
1060       childtype = g_variant_type_next (childtype);
1061     }
1062
1063   if (childtype != NULL)
1064     {
1065       g_variant_builder_clear (&builder);
1066       return ast_type_error (ast, type, error);
1067     }
1068
1069   return g_variant_builder_end (&builder);
1070 }
1071
1072 static void
1073 tuple_free (AST *ast)
1074 {
1075   Tuple *tuple = (Tuple *) ast;
1076
1077   ast_array_free (tuple->children, tuple->n_children);
1078   g_slice_free (Tuple, tuple);
1079 }
1080
1081 static AST *
1082 tuple_parse (TokenStream  *stream,
1083              va_list      *app,
1084              GError      **error)
1085 {
1086   static const ASTClass tuple_class = {
1087     tuple_get_pattern,
1088     maybe_wrapper, tuple_get_value,
1089     tuple_free
1090   };
1091   gboolean need_comma = FALSE;
1092   gboolean first = TRUE;
1093   Tuple *tuple;
1094
1095   tuple = g_slice_new (Tuple);
1096   tuple->ast.class = &tuple_class;
1097   tuple->children = NULL;
1098   tuple->n_children = 0;
1099
1100   token_stream_assert (stream, "(");
1101   while (!token_stream_consume (stream, ")"))
1102     {
1103       AST *child;
1104
1105       if (need_comma &&
1106           !token_stream_require (stream, ",",
1107                                  " or ')' to follow tuple element",
1108                                  error))
1109         goto error;
1110
1111       child = parse (stream, app, error);
1112
1113       if (!child)
1114         goto error;
1115
1116       ast_array_append (&tuple->children, &tuple->n_children, child);
1117
1118       /* the first time, we absolutely require a comma, so grab it here
1119        * and leave need_comma = FALSE so that the code above doesn't
1120        * require a second comma.
1121        *
1122        * the second and remaining times, we set need_comma = TRUE.
1123        */
1124       if (first)
1125         {
1126           if (!token_stream_require (stream, ",",
1127                                      " after first tuple element", error))
1128             goto error;
1129
1130           first = FALSE;
1131         }
1132       else
1133         need_comma = TRUE;
1134     }
1135
1136   return (AST *) tuple;
1137
1138  error:
1139   ast_array_free (tuple->children, tuple->n_children);
1140   g_slice_free (Tuple, tuple);
1141
1142   return NULL;
1143 }
1144
1145 typedef struct
1146 {
1147   AST ast;
1148
1149   AST *value;
1150 } Variant;
1151
1152 static gchar *
1153 variant_get_pattern (AST     *ast,
1154                      GError **error)
1155 {
1156   return g_strdup ("Mv");
1157 }
1158
1159 static GVariant *
1160 variant_get_value (AST                 *ast,
1161                    const GVariantType  *type,
1162                    GError             **error)
1163 {
1164   Variant *variant = (Variant *) ast;
1165   GVariant *child;
1166
1167   if (!g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
1168     return ast_type_error (ast, type, error);
1169
1170   child = ast_resolve (variant->value, error);
1171
1172   if (child == NULL)
1173     return NULL;
1174
1175   return g_variant_new_variant (child);
1176 }
1177
1178 static void
1179 variant_free (AST *ast)
1180 {
1181   Variant *variant = (Variant *) ast;
1182
1183   ast_free (variant->value);
1184   g_slice_free (Variant, variant);
1185 }
1186
1187 static AST *
1188 variant_parse (TokenStream  *stream,
1189                va_list      *app,
1190                GError      **error)
1191 {
1192   static const ASTClass variant_class = {
1193     variant_get_pattern,
1194     maybe_wrapper, variant_get_value,
1195     variant_free
1196   };
1197   Variant *variant;
1198   AST *value;
1199
1200   token_stream_assert (stream, "<");
1201   value = parse (stream, app, error);
1202
1203   if (!value)
1204     return NULL;
1205
1206   if (!token_stream_require (stream, ">", " to follow variant value", error))
1207     {
1208       ast_free (value);
1209       return NULL;
1210     }
1211
1212   variant = g_slice_new (Variant);
1213   variant->ast.class = &variant_class;
1214   variant->value = value;
1215
1216   return (AST *) variant;
1217 }
1218
1219 typedef struct
1220 {
1221   AST ast;
1222
1223   AST **keys;
1224   AST **values;
1225   gint n_children;
1226 } Dictionary;
1227
1228 static gchar *
1229 dictionary_get_pattern (AST     *ast,
1230                         GError **error)
1231 {
1232   Dictionary *dict = (Dictionary *) ast;
1233   gchar *value_pattern;
1234   gchar *key_pattern;
1235   gchar key_char;
1236   gchar *result;
1237
1238   if (dict->n_children == 0)
1239     return g_strdup ("Ma{**}");
1240
1241   key_pattern = ast_array_get_pattern (dict->keys,
1242                                        abs (dict->n_children),
1243                                        error);
1244
1245   if (key_pattern == NULL)
1246     return NULL;
1247
1248   /* we can not have maybe keys */
1249   if (key_pattern[0] == 'M')
1250     key_char = key_pattern[1];
1251   else
1252     key_char = key_pattern[0];
1253
1254   g_free (key_pattern);
1255
1256   /* the basic types,
1257    * plus undetermined number type and undetermined string type.
1258    */
1259   if (!strchr ("bynqiuxthfdsogNDS", key_char))
1260     {
1261       ast_set_error (ast, error, NULL,
1262                      G_VARIANT_PARSE_ERROR_BASIC_TYPE_EXPECTED,
1263                      "dictionary keys must have basic types");
1264       return NULL;
1265     }
1266
1267   value_pattern = ast_get_pattern (dict->values[0], error);
1268
1269   if (value_pattern == NULL)
1270     return NULL;
1271
1272   result = g_strdup_printf ("M%s{%c%s}",
1273                             dict->n_children > 0 ? "a" : "",
1274                             key_char, value_pattern);
1275   g_free (value_pattern);
1276
1277   return result;
1278 }
1279
1280 static GVariant *
1281 dictionary_get_value (AST                 *ast,
1282                       const GVariantType  *type,
1283                       GError             **error)
1284 {
1285   Dictionary *dict = (Dictionary *) ast;
1286
1287   if (dict->n_children == -1)
1288     {
1289       const GVariantType *subtype;
1290       GVariantBuilder builder;
1291       GVariant *subvalue;
1292
1293       if (!g_variant_type_is_dict_entry (type))
1294         return ast_type_error (ast, type, error);
1295
1296       g_variant_builder_init (&builder, type);
1297
1298       subtype = g_variant_type_key (type);
1299       if (!(subvalue = ast_get_value (dict->keys[0], subtype, error)))
1300         {
1301           g_variant_builder_clear (&builder);
1302           return NULL;
1303         }
1304       g_variant_builder_add_value (&builder, subvalue);
1305
1306       subtype = g_variant_type_value (type);
1307       if (!(subvalue = ast_get_value (dict->values[0], subtype, error)))
1308         {
1309           g_variant_builder_clear (&builder);
1310           return NULL;
1311         }
1312       g_variant_builder_add_value (&builder, subvalue);
1313
1314       return g_variant_builder_end (&builder);
1315     }
1316   else
1317     {
1318       const GVariantType *entry, *key, *val;
1319       GVariantBuilder builder;
1320       gint i;
1321
1322       if (!g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_DICTIONARY))
1323         return ast_type_error (ast, type, error);
1324
1325       entry = g_variant_type_element (type);
1326       key = g_variant_type_key (entry);
1327       val = g_variant_type_value (entry);
1328
1329       g_variant_builder_init (&builder, type);
1330
1331       for (i = 0; i < dict->n_children; i++)
1332         {
1333           GVariant *subvalue;
1334
1335           g_variant_builder_open (&builder, entry);
1336
1337           if (!(subvalue = ast_get_value (dict->keys[i], key, error)))
1338             {
1339               g_variant_builder_clear (&builder);
1340               return NULL;
1341             }
1342           g_variant_builder_add_value (&builder, subvalue);
1343
1344           if (!(subvalue = ast_get_value (dict->values[i], val, error)))
1345             {
1346               g_variant_builder_clear (&builder);
1347               return NULL;
1348             }
1349           g_variant_builder_add_value (&builder, subvalue);
1350           g_variant_builder_close (&builder);
1351         }
1352
1353       return g_variant_builder_end (&builder);
1354     }
1355 }
1356
1357 static void
1358 dictionary_free (AST *ast)
1359 {
1360   Dictionary *dict = (Dictionary *) ast;
1361   gint n_children;
1362
1363   if (dict->n_children > -1)
1364     n_children = dict->n_children;
1365   else
1366     n_children = 1;
1367
1368   ast_array_free (dict->keys, n_children);
1369   ast_array_free (dict->values, n_children);
1370   g_slice_free (Dictionary, dict);
1371 }
1372
1373 static AST *
1374 dictionary_parse (TokenStream  *stream,
1375                   va_list      *app,
1376                   GError      **error)
1377 {
1378   static const ASTClass dictionary_class = {
1379     dictionary_get_pattern,
1380     maybe_wrapper, dictionary_get_value,
1381     dictionary_free
1382   };
1383   gint n_keys, n_values;
1384   gboolean only_one;
1385   Dictionary *dict;
1386   AST *first;
1387
1388   dict = g_slice_new (Dictionary);
1389   dict->ast.class = &dictionary_class;
1390   dict->keys = NULL;
1391   dict->values = NULL;
1392   n_keys = n_values = 0;
1393
1394   token_stream_assert (stream, "{");
1395
1396   if (token_stream_consume (stream, "}"))
1397     {
1398       dict->n_children = 0;
1399       return (AST *) dict;
1400     }
1401
1402   if ((first = parse (stream, app, error)) == NULL)
1403     goto error;
1404
1405   ast_array_append (&dict->keys, &n_keys, first);
1406
1407   only_one = token_stream_consume (stream, ",");
1408   if (!only_one &&
1409       !token_stream_require (stream, ":",
1410                              " or ',' to follow dictionary entry key",
1411                              error))
1412     goto error;
1413
1414   if ((first = parse (stream, app, error)) == NULL)
1415     goto error;
1416
1417   ast_array_append (&dict->values, &n_values, first);
1418
1419   if (only_one)
1420     {
1421       if (!token_stream_require (stream, "}", " at end of dictionary entry",
1422                                  error))
1423         goto error;
1424
1425       g_assert (n_keys == 1 && n_values == 1);
1426       dict->n_children = -1;
1427
1428       return (AST *) dict;
1429     }
1430
1431   while (!token_stream_consume (stream, "}"))
1432     {
1433       AST *child;
1434
1435       if (!token_stream_require (stream, ",",
1436                                  " or '}' to follow dictionary entry", error))
1437         goto error;
1438
1439       child = parse (stream, app, error);
1440
1441       if (!child)
1442         goto error;
1443
1444       ast_array_append (&dict->keys, &n_keys, child);
1445
1446       if (!token_stream_require (stream, ":",
1447                                  " to follow dictionary entry key", error))
1448         goto error;
1449
1450       child = parse (stream, app, error);
1451
1452       if (!child)
1453         goto error;
1454
1455       ast_array_append (&dict->values, &n_values, child);
1456     }
1457
1458   g_assert (n_keys == n_values);
1459   dict->n_children = n_keys;
1460
1461   return (AST *) dict;
1462
1463  error:
1464   ast_array_free (dict->keys, n_keys);
1465   ast_array_free (dict->values, n_values);
1466   g_slice_free (Dictionary, dict);
1467
1468   return NULL;
1469 }
1470
1471 typedef struct
1472 {
1473   AST ast;
1474   gchar *string;
1475 } String;
1476
1477 static gchar *
1478 string_get_pattern (AST     *ast,
1479                     GError **error)
1480 {
1481   return g_strdup ("MS");
1482 }
1483
1484 static GVariant *
1485 string_get_value (AST                 *ast,
1486                   const GVariantType  *type,
1487                   GError             **error)
1488 {
1489   String *string = (String *) ast;
1490
1491   if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
1492     return g_variant_new_string (string->string);
1493
1494   else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
1495     {
1496       if (!g_variant_is_object_path (string->string))
1497         {
1498           ast_set_error (ast, error, NULL,
1499                          G_VARIANT_PARSE_ERROR_INVALID_OBJECT_PATH,
1500                          "not a valid object path");
1501           return NULL;
1502         }
1503
1504       return g_variant_new_object_path (string->string);
1505     }
1506
1507   else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
1508     {
1509       if (!g_variant_is_signature (string->string))
1510         {
1511           ast_set_error (ast, error, NULL,
1512                          G_VARIANT_PARSE_ERROR_INVALID_SIGNATURE,
1513                          "not a valid signature");
1514           return NULL;
1515         }
1516
1517       return g_variant_new_signature (string->string);
1518     }
1519
1520   else
1521     return ast_type_error (ast, type, error);
1522 }
1523
1524 static void
1525 string_free (AST *ast)
1526 {
1527   String *string = (String *) ast;
1528
1529   g_free (string->string);
1530   g_slice_free (String, string);
1531 }
1532
1533 static gboolean
1534 unicode_unescape (const gchar  *src,
1535                   gint         *src_ofs,
1536                   gchar        *dest,
1537                   gint         *dest_ofs,
1538                   gint          length,
1539                   SourceRef    *ref,
1540                   GError      **error)
1541 {
1542   gchar buffer[9];
1543   guint64 value;
1544   gchar *end;
1545
1546   (*src_ofs)++;
1547
1548   g_assert (length < sizeof (buffer));
1549   strncpy (buffer, src + *src_ofs, length);
1550   buffer[length] = '\0';
1551
1552   value = g_ascii_strtoull (buffer, &end, 0x10);
1553
1554   if (value == 0 || end != buffer + length)
1555     {
1556       parser_set_error (error, ref, NULL,
1557                         G_VARIANT_PARSE_ERROR_INVALID_CHARACTER,
1558                         "invalid %d-character unicode escape", length);
1559       return FALSE;
1560     }
1561
1562   g_assert (value <= G_MAXUINT32);
1563
1564   *dest_ofs += g_unichar_to_utf8 (value, dest + *dest_ofs);
1565   *src_ofs += length;
1566
1567   return TRUE;
1568 }
1569
1570 static AST *
1571 string_parse (TokenStream  *stream,
1572               va_list      *app,
1573               GError      **error)
1574 {
1575   static const ASTClass string_class = {
1576     string_get_pattern,
1577     maybe_wrapper, string_get_value,
1578     string_free
1579   };
1580   String *string;
1581   SourceRef ref;
1582   gchar *token;
1583   gsize length;
1584   gchar quote;
1585   gchar *str;
1586   gint i, j;
1587
1588   token_stream_start_ref (stream, &ref);
1589   token = token_stream_get (stream);
1590   token_stream_end_ref (stream, &ref);
1591   length = strlen (token);
1592   quote = token[0];
1593
1594   str = g_malloc (length);
1595   g_assert (quote == '"' || quote == '\'');
1596   j = 0;
1597   i = 1;
1598   while (token[i] != quote)
1599     switch (token[i])
1600       {
1601       case '\0':
1602         parser_set_error (error, &ref, NULL,
1603                           G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1604                           "unterminated string constant");
1605         g_free (token);
1606         g_free (str);
1607         return NULL;
1608
1609       case '\\':
1610         switch (token[++i])
1611           {
1612           case '\0':
1613             parser_set_error (error, &ref, NULL,
1614                               G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1615                               "unterminated string constant");
1616             g_free (token);
1617             g_free (str);
1618             return NULL;
1619
1620           case 'u':
1621             if (!unicode_unescape (token, &i, str, &j, 4, &ref, error))
1622               {
1623                 g_free (token);
1624                 g_free (str);
1625                 return NULL;
1626               }
1627             continue;
1628
1629           case 'U':
1630             if (!unicode_unescape (token, &i, str, &j, 8, &ref, error))
1631               {
1632                 g_free (token);
1633                 g_free (str);
1634                 return NULL;
1635               }
1636             continue;
1637
1638           case 'a': str[j++] = '\a'; i++; continue;
1639           case 'b': str[j++] = '\b'; i++; continue;
1640           case 'f': str[j++] = '\f'; i++; continue;
1641           case 'n': str[j++] = '\n'; i++; continue;
1642           case 'r': str[j++] = '\r'; i++; continue;
1643           case 't': str[j++] = '\t'; i++; continue;
1644           case 'v': str[j++] = '\v'; i++; continue;
1645           case '\n': i++; continue;
1646           }
1647
1648       default:
1649         str[j++] = token[i++];
1650       }
1651   str[j++] = '\0';
1652   g_free (token);
1653
1654   string = g_slice_new (String);
1655   string->ast.class = &string_class;
1656   string->string = str;
1657
1658   token_stream_next (stream);
1659
1660   return (AST *) string;
1661 }
1662
1663 typedef struct
1664 {
1665   AST ast;
1666   gchar *string;
1667 } ByteString;
1668
1669 static gchar *
1670 bytestring_get_pattern (AST     *ast,
1671                         GError **error)
1672 {
1673   return g_strdup ("May");
1674 }
1675
1676 static GVariant *
1677 bytestring_get_value (AST                 *ast,
1678                       const GVariantType  *type,
1679                       GError             **error)
1680 {
1681   ByteString *string = (ByteString *) ast;
1682
1683   if (!g_variant_type_equal (type, G_VARIANT_TYPE_BYTESTRING))
1684     return ast_type_error (ast, type, error);
1685
1686   return g_variant_new_bytestring (string->string);
1687 }
1688
1689 static void
1690 bytestring_free (AST *ast)
1691 {
1692   ByteString *string = (ByteString *) ast;
1693
1694   g_free (string->string);
1695   g_slice_free (ByteString, string);
1696 }
1697
1698 static AST *
1699 bytestring_parse (TokenStream  *stream,
1700                   va_list      *app,
1701                   GError      **error)
1702 {
1703   static const ASTClass bytestring_class = {
1704     bytestring_get_pattern,
1705     maybe_wrapper, bytestring_get_value,
1706     bytestring_free
1707   };
1708   ByteString *string;
1709   SourceRef ref;
1710   gchar *token;
1711   gsize length;
1712   gchar quote;
1713   gchar *str;
1714   gint i, j;
1715
1716   token_stream_start_ref (stream, &ref);
1717   token = token_stream_get (stream);
1718   token_stream_end_ref (stream, &ref);
1719   g_assert (token[0] == 'b');
1720   length = strlen (token);
1721   quote = token[1];
1722
1723   str = g_malloc (length);
1724   g_assert (quote == '"' || quote == '\'');
1725   j = 0;
1726   i = 2;
1727   while (token[i] != quote)
1728     switch (token[i])
1729       {
1730       case '\0':
1731         parser_set_error (error, &ref, NULL,
1732                           G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1733                           "unterminated string constant");
1734         g_free (token);
1735         return NULL;
1736
1737       case '\\':
1738         switch (token[++i])
1739           {
1740           case '\0':
1741             parser_set_error (error, &ref, NULL,
1742                               G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1743                               "unterminated string constant");
1744             g_free (token);
1745             return NULL;
1746
1747           case '0': case '1': case '2': case '3':
1748           case '4': case '5': case '6': case '7':
1749             {
1750               /* up to 3 characters */
1751               guchar val = token[i++] - '0';
1752
1753               if ('0' <= token[i] && token[i] < '8')
1754                 val = (val << 3) | (token[i++] - '0');
1755
1756               if ('0' <= token[i] && token[i] < '8')
1757                 val = (val << 3) | (token[i++] - '0');
1758
1759               str[j++] = val;
1760             }
1761             continue;
1762
1763           case 'a': str[j++] = '\a'; i++; continue;
1764           case 'b': str[j++] = '\b'; i++; continue;
1765           case 'f': str[j++] = '\f'; i++; continue;
1766           case 'n': str[j++] = '\n'; i++; continue;
1767           case 'r': str[j++] = '\r'; i++; continue;
1768           case 't': str[j++] = '\t'; i++; continue;
1769           case 'v': str[j++] = '\v'; i++; continue;
1770           case '\n': i++; continue;
1771           }
1772
1773       default:
1774         str[j++] = token[i++];
1775       }
1776   str[j++] = '\0';
1777   g_free (token);
1778
1779   string = g_slice_new (ByteString);
1780   string->ast.class = &bytestring_class;
1781   string->string = str;
1782
1783   token_stream_next (stream);
1784
1785   return (AST *) string;
1786 }
1787
1788 typedef struct
1789 {
1790   AST ast;
1791
1792   gchar *token;
1793 } Number;
1794
1795 static gchar *
1796 number_get_pattern (AST     *ast,
1797                     GError **error)
1798 {
1799   Number *number = (Number *) ast;
1800
1801   if (strchr (number->token, '.') ||
1802       (!g_str_has_prefix (number->token, "0x") && strchr (number->token, 'e')) ||
1803       strstr (number->token, "inf") ||
1804       strstr (number->token, "nan"))
1805     return g_strdup ("MD");
1806
1807   return g_strdup ("MN");
1808 }
1809
1810 static GVariant *
1811 number_overflow (AST                 *ast,
1812                  const GVariantType  *type,
1813                  GError             **error)
1814 {
1815   ast_set_error (ast, error, NULL,
1816                  G_VARIANT_PARSE_ERROR_NUMBER_OUT_OF_RANGE,
1817                  "number out of range for type '%c'",
1818                  g_variant_type_peek_string (type)[0]);
1819   return NULL;
1820 }
1821
1822 static GVariant *
1823 number_get_value (AST                 *ast,
1824                   const GVariantType  *type,
1825                   GError             **error)
1826 {
1827   Number *number = (Number *) ast;
1828   const gchar *token;
1829   gboolean negative;
1830   guint64 abs_val;
1831   gdouble dbl_val;
1832   gchar typechar;
1833   gchar *end;
1834
1835   typechar = *g_variant_type_peek_string (type);
1836   token = number->token;
1837
1838   if (typechar == 'f' || typechar == 'd')
1839     {
1840       errno = 0;
1841       dbl_val = g_ascii_strtod (token, &end);
1842       if (dbl_val != 0.0 && errno == ERANGE)
1843         {
1844           ast_set_error (ast, error, NULL,
1845                          G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG,
1846                          "number too big for any type");
1847           return NULL;
1848         }
1849
1850       /* silence uninitialised warnings... */
1851       negative = FALSE;
1852       abs_val = 0;
1853     }
1854   else
1855     {
1856       negative = token[0] == '-';
1857       if (token[0] == '-')
1858         token++;
1859
1860       errno = 0;
1861       abs_val = g_ascii_strtoull (token, &end, 0);
1862       if (abs_val == G_MAXUINT64 && errno == ERANGE)
1863         {
1864           ast_set_error (ast, error, NULL,
1865                          G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG,
1866                          "integer too big for any type");
1867           return NULL;
1868         }
1869
1870       if (abs_val == 0)
1871         negative = FALSE;
1872
1873       /* silence uninitialised warning... */
1874       dbl_val = 0.0;
1875     }
1876
1877   if (*end != '\0')
1878     {
1879       SourceRef ref;
1880
1881       ref = ast->source_ref;
1882       ref.start += end - number->token;
1883       ref.end = ref.start + 1;
1884
1885       parser_set_error (error, &ref, NULL,
1886                         G_VARIANT_PARSE_ERROR_INVALID_CHARACTER,
1887                         "invalid character in number");
1888       return NULL;
1889      }
1890
1891   switch (typechar)
1892     {
1893     case 'y':
1894       if (negative || abs_val > G_MAXUINT8)
1895         return number_overflow (ast, type, error);
1896       return g_variant_new_byte (abs_val);
1897
1898     case 'n':
1899       if (abs_val - negative > G_MAXINT16)
1900         return number_overflow (ast, type, error);
1901       return g_variant_new_int16 (negative ? -abs_val : abs_val);
1902
1903     case 'q':
1904       if (negative || abs_val > G_MAXUINT16)
1905         return number_overflow (ast, type, error);
1906       return g_variant_new_uint16 (abs_val);
1907
1908     case 'i':
1909       if (abs_val - negative > G_MAXINT32)
1910         return number_overflow (ast, type, error);
1911       return g_variant_new_int32 (negative ? -abs_val : abs_val);
1912
1913     case 'u':
1914       if (negative || abs_val > G_MAXUINT32)
1915         return number_overflow (ast, type, error);
1916       return g_variant_new_uint32 (abs_val);
1917
1918     case 'x':
1919       if (abs_val - negative > G_MAXINT64)
1920         return number_overflow (ast, type, error);
1921       return g_variant_new_int64 (negative ? -abs_val : abs_val);
1922
1923     case 't':
1924       if (negative)
1925         return number_overflow (ast, type, error);
1926       return g_variant_new_uint64 (abs_val);
1927
1928     case 'h':
1929       if (abs_val - negative > G_MAXINT32)
1930         return number_overflow (ast, type, error);
1931       return g_variant_new_handle (negative ? -abs_val : abs_val);
1932
1933     case 'f':
1934       return g_variant_new_float (dbl_val);
1935
1936     case 'd':
1937       return g_variant_new_double (dbl_val);
1938
1939     default:
1940       return ast_type_error (ast, type, error);
1941     }
1942 }
1943
1944 static void
1945 number_free (AST *ast)
1946 {
1947   Number *number = (Number *) ast;
1948
1949   g_free (number->token);
1950   g_slice_free (Number, number);
1951 }
1952
1953 static AST *
1954 number_parse (TokenStream  *stream,
1955               va_list      *app,
1956               GError      **error)
1957 {
1958   static const ASTClass number_class = {
1959     number_get_pattern,
1960     maybe_wrapper, number_get_value,
1961     number_free
1962   };
1963   Number *number;
1964
1965   number = g_slice_new (Number);
1966   number->ast.class = &number_class;
1967   number->token = token_stream_get (stream);
1968   token_stream_next (stream);
1969
1970   return (AST *) number;
1971 }
1972
1973 typedef struct
1974 {
1975   AST ast;
1976   gboolean value;
1977 } Boolean;
1978
1979 static gchar *
1980 boolean_get_pattern (AST     *ast,
1981                      GError **error)
1982 {
1983   return g_strdup ("Mb");
1984 }
1985
1986 static GVariant *
1987 boolean_get_value (AST                 *ast,
1988                    const GVariantType  *type,
1989                    GError             **error)
1990 {
1991   Boolean *boolean = (Boolean *) ast;
1992
1993   if (!g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
1994     return ast_type_error (ast, type, error);
1995
1996   return g_variant_new_boolean (boolean->value);
1997 }
1998
1999 static void
2000 boolean_free (AST *ast)
2001 {
2002   Boolean *boolean = (Boolean *) ast;
2003
2004   g_slice_free (Boolean, boolean);
2005 }
2006
2007 static AST *
2008 boolean_new (gboolean value)
2009 {
2010   static const ASTClass boolean_class = {
2011     boolean_get_pattern,
2012     maybe_wrapper, boolean_get_value,
2013     boolean_free
2014   };
2015   Boolean *boolean;
2016
2017   boolean = g_slice_new (Boolean);
2018   boolean->ast.class = &boolean_class;
2019   boolean->value = value;
2020
2021   return (AST *) boolean;
2022 }
2023
2024 typedef struct
2025 {
2026   AST ast;
2027
2028   GVariant *value;
2029 } Positional;
2030
2031 static gchar *
2032 positional_get_pattern (AST     *ast,
2033                         GError **error)
2034 {
2035   Positional *positional = (Positional *) ast;
2036
2037   return g_strdup (g_variant_get_type_string (positional->value));
2038 }
2039
2040 static GVariant *
2041 positional_get_value (AST                 *ast,
2042                       const GVariantType  *type,
2043                       GError             **error)
2044 {
2045   Positional *positional = (Positional *) ast;
2046   GVariant *value;
2047
2048   g_assert (positional->value != NULL);
2049
2050   if G_UNLIKELY (!g_variant_is_of_type (positional->value, type))
2051     return ast_type_error (ast, type, error);
2052
2053   /* NOTE: if _get is called more than once then
2054    * things get messed up with respect to floating refs.
2055    *
2056    * fortunately, this function should only ever get called once.
2057    */
2058   g_assert (positional->value != NULL);
2059   value = positional->value;
2060   positional->value = NULL;
2061
2062   return value;
2063 }
2064
2065 static void
2066 positional_free (AST *ast)
2067 {
2068   Positional *positional = (Positional *) ast;
2069
2070   /* if positional->value is set, just leave it.
2071    * memory management doesn't matter in case of programmer error.
2072    */
2073   g_slice_free (Positional, positional);
2074 }
2075
2076 static AST *
2077 positional_parse (TokenStream  *stream,
2078                   va_list      *app,
2079                   GError      **error)
2080 {
2081   static const ASTClass positional_class = {
2082     positional_get_pattern,
2083     positional_get_value, NULL,
2084     positional_free
2085   };
2086   Positional *positional;
2087   const gchar *endptr;
2088   gchar *token;
2089
2090   token = token_stream_get (stream);
2091   g_assert (token[0] == '%');
2092
2093   positional = g_slice_new (Positional);
2094   positional->ast.class = &positional_class;
2095   positional->value = g_variant_new_va (token + 1, &endptr, app);
2096
2097   if (*endptr || positional->value == NULL)
2098     {
2099       token_stream_set_error (stream, error, TRUE,
2100                               G_VARIANT_PARSE_ERROR_INVALID_FORMAT_STRING,
2101                               "invalid GVariant format string");
2102       /* memory management doesn't matter in case of programmer error. */
2103       return NULL;
2104     }
2105
2106   token_stream_next (stream);
2107   g_free (token);
2108
2109   return (AST *) positional;
2110 }
2111
2112 typedef struct
2113 {
2114   AST ast;
2115
2116   GVariantType *type;
2117   AST *child;
2118 } TypeDecl;
2119
2120 static gchar *
2121 typedecl_get_pattern (AST     *ast,
2122                       GError **error)
2123 {
2124   TypeDecl *decl = (TypeDecl *) ast;
2125
2126   return g_variant_type_dup_string (decl->type);
2127 }
2128
2129 static GVariant *
2130 typedecl_get_value (AST                 *ast,
2131                     const GVariantType  *type,
2132                     GError             **error)
2133 {
2134   TypeDecl *decl = (TypeDecl *) ast;
2135
2136   return ast_get_value (decl->child, type, error);
2137 }
2138
2139 static void
2140 typedecl_free (AST *ast)
2141 {
2142   TypeDecl *decl = (TypeDecl *) ast;
2143
2144   ast_free (decl->child);
2145   g_variant_type_free (decl->type);
2146   g_slice_free (TypeDecl, decl);
2147 }
2148
2149 static AST *
2150 typedecl_parse (TokenStream  *stream,
2151                 va_list      *app,
2152                 GError      **error)
2153 {
2154   static const ASTClass typedecl_class = {
2155     typedecl_get_pattern,
2156     typedecl_get_value, NULL,
2157     typedecl_free
2158   };
2159   GVariantType *type;
2160   TypeDecl *decl;
2161   AST *child;
2162
2163   if (token_stream_peek (stream, '@'))
2164     {
2165       gchar *token;
2166
2167       token = token_stream_get (stream);
2168
2169       if (!g_variant_type_string_is_valid (token + 1))
2170         {
2171           token_stream_set_error (stream, error, TRUE,
2172                                   G_VARIANT_PARSE_ERROR_INVALID_TYPE_STRING,
2173                                   "invalid type declaration");
2174           g_free (token);
2175
2176           return NULL;
2177         }
2178
2179       type = g_variant_type_new (token + 1);
2180
2181       if (!g_variant_type_is_definite (type))
2182         {
2183           token_stream_set_error (stream, error, TRUE,
2184                                   G_VARIANT_PARSE_ERROR_DEFINITE_TYPE_EXPECTED,
2185                                   "type declarations must be definite");
2186           g_variant_type_free (type);
2187           g_free (token);
2188
2189           return NULL;
2190         }
2191
2192       token_stream_next (stream);
2193       g_free (token);
2194     }
2195   else
2196     {
2197       if (token_stream_consume (stream, "boolean"))
2198         type = g_variant_type_copy (G_VARIANT_TYPE_BOOLEAN);
2199
2200       else if (token_stream_consume (stream, "byte"))
2201         type = g_variant_type_copy (G_VARIANT_TYPE_BYTE);
2202
2203       else if (token_stream_consume (stream, "int16"))
2204         type = g_variant_type_copy (G_VARIANT_TYPE_INT16);
2205
2206       else if (token_stream_consume (stream, "uint16"))
2207         type = g_variant_type_copy (G_VARIANT_TYPE_UINT16);
2208
2209       else if (token_stream_consume (stream, "int32"))
2210         type = g_variant_type_copy (G_VARIANT_TYPE_INT32);
2211
2212       else if (token_stream_consume (stream, "handle"))
2213         type = g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
2214
2215       else if (token_stream_consume (stream, "uint32"))
2216         type = g_variant_type_copy (G_VARIANT_TYPE_UINT32);
2217
2218       else if (token_stream_consume (stream, "int64"))
2219         type = g_variant_type_copy (G_VARIANT_TYPE_INT64);
2220
2221       else if (token_stream_consume (stream, "uint64"))
2222         type = g_variant_type_copy (G_VARIANT_TYPE_UINT64);
2223
2224       else if (token_stream_consume (stream, "float"))
2225         type = g_variant_type_copy (G_VARIANT_TYPE_FLOAT);
2226
2227       else if (token_stream_consume (stream, "double"))
2228         type = g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
2229
2230       else if (token_stream_consume (stream, "string"))
2231         type = g_variant_type_copy (G_VARIANT_TYPE_STRING);
2232
2233       else if (token_stream_consume (stream, "objectpath"))
2234         type = g_variant_type_copy (G_VARIANT_TYPE_OBJECT_PATH);
2235
2236       else if (token_stream_consume (stream, "signature"))
2237         type = g_variant_type_copy (G_VARIANT_TYPE_SIGNATURE);
2238
2239       else
2240         {
2241           token_stream_set_error (stream, error, TRUE,
2242                                   G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD,
2243                                   "unknown keyword");
2244           return NULL;
2245         }
2246     }
2247
2248   if ((child = parse (stream, app, error)) == NULL)
2249     {
2250       g_variant_type_free (type);
2251       return NULL;
2252     }
2253
2254   decl = g_slice_new (TypeDecl);
2255   decl->ast.class = &typedecl_class;
2256   decl->type = type;
2257   decl->child = child;
2258
2259   return (AST *) decl;
2260 }
2261
2262 static AST *
2263 parse (TokenStream  *stream,
2264        va_list      *app,
2265        GError      **error)
2266 {
2267   SourceRef source_ref;
2268   AST *result;
2269
2270   token_stream_prepare (stream);
2271   token_stream_start_ref (stream, &source_ref);
2272
2273   if (token_stream_peek (stream, '['))
2274     result = array_parse (stream, app, error);
2275
2276   else if (token_stream_peek (stream, '('))
2277     result = tuple_parse (stream, app, error);
2278
2279   else if (token_stream_peek (stream, '<'))
2280     result = variant_parse (stream, app, error);
2281
2282   else if (token_stream_peek (stream, '{'))
2283     result = dictionary_parse (stream, app, error);
2284
2285   else if (app && token_stream_peek (stream, '%'))
2286     result = positional_parse (stream, app, error);
2287
2288   else if (token_stream_consume (stream, "true"))
2289     result = boolean_new (TRUE);
2290
2291   else if (token_stream_consume (stream, "false"))
2292     result = boolean_new (FALSE);
2293
2294   else if (token_stream_is_numeric (stream) ||
2295            token_stream_peek_string (stream, "inf") ||
2296            token_stream_peek_string (stream, "nan"))
2297     result = number_parse (stream, app, error);
2298
2299   else if (token_stream_peek (stream, 'n') ||
2300            token_stream_peek (stream, 'j'))
2301     result = maybe_parse (stream, app, error);
2302
2303   else if (token_stream_peek (stream, '@') ||
2304            token_stream_is_keyword (stream))
2305     result = typedecl_parse (stream, app, error);
2306
2307   else if (token_stream_peek (stream, '\'') ||
2308            token_stream_peek (stream, '"'))
2309     result = string_parse (stream, app, error);
2310
2311   else if (token_stream_peek2 (stream, 'b', '\'') ||
2312            token_stream_peek2 (stream, 'b', '"'))
2313     result = bytestring_parse (stream, app, error);
2314
2315   else
2316     {
2317       token_stream_set_error (stream, error, FALSE,
2318                               G_VARIANT_PARSE_ERROR_VALUE_EXPECTED,
2319                               "expected value");
2320       return NULL;
2321     }
2322
2323   if (result != NULL)
2324     {
2325       token_stream_end_ref (stream, &source_ref);
2326       result->source_ref = source_ref;
2327     }
2328
2329   return result;
2330 }
2331
2332 /**
2333  * g_variant_parse:
2334  * @type: (allow-none): a #GVariantType, or %NULL
2335  * @text: a string containing a GVariant in text form
2336  * @limit: (allow-none): a pointer to the end of @text, or %NULL
2337  * @endptr: (allow-none): a location to store the end pointer, or %NULL
2338  * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
2339  *
2340  * Parses a #GVariant from a text representation.
2341  *
2342  * A single #GVariant is parsed from the content of @text.
2343  *
2344  * The format is described [here][gvariant-text].
2345  *
2346  * The memory at @limit will never be accessed and the parser behaves as
2347  * if the character at @limit is the nul terminator.  This has the
2348  * effect of bounding @text.
2349  *
2350  * If @endptr is non-%NULL then @text is permitted to contain data
2351  * following the value that this function parses and @endptr will be
2352  * updated to point to the first character past the end of the text
2353  * parsed by this function.  If @endptr is %NULL and there is extra data
2354  * then an error is returned.
2355  *
2356  * If @type is non-%NULL then the value will be parsed to have that
2357  * type.  This may result in additional parse errors (in the case that
2358  * the parsed value doesn't fit the type) but may also result in fewer
2359  * errors (in the case that the type would have been ambiguous, such as
2360  * with empty arrays).
2361  *
2362  * In the event that the parsing is successful, the resulting #GVariant
2363  * is returned.
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 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 }