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