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