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