1/*
2 * Copyright © 2021 Benjamin Otte
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authors: Benjamin Otte <otte@gnome.org>
18 */
19
20
21#include "config.h"
22
23#include "gtkjsonparserprivate.h"
24#include <stdlib.h>
25#include <errno.h>
26
27typedef struct _GtkJsonBlock GtkJsonBlock;
28
29typedef enum {
30 GTK_JSON_BLOCK_TOPLEVEL,
31 GTK_JSON_BLOCK_OBJECT,
32 GTK_JSON_BLOCK_ARRAY,
33} GtkJsonBlockType;
34
35struct _GtkJsonBlock
36{
37 GtkJsonBlockType type;
38 const guchar *value; /* start of current value to be consumed by external code */
39 const guchar *member_name; /* name of current value, only used for object types */
40 gsize index; /* index of the current element */
41};
42
43struct _GtkJsonParser
44{
45 GBytes *bytes;
46 const guchar *reader; /* current read head, pointing as far as we've read */
47 const guchar *start; /* pointer at start of data, after optional BOM */
48 const guchar *end; /* pointer after end of data we're reading */
49
50 GError *error; /* if an error has happened, it's stored here. Errors aren't recoverable. */
51 const guchar *error_start; /* start of error location */
52 const guchar *error_end; /* end of error location */
53
54 GtkJsonBlock *block; /* current block */
55 GtkJsonBlock *blocks; /* blocks array */
56 GtkJsonBlock *blocks_end; /* blocks array */
57 GtkJsonBlock blocks_preallocated[128]; /* preallocated */
58};
59
60typedef enum {
61 WHITESPACE = (1 << 4),
62 NEWLINE = (1 << 5),
63 STRING_ELEMENT = (1 << 6),
64 STRING_MARKER = (1 << 7),
65} JsonCharacterType;
66
67#define JSON_CHARACTER_NODE_MASK ((1 << 4) - 1)
68
69static const guchar json_character_table[256] = {
70 ['\t'] = WHITESPACE,
71 ['\r'] = WHITESPACE | NEWLINE,
72 ['\n'] = WHITESPACE | NEWLINE,
73 [' '] = WHITESPACE | STRING_ELEMENT,
74 ['!'] = STRING_ELEMENT,
75 ['"'] = GTK_JSON_STRING | STRING_MARKER,
76 ['#'] = STRING_ELEMENT,
77 ['$'] = STRING_ELEMENT,
78 ['%'] = STRING_ELEMENT,
79 ['&'] = STRING_ELEMENT,
80 ['\''] = STRING_ELEMENT,
81 ['('] = STRING_ELEMENT,
82 [')'] = STRING_ELEMENT,
83 ['*'] = STRING_ELEMENT,
84 ['+'] = STRING_ELEMENT,
85 [','] = STRING_ELEMENT,
86 ['-'] = GTK_JSON_NUMBER | STRING_ELEMENT,
87 ['.'] = STRING_ELEMENT,
88 ['/'] = STRING_ELEMENT,
89 ['0'] = GTK_JSON_NUMBER | STRING_ELEMENT,
90 ['1'] = GTK_JSON_NUMBER | STRING_ELEMENT,
91 ['2'] = GTK_JSON_NUMBER | STRING_ELEMENT,
92 ['3'] = GTK_JSON_NUMBER | STRING_ELEMENT,
93 ['4'] = GTK_JSON_NUMBER | STRING_ELEMENT,
94 ['5'] = GTK_JSON_NUMBER | STRING_ELEMENT,
95 ['6'] = GTK_JSON_NUMBER | STRING_ELEMENT,
96 ['7'] = GTK_JSON_NUMBER | STRING_ELEMENT,
97 ['8'] = GTK_JSON_NUMBER | STRING_ELEMENT,
98 ['9'] = GTK_JSON_NUMBER | STRING_ELEMENT,
99 [':'] = STRING_ELEMENT,
100 [';'] = STRING_ELEMENT,
101 ['<'] = STRING_ELEMENT,
102 ['='] = STRING_ELEMENT,
103 ['>'] = STRING_ELEMENT,
104 ['?'] = STRING_ELEMENT,
105 ['@'] = STRING_ELEMENT,
106 ['A'] = STRING_ELEMENT,
107 ['B'] = STRING_ELEMENT,
108 ['C'] = STRING_ELEMENT,
109 ['D'] = STRING_ELEMENT,
110 ['E'] = STRING_ELEMENT,
111 ['F'] = STRING_ELEMENT,
112 ['G'] = STRING_ELEMENT,
113 ['H'] = STRING_ELEMENT,
114 ['I'] = STRING_ELEMENT,
115 ['J'] = STRING_ELEMENT,
116 ['K'] = STRING_ELEMENT,
117 ['L'] = STRING_ELEMENT,
118 ['M'] = STRING_ELEMENT,
119 ['N'] = STRING_ELEMENT,
120 ['O'] = STRING_ELEMENT,
121 ['P'] = STRING_ELEMENT,
122 ['Q'] = STRING_ELEMENT,
123 ['R'] = STRING_ELEMENT,
124 ['S'] = STRING_ELEMENT,
125 ['T'] = STRING_ELEMENT,
126 ['U'] = STRING_ELEMENT,
127 ['V'] = STRING_ELEMENT,
128 ['W'] = STRING_ELEMENT,
129 ['X'] = STRING_ELEMENT,
130 ['Y'] = STRING_ELEMENT,
131 ['Z'] = STRING_ELEMENT,
132 ['['] = GTK_JSON_ARRAY | STRING_ELEMENT,
133 ['\\'] = STRING_MARKER,
134 [']'] = STRING_ELEMENT,
135 ['^'] = STRING_ELEMENT,
136 ['_'] = STRING_ELEMENT,
137 ['`'] = STRING_ELEMENT,
138 ['a'] = STRING_ELEMENT,
139 ['b'] = STRING_ELEMENT,
140 ['c'] = STRING_ELEMENT,
141 ['d'] = STRING_ELEMENT,
142 ['e'] = STRING_ELEMENT,
143 ['f'] = GTK_JSON_BOOLEAN | STRING_ELEMENT,
144 ['g'] = STRING_ELEMENT,
145 ['h'] = STRING_ELEMENT,
146 ['i'] = STRING_ELEMENT,
147 ['j'] = STRING_ELEMENT,
148 ['k'] = STRING_ELEMENT,
149 ['l'] = STRING_ELEMENT,
150 ['m'] = STRING_ELEMENT,
151 ['n'] = GTK_JSON_NULL | STRING_ELEMENT,
152 ['o'] = STRING_ELEMENT,
153 ['p'] = STRING_ELEMENT,
154 ['q'] = STRING_ELEMENT,
155 ['r'] = STRING_ELEMENT,
156 ['s'] = STRING_ELEMENT,
157 ['t'] = GTK_JSON_BOOLEAN | STRING_ELEMENT,
158 ['u'] = STRING_ELEMENT,
159 ['v'] = STRING_ELEMENT,
160 ['w'] = STRING_ELEMENT,
161 ['x'] = STRING_ELEMENT,
162 ['y'] = STRING_ELEMENT,
163 ['z'] = STRING_ELEMENT,
164 ['{'] = GTK_JSON_OBJECT | STRING_ELEMENT,
165 ['|'] = STRING_ELEMENT,
166 ['}'] = STRING_ELEMENT,
167 ['~'] = STRING_ELEMENT,
168 [127] = STRING_ELEMENT,
169};
170
171static const guchar *
172json_skip_characters (const guchar *start,
173 const guchar *end,
174 JsonCharacterType type)
175{
176 const guchar *s;
177
178 for (s = start; s < end; s++)
179 {
180 if (!(json_character_table[*s] & type))
181 break;
182 }
183 return s;
184}
185
186static const guchar *
187json_skip_characters_until (const guchar *start,
188 const guchar *end,
189 JsonCharacterType type)
190{
191 const guchar *s;
192
193 for (s = start; s < end; s++)
194 {
195 if (json_character_table[*s] & type)
196 break;
197 }
198 return s;
199}
200
201static const guchar *
202json_find_character (const guchar *start,
203 JsonCharacterType type)
204{
205 const guchar *s;
206
207 for (s = start; ; s++)
208 {
209 if ((json_character_table[*s] & type))
210 break;
211 }
212 return s;
213}
214
215GQuark
216gtk_json_error_quark (void)
217{
218 return g_quark_from_static_string (string: "gtk-json-error-quark");
219}
220
221static void
222gtk_json_parser_take_error (GtkJsonParser *self,
223 const guchar *start_location,
224 const guchar *end_location,
225 GError *error)
226{
227 g_assert (start_location <= end_location);
228 g_assert (self->start <= start_location);
229 g_assert (end_location <= self->end);
230
231 if (self->error)
232 {
233 g_error_free (error);
234 return;
235 }
236
237 self->error = error;
238 self->error_start = start_location;
239 self->error_end = end_location;
240}
241
242static void
243gtk_json_parser_syntax_error_at (GtkJsonParser *self,
244 const guchar *error_start,
245 const guchar *error_end,
246 const char *format,
247 ...) G_GNUC_PRINTF(4, 5);
248static void
249gtk_json_parser_syntax_error_at (GtkJsonParser *self,
250 const guchar *error_start,
251 const guchar *error_end,
252 const char *format,
253 ...)
254{
255 va_list args;
256
257 if (self->error)
258 return;
259
260 va_start (args, format);
261 gtk_json_parser_take_error (self,
262 start_location: error_start,
263 end_location: error_end,
264 error: g_error_new_valist (GTK_JSON_ERROR,
265 code: GTK_JSON_ERROR_SYNTAX,
266 format, args));
267 va_end (args);
268}
269
270static void
271gtk_json_parser_syntax_error (GtkJsonParser *self,
272 const char *format,
273 ...) G_GNUC_PRINTF(2, 3);
274static void
275gtk_json_parser_syntax_error (GtkJsonParser *self,
276 const char *format,
277 ...)
278{
279 va_list args;
280 const guchar *error_end;
281
282 if (self->error)
283 return;
284
285 va_start (args, format);
286 for (error_end = self->reader;
287 error_end < self->end && g_ascii_isalnum (*error_end);
288 error_end++)
289 ;
290 if (error_end == self->reader &&
291 g_utf8_get_char_validated (p: (const char *) error_end, max_len: self->end - error_end) < (gunichar) -2)
292 {
293 error_end = (const guchar *) g_utf8_next_char (error_end);
294 }
295
296 gtk_json_parser_take_error (self,
297 start_location: self->reader,
298 end_location: error_end,
299 error: g_error_new_valist (GTK_JSON_ERROR,
300 code: GTK_JSON_ERROR_SYNTAX,
301 format, args));
302 va_end (args);
303}
304
305static void
306gtk_json_parser_type_error (GtkJsonParser *self,
307 const char *format,
308 ...) G_GNUC_PRINTF(2, 3);
309static void
310gtk_json_parser_type_error (GtkJsonParser *self,
311 const char *format,
312 ...)
313{
314 const guchar *start_location;
315 va_list args;
316
317 if (self->error)
318 return;
319
320 if (self->block->value)
321 start_location = self->block->value;
322 else if (self->block != self->blocks)
323 start_location = self->block[-1].value;
324 else
325 start_location = self->start;
326
327 va_start (args, format);
328 gtk_json_parser_take_error (self,
329 start_location,
330 end_location: self->reader,
331 error: g_error_new_valist (GTK_JSON_ERROR,
332 code: GTK_JSON_ERROR_TYPE,
333 format, args));
334 va_end (args);
335}
336
337void
338gtk_json_parser_value_error (GtkJsonParser *self,
339 const char *format,
340 ...)
341{
342 const guchar *start_location;
343 va_list args;
344
345 if (self->error)
346 return;
347
348 if (self->block->value)
349 start_location = self->block->value;
350 else if (self->block != self->blocks)
351 start_location = self->block[-1].value;
352 else
353 start_location = self->start;
354
355 va_start (args, format);
356 gtk_json_parser_take_error (self,
357 start_location,
358 end_location: self->reader,
359 error: g_error_new_valist (GTK_JSON_ERROR,
360 code: GTK_JSON_ERROR_VALUE,
361 format, args));
362 va_end (args);
363}
364
365void
366gtk_json_parser_schema_error (GtkJsonParser *self,
367 const char *format,
368 ...)
369{
370 const guchar *start_location;
371 va_list args;
372
373 if (self->error)
374 return;
375
376 if (self->block->member_name)
377 start_location = self->block->member_name;
378 if (self->block->value)
379 start_location = self->block->value;
380 else if (self->block != self->blocks)
381 start_location = self->block[-1].value;
382 else
383 start_location = self->start;
384
385 va_start (args, format);
386 gtk_json_parser_take_error (self,
387 start_location,
388 end_location: self->reader,
389 error: g_error_new_valist (GTK_JSON_ERROR,
390 code: GTK_JSON_ERROR_SCHEMA,
391 format, args));
392 va_end (args);
393}
394
395static gboolean
396gtk_json_parser_is_eof (GtkJsonParser *self)
397{
398 return self->reader >= self->end;
399}
400
401static gsize
402gtk_json_parser_remaining (GtkJsonParser *self)
403{
404 g_return_val_if_fail (self->reader <= self->end, 0);
405
406 return self->end - self->reader;
407}
408
409static void
410gtk_json_parser_skip_bom (GtkJsonParser *self)
411{
412 if (gtk_json_parser_remaining (self) < 3)
413 return;
414
415 if (self->reader[0] == 0xEF &&
416 self->reader[1] == 0xBB &&
417 self->reader[2] == 0xBF)
418 self->reader += 3;
419}
420
421static void
422gtk_json_parser_skip_whitespace (GtkJsonParser *self)
423{
424 self->reader = json_skip_characters (start: self->reader, end: self->end, type: WHITESPACE);
425}
426
427static gboolean
428gtk_json_parser_has_char (GtkJsonParser *self,
429 char c)
430{
431 return gtk_json_parser_remaining (self) && *self->reader == c;
432}
433
434static gboolean
435gtk_json_parser_try_char (GtkJsonParser *self,
436 char c)
437{
438 if (!gtk_json_parser_has_char (self, c))
439 return FALSE;
440
441 self->reader++;
442 return TRUE;
443}
444
445static gboolean
446gtk_json_parser_try_identifier_len (GtkJsonParser *self,
447 const char *ident,
448 gsize len)
449{
450 if (gtk_json_parser_remaining (self) < len)
451 return FALSE;
452
453 if (memcmp (s1: self->reader, s2: ident, n: len) != 0)
454 return FALSE;
455
456 self->reader += len;
457 return TRUE;
458}
459
460#define gtk_json_parser_try_identifier(parser, ident) gtk_json_parser_try_identifier_len(parser, ident, strlen(ident))
461
462/*
463 * decode_utf16_surrogate_pair:
464 * @first: the first UTF-16 code point
465 * @second: the second UTF-16 code point
466 *
467 * Decodes a surrogate pair of UTF-16 code points into the equivalent
468 * Unicode code point.
469 *
470 * If the code points are not valid, 0 is returned.
471 *
472 * Returns: the Unicode code point equivalent to the surrogate pair
473 */
474static inline gunichar
475decode_utf16_surrogate_pair (gunichar first,
476 gunichar second)
477{
478 if (0xd800 > first || first > 0xdbff ||
479 0xdc00 > second || second > 0xdfff)
480 return 0;
481
482 return 0x10000
483 | (first & 0x3ff) << 10
484 | (second & 0x3ff);
485}
486
487static gsize
488gtk_json_unescape_char (const guchar *json_escape,
489 char out_data[6],
490 gsize *out_len)
491{
492 switch (json_escape[1])
493 {
494 case '"':
495 case '\\':
496 case '/':
497 out_data[0] = json_escape[1];
498 *out_len = 1;
499 return 2;
500 case 'b':
501 out_data[0] = '\b';
502 *out_len = 1;
503 return 2;
504 case 'f':
505 out_data[0] = '\f';
506 *out_len = 1;
507 return 2;
508 case 'n':
509 out_data[0] = '\n';
510 *out_len = 1;
511 return 2;
512 case 'r':
513 out_data[0] = '\r';
514 *out_len = 1;
515 return 2;
516 case 't':
517 out_data[0] = '\t';
518 *out_len = 1;
519 return 2;
520 case 'u':
521 {
522 gunichar unichar = (g_ascii_xdigit_value (c: json_escape[2]) << 12) |
523 (g_ascii_xdigit_value (c: json_escape[3]) << 8) |
524 (g_ascii_xdigit_value (c: json_escape[4]) << 4) |
525 (g_ascii_xdigit_value (c: json_escape[5]));
526 gsize result = 6;
527
528 /* resolve UTF-16 surrogates for Unicode characters not in the BMP,
529 * as per ECMA 404, § 9, "String"
530 */
531 if (g_unichar_type (c: unichar) == G_UNICODE_SURROGATE)
532 {
533 unichar = decode_utf16_surrogate_pair (first: unichar,
534 second: (g_ascii_xdigit_value (c: json_escape[8]) << 12) |
535 (g_ascii_xdigit_value (c: json_escape[9]) << 8) |
536 (g_ascii_xdigit_value (c: json_escape[10]) << 4) |
537 (g_ascii_xdigit_value (c: json_escape[11])));
538 result += 6;
539 }
540 *out_len = g_unichar_to_utf8 (c: unichar, outbuf: out_data);
541 return result;
542 }
543 default:
544 g_assert_not_reached ();
545 return 0;
546 }
547}
548
549typedef struct _JsonStringIter JsonStringIter;
550struct _JsonStringIter
551{
552 char buf[6];
553 const guchar *s;
554 const guchar *next;
555};
556
557static gsize
558json_string_iter_next (JsonStringIter *iter)
559{
560 gsize len;
561
562 iter->s = iter->next;
563 iter->next = json_find_character (start: iter->s, type: STRING_MARKER);
564 if (iter->next != iter->s)
565 return iter->next - iter->s;
566 if (*iter->next == '"')
567 return 0;
568 iter->next += gtk_json_unescape_char (json_escape: iter->next, out_data: iter->buf, out_len: &len);
569 iter->s = (const guchar *) iter->buf;
570 return len;
571}
572
573/* The escaped string MUST be valid json, so it must begin
574 * with " and end with " and must not contain any invalid
575 * escape codes.
576 * This function is meant to be fast
577 */
578static gsize
579json_string_iter_init (JsonStringIter *iter,
580 const guchar *string)
581{
582 g_assert (*string == '"');
583
584 iter->next = string + 1;
585
586 return json_string_iter_next (iter);
587}
588
589static gboolean
590json_string_iter_has_next (JsonStringIter *iter)
591{
592 return *iter->next != '"';
593}
594
595static const char *
596json_string_iter_get (JsonStringIter *iter)
597{
598 return (const char *) iter->s;
599}
600
601/* The escaped string MUST be valid json, so it must begin
602 * with " and end with " and must not contain any invalid
603 * escape codes.
604 * This function is meant to be fast
605 */
606static char *
607gtk_json_unescape_string (const guchar *escaped)
608{
609 JsonStringIter iter;
610 GString *string;
611 gsize len;
612
613 len = json_string_iter_init (iter: &iter, string: escaped);
614 string = NULL;
615
616 if (!json_string_iter_has_next (iter: &iter))
617 return g_strndup (str: json_string_iter_get (iter: &iter), n: len);
618
619 string = g_string_new (NULL);
620
621 do
622 {
623 g_string_append_len (string, val: json_string_iter_get (iter: &iter), len);
624 }
625 while ((len = json_string_iter_next (iter: &iter)));
626
627 return g_string_free (string, FALSE);
628}
629
630static gboolean
631gtk_json_parser_parse_string (GtkJsonParser *self)
632{
633 const guchar *start;
634
635 start = self->reader;
636
637 if (!gtk_json_parser_try_char (self, c: '"'))
638 {
639 gtk_json_parser_type_error (self, format: "Not a string");
640 return FALSE;
641 }
642
643 self->reader = json_skip_characters (start: self->reader, end: self->end, type: STRING_ELEMENT);
644
645 while (gtk_json_parser_remaining (self))
646 {
647 if (*self->reader < 0x20)
648 {
649 if (*self->reader == '\r' || *self->reader == '\n')
650 gtk_json_parser_syntax_error (self, format: "Newlines in strings are not allowed");
651 else if (*self->reader == '\t')
652 gtk_json_parser_syntax_error (self, format: "Tabs not allowed in strings");
653 else
654 gtk_json_parser_syntax_error (self, format: "Disallowed control character in string literal");
655 return FALSE;
656 }
657 else if (*self->reader > 127)
658 {
659 gunichar c = g_utf8_get_char_validated (p: (const char *) self->reader, max_len: gtk_json_parser_remaining (self));
660 if (c == (gunichar) -2 || c == (gunichar) -1)
661 {
662 gtk_json_parser_syntax_error (self, format: "Invalid UTF-8");
663 return FALSE;
664 }
665 self->reader = (const guchar *) g_utf8_next_char ((const char *) self->reader);
666 }
667 else if (*self->reader == '"')
668 {
669 self->reader++;
670 return TRUE;
671 }
672 else if (*self->reader == '\\')
673 {
674 if (gtk_json_parser_remaining (self) < 2)
675 {
676 self->reader = self->end;
677 goto end;
678 }
679 switch (self->reader[1])
680 {
681 case '"':
682 case '\\':
683 case '/':
684 case 'b':
685 case 'f':
686 case 'n':
687 case 'r':
688 case 't':
689 break;
690
691 case 'u':
692 /* lots of work necessary to validate the unicode escapes here */
693 if (gtk_json_parser_remaining (self) < 6 ||
694 !g_ascii_isxdigit (self->reader[2]) ||
695 !g_ascii_isxdigit (self->reader[3]) ||
696 !g_ascii_isxdigit (self->reader[4]) ||
697 !g_ascii_isxdigit (self->reader[5]))
698 {
699 const guchar *end;
700 for (end = self->reader + 2;
701 end < self->reader + 6 && end < self->end;
702 end++)
703 {
704 if (!g_ascii_isxdigit (*end))
705 break;
706 }
707 gtk_json_parser_syntax_error_at (self, error_start: self->reader, error_end: end, format: "Invalid Unicode escape sequence");
708 return FALSE;
709 }
710 else
711 {
712 gsize escape_size = 6;
713 gunichar unichar = (g_ascii_xdigit_value (c: self->reader[2]) << 12) |
714 (g_ascii_xdigit_value (c: self->reader[3]) << 8) |
715 (g_ascii_xdigit_value (c: self->reader[4]) << 4) |
716 (g_ascii_xdigit_value (c: self->reader[5]));
717
718 /* resolve UTF-16 surrogates for Unicode characters not in the BMP,
719 * as per ECMA 404, § 9, "String"
720 */
721 if (g_unichar_type (c: unichar) == G_UNICODE_SURROGATE)
722 {
723 if (gtk_json_parser_remaining (self) >= 12 &&
724 self->reader[6] == '\\' &&
725 self->reader[7] == 'u' &&
726 g_ascii_isxdigit (self->reader[8]) &&
727 g_ascii_isxdigit (self->reader[9]) &&
728 g_ascii_isxdigit (self->reader[10]) &&
729 g_ascii_isxdigit (self->reader[11]))
730 {
731 unichar = decode_utf16_surrogate_pair (first: unichar,
732 second: (g_ascii_xdigit_value (c: self->reader[8]) << 12) |
733 (g_ascii_xdigit_value (c: self->reader[9]) << 8) |
734 (g_ascii_xdigit_value (c: self->reader[10]) << 4) |
735 (g_ascii_xdigit_value (c: self->reader[11])));
736 escape_size += 6;
737 }
738 else
739 {
740 unichar = 0;
741 }
742
743 if (unichar == 0)
744 {
745 gtk_json_parser_syntax_error_at (self, error_start: self->reader, error_end: self->reader + escape_size, format: "Invalid UTF-16 surrogate pair");
746 return FALSE;
747 }
748
749 self->reader += escape_size - 2;
750 }
751 }
752 break;
753 default:
754 if (g_utf8_get_char_validated (p: (const char *) self->reader + 1, max_len: self->end - self->reader - 1) < (gunichar) -2)
755 gtk_json_parser_syntax_error_at (self, error_start: self->reader, error_end: (const guchar *) g_utf8_next_char (self->reader + 1), format: "Unknown escape sequence");
756 else
757 gtk_json_parser_syntax_error_at (self, error_start: self->reader, error_end: self->reader + 1, format: "Unknown escape sequence");
758 return FALSE;
759 }
760 self->reader += 2;
761 }
762
763 self->reader = json_skip_characters (start: self->reader, end: self->end, type: STRING_ELEMENT);
764 }
765
766end:
767 gtk_json_parser_syntax_error_at (self, error_start: start, error_end: self->reader, format: "Unterminated string literal");
768 return FALSE;
769}
770
771static gboolean
772gtk_json_parser_parse_number (GtkJsonParser *self)
773{
774 const guchar *start = self->reader;
775 gboolean have_sign;
776
777 /* sign */
778 have_sign = gtk_json_parser_try_char (self, c: '-');
779
780 /* integer part */
781 if (gtk_json_parser_try_char (self, c: '0'))
782 {
783 /* Technically, "01" in the JSON grammar would be 2 numbers:
784 * "0" followed by "1".
785 * Practically, nobody understands that it's 2 numbers, so we
786 * special-purpose an error message for it, because 2 numbers
787 * can never follow each other.
788 */
789 if (!gtk_json_parser_is_eof (self) &&
790 g_ascii_isdigit (*self->reader))
791 {
792 do
793 {
794 self->reader++;
795 }
796 while (!gtk_json_parser_is_eof (self) &&
797 g_ascii_isdigit (*self->reader));
798
799 gtk_json_parser_syntax_error_at (self, error_start: start, error_end: self->reader, format: "Numbers may not start with leading 0s");
800 return FALSE;
801 }
802 }
803 else
804 {
805 if (gtk_json_parser_is_eof (self) ||
806 !g_ascii_isdigit (*self->reader))
807 {
808 if (have_sign)
809 gtk_json_parser_syntax_error_at (self, error_start: start, error_end: self->reader, format: "Expected a number after '-' character");
810 else
811 gtk_json_parser_type_error (self, format: "Not a number");
812 return FALSE;
813 }
814
815 self->reader++;
816
817 while (!gtk_json_parser_is_eof (self) && g_ascii_isdigit (*self->reader))
818 self->reader++;
819 }
820
821 /* fractional part */
822 if (gtk_json_parser_try_char (self, c: '.'))
823 {
824 if (!g_ascii_isdigit (*self->reader))
825 {
826 gtk_json_parser_syntax_error_at (self, error_start: start, error_end: self->reader, format: "Expected a digit after '.'");
827 return FALSE;
828 }
829
830 do
831 {
832 self->reader++;
833 }
834 while (!gtk_json_parser_is_eof (self) && g_ascii_isdigit (*self->reader));
835 }
836
837 /* exponent */
838 if (gtk_json_parser_try_char (self, c: 'e') ||
839 gtk_json_parser_try_char (self, c: 'E'))
840 {
841 if (!gtk_json_parser_try_char (self, c: '-'))
842 gtk_json_parser_try_char (self, c: '+');
843
844 if (!g_ascii_isdigit (*self->reader))
845 {
846 gtk_json_parser_syntax_error_at (self, error_start: start, error_end: self->reader, format: "Expected a digit in exponent");
847 return FALSE;
848 }
849
850 do
851 {
852 self->reader++;
853 }
854 while (!gtk_json_parser_is_eof (self) && g_ascii_isdigit (*self->reader));
855 }
856 return TRUE;
857}
858
859static gboolean
860gtk_json_parser_parse_value (GtkJsonParser *self)
861{
862 if (gtk_json_parser_is_eof (self))
863 {
864 gtk_json_parser_syntax_error (self, format: "Unexpected end of document");
865 return FALSE;
866 }
867
868 switch (json_character_table[*self->block->value] & JSON_CHARACTER_NODE_MASK)
869 {
870 case GTK_JSON_STRING:
871 return gtk_json_parser_parse_string (self);
872
873 case GTK_JSON_NUMBER:
874 return gtk_json_parser_parse_number (self);
875
876 case GTK_JSON_NULL:
877 if (gtk_json_parser_try_identifier (self, "null"))
878 return TRUE;
879 break;
880
881 case GTK_JSON_BOOLEAN:
882 if (gtk_json_parser_try_identifier (self, "true") ||
883 gtk_json_parser_try_identifier (self, "false"))
884 return TRUE;
885 break;
886
887 case GTK_JSON_OBJECT:
888 case GTK_JSON_ARRAY:
889 /* don't preparse objects */
890 return TRUE;
891
892 default:
893 break;
894 }
895
896 if (gtk_json_parser_remaining (self) >= 2 &&
897 (self->block->value[0] == '.' || self->block->value[0] == '+') &&
898 g_ascii_isdigit (self->block->value[1]))
899 {
900 const guchar *end = self->block->value + 2;
901 while (end < self->end && g_ascii_isalnum (*end))
902 end++;
903 gtk_json_parser_syntax_error_at (self, error_start: self->block->value, error_end: end, format: "Numbers may not start with '%c'", *self->block->value);
904 }
905 else if (*self->reader == 0)
906 gtk_json_parser_syntax_error (self, format: "Unexpected nul byte in document");
907 else
908 gtk_json_parser_syntax_error (self, format: "Expected a value");
909 return FALSE;
910}
911
912static void
913gtk_json_parser_push_block (GtkJsonParser *self,
914 GtkJsonBlockType type)
915{
916 self->block++;
917 if (self->block == self->blocks_end)
918 {
919 gsize old_size = self->blocks_end - self->blocks;
920 gsize new_size = old_size + 128;
921
922 if (self->blocks == self->blocks_preallocated)
923 {
924 self->blocks = g_new (GtkJsonBlock, new_size);
925 memcpy (dest: self->blocks, src: self->blocks_preallocated, n: sizeof (GtkJsonBlock) * G_N_ELEMENTS (self->blocks_preallocated));
926 }
927 else
928 {
929 self->blocks = g_renew (GtkJsonBlock, self->blocks, new_size);
930 }
931 self->blocks_end = self->blocks + new_size;
932 self->block = self->blocks + old_size;
933 }
934
935 self->block->type = type;
936 self->block->member_name = 0;
937 self->block->value = 0;
938 self->block->index = 0;
939}
940
941static void
942gtk_json_parser_pop_block (GtkJsonParser *self)
943{
944 g_assert (self->block > self->blocks);
945 self->block--;
946}
947
948GtkJsonParser *
949gtk_json_parser_new_for_string (const char *string,
950 gssize size)
951{
952 GtkJsonParser *self;
953 GBytes *bytes;
954
955 bytes = g_bytes_new (data: string, size: size >= 0 ? size : strlen (s: string));
956
957 self = gtk_json_parser_new_for_bytes (bytes);
958
959 g_bytes_unref (bytes);
960
961 return self;
962}
963
964GtkJsonParser *
965gtk_json_parser_new_for_bytes (GBytes *bytes)
966{
967 GtkJsonParser *self;
968 gsize size;
969
970 g_return_val_if_fail (bytes != NULL, NULL);
971
972 self = g_slice_new0 (GtkJsonParser);
973
974 self->bytes = g_bytes_ref (bytes);
975 self->reader = g_bytes_get_data (bytes, size: &size);
976 self->end = self->reader + size;
977
978 self->blocks = self->blocks_preallocated;
979 self->blocks_end = self->blocks + G_N_ELEMENTS (self->blocks_preallocated);
980 self->block = self->blocks;
981 self->block->type = GTK_JSON_BLOCK_TOPLEVEL;
982
983 gtk_json_parser_skip_bom (self);
984 self->start = self->reader;
985 gtk_json_parser_rewind (self);
986
987 return self;
988}
989
990void
991gtk_json_parser_free (GtkJsonParser *self)
992{
993 if (self == NULL)
994 return;
995
996 g_bytes_unref (bytes: self->bytes);
997
998 if (self->blocks != self->blocks_preallocated)
999 g_free (mem: self->blocks);
1000
1001 if (self->error)
1002 g_error_free (error: self->error);
1003
1004 g_slice_free (GtkJsonParser, self);
1005}
1006
1007static gboolean
1008gtk_json_parser_skip_block (GtkJsonParser *self)
1009{
1010 gsize depth;
1011
1012 if (self->reader != self->block->value)
1013 return TRUE;
1014
1015 depth = gtk_json_parser_get_depth (self);
1016 while (TRUE)
1017 {
1018 if (*self->reader == '{')
1019 {
1020 if (!gtk_json_parser_start_object (self))
1021 return FALSE;
1022 }
1023 else if (*self->reader == '[')
1024 {
1025 if (!gtk_json_parser_start_array (self))
1026 return FALSE;
1027 }
1028
1029 while (self->reader != self->block->value)
1030 {
1031 /* This should never be reentrant to this function or we might
1032 * loop causing stack overflow */
1033 if (!gtk_json_parser_next (self))
1034 {
1035 if (!gtk_json_parser_end (self))
1036 return FALSE;
1037 if (depth >= gtk_json_parser_get_depth (self))
1038 return TRUE;
1039 }
1040 }
1041 }
1042
1043 return TRUE;
1044}
1045
1046gboolean
1047gtk_json_parser_next (GtkJsonParser *self)
1048{
1049 if (self->error)
1050 return FALSE;
1051
1052 if (self->block->value == NULL)
1053 return FALSE;
1054
1055 if (!gtk_json_parser_skip_block (self))
1056 {
1057 g_assert (self->error);
1058 return FALSE;
1059 }
1060
1061 switch (self->block->type)
1062 {
1063 case GTK_JSON_BLOCK_TOPLEVEL:
1064 gtk_json_parser_skip_whitespace (self);
1065 if (gtk_json_parser_is_eof (self))
1066 {
1067 self->block->value = NULL;
1068 }
1069 else if (*self->reader == 0)
1070 {
1071 gtk_json_parser_syntax_error (self, format: "Unexpected nul byte in document");
1072 }
1073 else
1074 {
1075 gtk_json_parser_syntax_error_at (self, error_start: self->reader, error_end: self->end, format: "Data at end of document");
1076 }
1077 return FALSE;
1078
1079 case GTK_JSON_BLOCK_OBJECT:
1080 gtk_json_parser_skip_whitespace (self);
1081 if (gtk_json_parser_is_eof (self))
1082 {
1083 gtk_json_parser_syntax_error_at (self,
1084 error_start: self->block[-1].value,
1085 error_end: self->reader,
1086 format: "Unterminated object");
1087 self->block->member_name = NULL;
1088 self->block->value = NULL;
1089 }
1090 if (gtk_json_parser_has_char (self, c: '}'))
1091 {
1092 self->block->member_name = NULL;
1093 self->block->value = NULL;
1094 return FALSE;
1095 }
1096 if (!gtk_json_parser_try_char (self, c: ','))
1097 {
1098 gtk_json_parser_syntax_error (self, format: "Expected a ',' to separate object members");
1099 return FALSE;
1100 }
1101 gtk_json_parser_skip_whitespace (self);
1102 if (!gtk_json_parser_has_char (self, c: '"'))
1103 {
1104 gtk_json_parser_syntax_error (self, format: "Expected a string for object member name");
1105 return FALSE;
1106 }
1107 self->block->member_name = self->reader;
1108
1109 if (!gtk_json_parser_parse_string (self))
1110 return FALSE;
1111 gtk_json_parser_skip_whitespace (self);
1112 if (!gtk_json_parser_try_char (self, c: ':'))
1113 {
1114 gtk_json_parser_syntax_error (self, format: "Missing ':' after member name");
1115 return FALSE;
1116 }
1117
1118 gtk_json_parser_skip_whitespace (self);
1119 self->block->value = self->reader;
1120 if (!gtk_json_parser_parse_value (self))
1121 return FALSE;
1122 break;
1123
1124 case GTK_JSON_BLOCK_ARRAY:
1125 gtk_json_parser_skip_whitespace (self);
1126 if (gtk_json_parser_is_eof (self))
1127 {
1128 gtk_json_parser_syntax_error_at (self,
1129 error_start: self->block[-1].value,
1130 error_end: self->reader,
1131 format: "Unterminated array");
1132 self->block->member_name = NULL;
1133 self->block->value = NULL;
1134 }
1135 if (gtk_json_parser_has_char (self, c: ']'))
1136 {
1137 self->block->value = NULL;
1138 return FALSE;
1139 }
1140
1141 if (!gtk_json_parser_try_char (self, c: ','))
1142 {
1143 gtk_json_parser_syntax_error (self, format: "Expected a ',' to separate array members");
1144 return FALSE;
1145 }
1146
1147 gtk_json_parser_skip_whitespace (self);
1148 self->block->value = self->reader;
1149 if (!gtk_json_parser_parse_value (self))
1150 return FALSE;
1151 break;
1152
1153 default:
1154 g_assert_not_reached ();
1155 break;
1156 }
1157
1158 return TRUE;
1159}
1160
1161void
1162gtk_json_parser_rewind (GtkJsonParser *self)
1163{
1164 if (self->error)
1165 return;
1166
1167 switch (self->block->type)
1168 {
1169 case GTK_JSON_BLOCK_OBJECT:
1170 gtk_json_parser_pop_block (self);
1171 self->reader = self->block->value;
1172 gtk_json_parser_start_object (self);
1173 break;
1174
1175 case GTK_JSON_BLOCK_ARRAY:
1176 gtk_json_parser_pop_block (self);
1177 self->reader = self->block->value;
1178 gtk_json_parser_start_array (self);
1179 break;
1180
1181 case GTK_JSON_BLOCK_TOPLEVEL:
1182 self->reader = self->start;
1183 gtk_json_parser_skip_whitespace (self);
1184 if (gtk_json_parser_is_eof (self))
1185 {
1186 gtk_json_parser_syntax_error_at (self, error_start: self->start, error_end: self->reader, format: "Empty document");
1187 }
1188 else
1189 {
1190 self->block->value = self->reader;
1191 gtk_json_parser_parse_value (self);
1192 }
1193 break;
1194
1195 default:
1196 g_assert_not_reached ();
1197 return;
1198 }
1199}
1200
1201gsize
1202gtk_json_parser_get_depth (GtkJsonParser *self)
1203{
1204 return self->block - self->blocks;
1205}
1206
1207GtkJsonNode
1208gtk_json_parser_get_node (GtkJsonParser *self)
1209{
1210 if (self->error)
1211 return GTK_JSON_NONE;
1212
1213 if (self->block->value == NULL)
1214 return GTK_JSON_NONE;
1215
1216 return (json_character_table[*self->block->value] & JSON_CHARACTER_NODE_MASK);
1217}
1218
1219const GError *
1220gtk_json_parser_get_error (GtkJsonParser *self)
1221{
1222 return self->error;
1223}
1224
1225void
1226gtk_json_parser_get_error_offset (GtkJsonParser *self,
1227 gsize *start,
1228 gsize *end)
1229{
1230 const guchar *data;
1231
1232 if (self->error == NULL)
1233 {
1234 if (start)
1235 *start = 0;
1236 if (end)
1237 *end = 0;
1238 return;
1239 }
1240
1241 data = g_bytes_get_data (bytes: self->bytes, NULL);
1242 if (start)
1243 *start = self->error_start - data;
1244 if (end)
1245 *end = self->error_end - data;
1246}
1247
1248void
1249gtk_json_parser_get_error_location (GtkJsonParser *self,
1250 gsize *start_line,
1251 gsize *start_line_bytes,
1252 gsize *end_line,
1253 gsize *end_line_bytes)
1254{
1255 const guchar *s, *line_start;
1256 gsize lines;
1257
1258 if (self->error == NULL)
1259 {
1260 if (start_line)
1261 *start_line = 0;
1262 if (start_line_bytes)
1263 *start_line_bytes = 0;
1264 if (end_line)
1265 *end_line = 0;
1266 if (end_line_bytes)
1267 *end_line_bytes = 0;
1268 return;
1269 }
1270
1271 line_start = self->start;
1272 lines = 0;
1273
1274 for (s = json_skip_characters_until (start: line_start, end: self->error_start, type: NEWLINE);
1275 s < self->error_start;
1276 s = json_skip_characters_until (start: line_start, end: self->error_start, type: NEWLINE))
1277 {
1278 if (s[0] == '\r' && s + 1 < self->error_start && s[1] == '\n')
1279 s++;
1280 lines++;
1281 line_start = s + 1;
1282 }
1283
1284 if (start_line)
1285 *start_line = lines;
1286 if (start_line_bytes)
1287 *start_line_bytes = s - line_start;
1288
1289 if (end_line == NULL && end_line_bytes == NULL)
1290 return;
1291
1292 for (s = json_skip_characters_until (start: s, end: self->error_end, type: NEWLINE);
1293 s < self->error_end;
1294 s = json_skip_characters_until (start: line_start, end: self->error_end, type: NEWLINE))
1295 {
1296 if (s[0] == '\r' && s + 1 < self->error_start && s[1] == '\n')
1297 s++;
1298 lines++;
1299 line_start = s + 1;
1300 }
1301
1302 if (end_line)
1303 *end_line = lines;
1304 if (end_line_bytes)
1305 *end_line_bytes = s - line_start;
1306}
1307
1308static gboolean
1309gtk_json_parser_supports_member (GtkJsonParser *self)
1310{
1311 if (self->error)
1312 return FALSE;
1313
1314 if (self->block->type != GTK_JSON_BLOCK_OBJECT)
1315 return FALSE;
1316
1317 if (self->block->member_name == NULL)
1318 return FALSE;
1319
1320 return TRUE;
1321}
1322
1323char *
1324gtk_json_parser_get_member_name (GtkJsonParser *self)
1325{
1326 if (!gtk_json_parser_supports_member (self))
1327 return NULL;
1328
1329 return gtk_json_unescape_string (escaped: self->block->member_name);
1330}
1331
1332gboolean
1333gtk_json_parser_has_member (GtkJsonParser *self,
1334 const char *name)
1335{
1336 JsonStringIter iter;
1337 gsize found, len;
1338
1339 if (!gtk_json_parser_supports_member (self))
1340 return FALSE;
1341
1342 found = 0;
1343
1344 for (len = json_string_iter_init (iter: &iter, string: self->block->member_name);
1345 len > 0;
1346 len = json_string_iter_next (iter: &iter))
1347 {
1348 const char *s = json_string_iter_get (iter: &iter);
1349
1350 if (strncmp (s1: name + found, s2: s, n: len) != 0)
1351 return FALSE;
1352
1353 found += len;
1354 }
1355
1356 return TRUE;
1357}
1358
1359gboolean
1360gtk_json_parser_find_member (GtkJsonParser *self,
1361 const char *name)
1362{
1363 if (!gtk_json_parser_supports_member (self))
1364 {
1365 while (gtk_json_parser_next (self));
1366 return FALSE;
1367 }
1368
1369 gtk_json_parser_rewind (self);
1370
1371 do
1372 {
1373 if (gtk_json_parser_has_member (self, name))
1374 return TRUE;
1375 }
1376 while (gtk_json_parser_next (self));
1377
1378 return FALSE;
1379}
1380
1381static gssize
1382json_string_iter_run_select (const guchar *string_data,
1383 const char * const *options)
1384{
1385 JsonStringIter iter;
1386 gssize i, j;
1387 gsize found, len;
1388
1389 if (options == NULL || options[0] == NULL)
1390 return -1;
1391
1392 found = 0;
1393 i = 0;
1394
1395 for (len = json_string_iter_init (iter: &iter, string: string_data);
1396 len > 0;
1397 len = json_string_iter_next (iter: &iter))
1398 {
1399 const char *s = json_string_iter_get (iter: &iter);
1400
1401 if (strncmp (s1: options[i] + found, s2: s, n: len) != 0)
1402 {
1403 for (j = i + 1; options[j]; j++)
1404 {
1405 if (strncmp (s1: options[j], s2: options[i], n: found) == 0 &&
1406 strncmp (s1: options[j] + found, s2: s, n: len) == 0)
1407 {
1408 i = j;
1409 break;
1410 }
1411 }
1412 if (j != i)
1413 return -1;
1414 }
1415 found += len;
1416 }
1417
1418 if (options[i][found] == 0)
1419 return i;
1420
1421 for (j = i + 1; options[j]; i++)
1422 {
1423 if (strncmp (s1: options[j], s2: options[i], n: found) != 0)
1424 continue;
1425 if (options[j][found] == 0)
1426 return j;
1427 }
1428
1429 return -1;
1430}
1431
1432gssize
1433gtk_json_parser_select_member (GtkJsonParser *self,
1434 const char * const *options)
1435{
1436 if (!gtk_json_parser_supports_member (self))
1437 return -1;
1438
1439 return json_string_iter_run_select (string_data: self->block->member_name, options);
1440}
1441
1442gboolean
1443gtk_json_parser_get_boolean (GtkJsonParser *self)
1444{
1445 if (self->error)
1446 return FALSE;
1447
1448 if (self->block->value == NULL)
1449 return FALSE;
1450
1451 if (*self->block->value == 't')
1452 return TRUE;
1453 else if (*self->block->value == 'f')
1454 return FALSE;
1455
1456 gtk_json_parser_type_error (self, format: "Expected a boolean value");
1457 return FALSE;
1458}
1459
1460double
1461gtk_json_parser_get_number (GtkJsonParser *self)
1462{
1463 double result;
1464
1465 if (self->error)
1466 return 0;
1467
1468 if (self->block->value == NULL)
1469 return 0;
1470
1471 if (!strchr (s: "-0123456789", c: *self->block->value))
1472 {
1473 gtk_json_parser_type_error (self, format: "Expected a number");
1474 return 0;
1475 }
1476
1477 errno = 0;
1478 result = g_ascii_strtod (nptr: (const char *) self->block->value, NULL);
1479
1480 if (errno)
1481 {
1482 if (errno == ERANGE)
1483 gtk_json_parser_value_error (self, format: "Number out of range");
1484 else
1485 gtk_json_parser_value_error (self, format: "%s", g_strerror (errno));
1486
1487 return 0;
1488 }
1489
1490 return result;
1491}
1492
1493int
1494gtk_json_parser_get_int (GtkJsonParser *self)
1495{
1496 long result;
1497 char *end;
1498
1499 if (self->error)
1500 return 0;
1501
1502 if (self->block->value == NULL)
1503 return 0;
1504
1505 if (!strchr (s: "-0123456789", c: *self->block->value))
1506 {
1507 gtk_json_parser_type_error (self, format: "Expected an intereger");
1508 return 0;
1509 }
1510
1511 errno = 0;
1512 result = strtol (nptr: (const char *) self->block->value, endptr: &end, base: 10);
1513 if (*end == '.' || *end == 'e' || *end == 'E')
1514 {
1515 gtk_json_parser_type_error (self, format: "Expected an intereger");
1516 return 0;
1517 }
1518
1519 if (errno)
1520 {
1521 if (errno == ERANGE)
1522 gtk_json_parser_value_error (self, format: "Number out of integer range");
1523 else
1524 gtk_json_parser_value_error (self, format: "%s", g_strerror (errno));
1525
1526 return 0;
1527 }
1528 else if (result > G_MAXINT || result < G_MININT)
1529 {
1530 gtk_json_parser_value_error (self, format: "Number out of integer range");
1531 return 0;
1532 }
1533
1534 return result;
1535}
1536
1537guint
1538gtk_json_parser_get_uint (GtkJsonParser *self)
1539{
1540 gulong result;
1541 char *end;
1542
1543 if (self->error)
1544 return 0;
1545
1546 if (self->block->value == NULL)
1547 return 0;
1548
1549 if (!strchr (s: "0123456789", c: *self->block->value))
1550 {
1551 gtk_json_parser_type_error (self, format: "Expected an unsigned intereger");
1552 return 0;
1553 }
1554
1555 errno = 0;
1556 result = strtoul (nptr: (const char *) self->block->value, endptr: &end, base: 10);
1557 if (*end == '.' || *end == 'e' || *end == 'E')
1558 {
1559 gtk_json_parser_type_error (self, format: "Expected an unsigned intereger");
1560 return 0;
1561 }
1562
1563 if (errno)
1564 {
1565 if (errno == ERANGE)
1566 gtk_json_parser_value_error (self, format: "Number out of unsignedinteger range");
1567 else
1568 gtk_json_parser_value_error (self, format: "%s", g_strerror (errno));
1569
1570 return 0;
1571 }
1572 else if (result > G_MAXUINT)
1573 {
1574 gtk_json_parser_value_error (self, format: "Number out of unsigned integer range");
1575 return 0;
1576 }
1577
1578 return result;
1579}
1580
1581char *
1582gtk_json_parser_get_string (GtkJsonParser *self)
1583{
1584 if (self->error)
1585 return g_strdup (str: "");
1586
1587 if (self->block->value == NULL)
1588 return g_strdup (str: "");
1589
1590 if (*self->block->value != '"')
1591 {
1592 gtk_json_parser_type_error (self, format: "Expected a string");
1593 return g_strdup (str: "");
1594 }
1595
1596 return gtk_json_unescape_string (escaped: self->block->value);
1597}
1598
1599gssize
1600gtk_json_parser_select_string (GtkJsonParser *self,
1601 const char * const *options)
1602{
1603 if (self->error)
1604 return -1;
1605
1606 if (self->block->value == NULL)
1607 return -1;
1608
1609 if (*self->block->value != '"')
1610 {
1611 gtk_json_parser_type_error (self, format: "Expected a string");
1612 return -1;
1613 }
1614
1615 return json_string_iter_run_select (string_data: self->block->value, options);
1616}
1617
1618gboolean
1619gtk_json_parser_start_object (GtkJsonParser *self)
1620{
1621 if (self->error)
1622 return FALSE;
1623
1624 if (!gtk_json_parser_try_char (self, c: '{'))
1625 {
1626 gtk_json_parser_type_error (self, format: "Expected an object");
1627 return FALSE;
1628 }
1629
1630 gtk_json_parser_push_block (self, type: GTK_JSON_BLOCK_OBJECT);
1631
1632 gtk_json_parser_skip_whitespace (self);
1633 if (gtk_json_parser_is_eof (self))
1634 {
1635 gtk_json_parser_syntax_error_at (self,
1636 error_start: self->block[-1].value,
1637 error_end: self->reader,
1638 format: "Unterminated object");
1639 return FALSE;
1640 }
1641 if (gtk_json_parser_has_char (self, c: '}'))
1642 return TRUE;
1643
1644 if (!gtk_json_parser_has_char (self, c: '"'))
1645 {
1646 gtk_json_parser_syntax_error (self, format: "Expected a string for object member name");
1647 return FALSE;
1648 }
1649 self->block->member_name = self->reader;
1650
1651 if (!gtk_json_parser_parse_string (self))
1652 return FALSE;
1653 gtk_json_parser_skip_whitespace (self);
1654 if (!gtk_json_parser_try_char (self, c: ':'))
1655 {
1656 gtk_json_parser_syntax_error (self, format: "Missing ':' after member name");
1657 return FALSE;
1658 }
1659
1660 gtk_json_parser_skip_whitespace (self);
1661 self->block->value = self->reader;
1662 if (!gtk_json_parser_parse_value (self))
1663 return FALSE;
1664
1665 return TRUE;
1666}
1667
1668gboolean
1669gtk_json_parser_start_array (GtkJsonParser *self)
1670{
1671 if (self->error)
1672 return FALSE;
1673
1674 if (!gtk_json_parser_try_char (self, c: '['))
1675 {
1676 gtk_json_parser_type_error (self, format: "Expected an array");
1677 return FALSE;
1678 }
1679
1680 gtk_json_parser_push_block (self, type: GTK_JSON_BLOCK_ARRAY);
1681 gtk_json_parser_skip_whitespace (self);
1682 if (gtk_json_parser_is_eof (self))
1683 {
1684 gtk_json_parser_syntax_error_at (self,
1685 error_start: self->block[-1].value,
1686 error_end: self->reader,
1687 format: "Unterminated array");
1688 return FALSE;
1689 }
1690 if (gtk_json_parser_has_char (self, c: ']'))
1691 {
1692 self->block->value = NULL;
1693 return TRUE;
1694 }
1695 self->block->value = self->reader;
1696 if (!gtk_json_parser_parse_value (self))
1697 return FALSE;
1698
1699 return TRUE;
1700}
1701
1702gboolean
1703gtk_json_parser_end (GtkJsonParser *self)
1704{
1705 char bracket;
1706
1707 g_return_val_if_fail (self != NULL, FALSE);
1708
1709 while (gtk_json_parser_next (self));
1710
1711 if (self->error)
1712 return FALSE;
1713
1714 switch (self->block->type)
1715 {
1716 case GTK_JSON_BLOCK_OBJECT:
1717 bracket = '}';
1718 break;
1719 case GTK_JSON_BLOCK_ARRAY:
1720 bracket = ']';
1721 break;
1722 case GTK_JSON_BLOCK_TOPLEVEL:
1723 default:
1724 g_return_val_if_reached (FALSE);
1725 }
1726
1727 if (!gtk_json_parser_try_char (self, c: bracket))
1728 {
1729 gtk_json_parser_syntax_error (self, format: "No terminating '%c'", bracket);
1730 return FALSE;
1731 }
1732
1733 gtk_json_parser_pop_block (self);
1734
1735 return TRUE;
1736}
1737
1738

source code of gtk/subprojects/pango/pango/json/gtkjsonparser.c