Coverage Report

Created: 2025-07-18 06:10

/src/tinysparql/subprojects/json-glib-1.10.6/json-glib/json-parser.c
Line
Count
Source (jump to first uncovered line)
1
/* json-parser.c - JSON streams parser
2
 * 
3
 * This file is part of JSON-GLib
4
 *
5
 * SPDX-FileCopyrightText: 2007, 2008, 2009 OpenedHand Ltd
6
 * SPDX-FileCopyrightText: 2009, 2010 Intel Corp.
7
 * SPDX-FileCopyrightText: 2015 Collabora Ltd.
8
 * SPDX-License-Identifier: LGPL-2.1-or-later
9
 *
10
 * This library is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU Lesser General Public
12
 * License as published by the Free Software Foundation; either
13
 * version 2.1 of the License, or (at your option) any later version.
14
 *
15
 * This library is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 * Lesser General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public
21
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
22
 *
23
 * Author:
24
 *   Emmanuele Bassi  <ebassi@linux.intel.com>
25
 *   Philip Withnall  <philip.withnall@collabora.co.uk>
26
 */
27
28
/**
29
 * JsonParser:
30
 *
31
 * `JsonParser` provides an object for parsing a JSON data stream, either
32
 * inside a file or inside a static buffer.
33
 *
34
 * ## Using `JsonParser`
35
 *
36
 * The `JsonParser` API is fairly simple:
37
 *
38
 * ```c
39
 * gboolean
40
 * parse_json (const char *filename)
41
 * {
42
 *   g_autoptr(JsonParser) parser = json_parser_new ();
43
 *   g_autoptr(GError) error = NULL
44
 *
45
 *   json_parser_load_from_file (parser, filename, &error);
46
 *   if (error != NULL)
47
 *     {
48
 *       g_critical ("Unable to parse '%s': %s", filename, error->message);
49
 *       return FALSE;
50
 *     }
51
 *
52
 *   g_autoptr(JsonNode) root = json_parser_get_root (parser);
53
 *
54
 *   // manipulate the object tree from the root node
55
 *
56
 *   return TRUE
57
 * }
58
 * ```
59
 *
60
 * By default, the entire process of loading the data and parsing it is
61
 * synchronous; the [method@Json.Parser.load_from_stream_async] API will
62
 * load the data asynchronously, but parse it in the main context as the
63
 * signals of the parser must be emitted in the same thread. If you do
64
 * not use signals, and you wish to also parse the JSON data without blocking,
65
 * you should use a `GTask` and the synchronous `JsonParser` API inside the
66
 * task itself.
67
 */
68
69
#include "config.h"
70
71
#include <string.h>
72
73
#include <glib/gi18n-lib.h>
74
75
#include "json-types-private.h"
76
77
#include "json-debug.h"
78
#include "json-parser.h"
79
#include "json-scanner.h"
80
81
struct _JsonParserPrivate
82
{
83
  JsonNode *root;
84
  JsonNode *current_node;
85
86
  JsonScanner *scanner;
87
88
  JsonParserError error_code;
89
  GError *last_error;
90
91
  gchar *variable_name;
92
  gchar *filename;
93
94
  bool multi_root;
95
96
  guint has_assignment : 1;
97
  guint is_filename    : 1;
98
  guint is_immutable   : 1;
99
  guint is_strict      : 1;
100
};
101
102
enum
103
{
104
  PARSE_START,
105
  OBJECT_START,
106
  OBJECT_MEMBER,
107
  OBJECT_END,
108
  ARRAY_START,
109
  ARRAY_ELEMENT,
110
  ARRAY_END,
111
  PARSE_END,
112
  ERROR,
113
114
  LAST_SIGNAL
115
};
116
117
static guint parser_signals[LAST_SIGNAL] = { 0, };
118
119
enum
120
{
121
  PROP_IMMUTABLE = 1,
122
  PROP_STRICT,
123
  PROP_LAST
124
};
125
126
static GParamSpec *parser_props[PROP_LAST] = { NULL, };
127
128
G_DEFINE_QUARK (json-parser-error-quark, json_parser_error)
129
130
G_DEFINE_TYPE_WITH_PRIVATE (JsonParser, json_parser, G_TYPE_OBJECT)
131
132
static guint json_parse_array  (JsonParser    *parser,
133
                                JsonScanner   *scanner,
134
                                JsonNode     **node,
135
                                unsigned int   nesting);
136
static guint json_parse_object (JsonParser    *parser,
137
                                JsonScanner   *scanner,
138
                                JsonNode     **node,
139
                                unsigned int   nesting);
140
141
static inline void
142
json_parser_clear (JsonParser *parser)
143
32.7k
{
144
32.7k
  JsonParserPrivate *priv = parser->priv;
145
146
32.7k
  g_clear_pointer (&priv->variable_name, g_free);
147
32.7k
  g_clear_pointer (&priv->last_error, g_error_free);
148
32.7k
  g_clear_pointer (&priv->root, json_node_unref);
149
150
32.7k
  priv->multi_root = false;
151
32.7k
}
152
153
static inline void
154
json_parser_emit_array_start (JsonParser *parser)
155
189k
{
156
189k
  JsonParserClass *klass = JSON_PARSER_GET_CLASS (parser);
157
158
189k
  if (g_signal_has_handler_pending (parser, parser_signals[ARRAY_START], 0, FALSE))
159
0
    g_signal_emit (parser, parser_signals[ARRAY_START], 0);
160
189k
  else if (klass->array_start != NULL)
161
0
    klass->array_start (parser);
162
189k
}
163
164
static inline void
165
json_parser_emit_array_element (JsonParser *parser,
166
                                JsonArray  *array,
167
                                guint       idx)
168
386k
{
169
386k
  JsonParserClass *klass = JSON_PARSER_GET_CLASS (parser);
170
171
386k
  if (g_signal_has_handler_pending (parser, parser_signals[ARRAY_ELEMENT], 0, FALSE))
172
0
    g_signal_emit (parser, parser_signals[ARRAY_ELEMENT], 0, array, idx);
173
386k
  else if (klass->array_element != NULL)
174
0
    klass->array_element (parser, array, idx);
175
386k
}
176
177
static inline void
178
json_parser_emit_array_end (JsonParser *parser,
179
                            JsonArray  *array)
180
179k
{
181
179k
  JsonParserClass *klass = JSON_PARSER_GET_CLASS (parser);
182
183
179k
  if (g_signal_has_handler_pending (parser, parser_signals[ARRAY_END], 0, FALSE))
184
0
    g_signal_emit (parser, parser_signals[ARRAY_END], 0, array);
185
179k
  else if (klass->array_end != NULL)
186
0
    klass->array_end (parser, array);
187
179k
}
188
189
static inline void
190
json_parser_emit_object_start (JsonParser *parser)
191
1.63M
{
192
1.63M
  JsonParserClass *klass = JSON_PARSER_GET_CLASS (parser);
193
194
1.63M
  if (g_signal_has_handler_pending (parser, parser_signals[OBJECT_START], 0, FALSE))
195
0
    g_signal_emit (parser, parser_signals[OBJECT_START], 0);
196
1.63M
  else if (klass->object_start != NULL)
197
0
    klass->object_start (parser);
198
1.63M
}
199
200
static inline void
201
json_parser_emit_object_member (JsonParser *parser,
202
                                JsonObject *object,
203
                                const char *name)
204
1.83M
{
205
1.83M
  JsonParserClass *klass = JSON_PARSER_GET_CLASS (parser);
206
207
1.83M
  if (g_signal_has_handler_pending (parser, parser_signals[OBJECT_MEMBER], 0, FALSE))
208
0
    g_signal_emit (parser, parser_signals[OBJECT_MEMBER], 0, object, name);
209
1.83M
  else if (klass->object_member != NULL)
210
0
    klass->object_member (parser, object, name);
211
1.83M
}
212
213
static inline void
214
json_parser_emit_object_end (JsonParser *parser,
215
                             JsonObject *object)
216
1.62M
{
217
1.62M
  JsonParserClass *klass = JSON_PARSER_GET_CLASS (parser);
218
219
1.62M
  if (g_signal_has_handler_pending (parser, parser_signals[OBJECT_END], 0, FALSE))
220
0
    g_signal_emit (parser, parser_signals[OBJECT_END], 0, object);
221
1.62M
  else if (klass->object_end != NULL)
222
0
    klass->object_end (parser, object);
223
1.62M
}
224
225
static inline void
226
json_parser_emit_error (JsonParser *parser,
227
                        GError     *error)
228
1.52k
{
229
1.52k
  JsonParserClass *klass = JSON_PARSER_GET_CLASS (parser);
230
231
1.52k
  if (g_signal_has_handler_pending (parser, parser_signals[ERROR], 0, FALSE))
232
0
    g_signal_emit (parser, parser_signals[ERROR], 0, error);
233
1.52k
  else if (klass->error != NULL)
234
0
    klass->error (parser, error);
235
1.52k
}
236
237
static inline void
238
json_parser_emit_parse_start (JsonParser *parser)
239
16.3k
{
240
16.3k
  JsonParserClass *klass = JSON_PARSER_GET_CLASS (parser);
241
242
16.3k
  if (g_signal_has_handler_pending (parser, parser_signals[PARSE_START], 0, FALSE))
243
0
    g_signal_emit (parser, parser_signals[PARSE_START], 0);
244
16.3k
  else if (klass->parse_start != NULL)
245
0
    klass->parse_start (parser);
246
16.3k
}
247
248
static inline void
249
json_parser_emit_parse_end (JsonParser *parser)
250
16.3k
{
251
16.3k
  JsonParserClass *klass = JSON_PARSER_GET_CLASS (parser);
252
253
16.3k
  if (g_signal_has_handler_pending (parser, parser_signals[PARSE_END], 0, FALSE))
254
0
    g_signal_emit (parser, parser_signals[PARSE_END], 0);
255
16.3k
  else if (klass->parse_end != NULL)
256
0
    klass->parse_end (parser);
257
16.3k
}
258
259
static void
260
json_parser_dispose (GObject *gobject)
261
16.3k
{
262
16.3k
  json_parser_clear (JSON_PARSER (gobject));
263
264
16.3k
  G_OBJECT_CLASS (json_parser_parent_class)->dispose (gobject);
265
16.3k
}
266
267
static void
268
json_parser_finalize (GObject *gobject)
269
16.3k
{
270
16.3k
  JsonParserPrivate *priv = JSON_PARSER (gobject)->priv;
271
272
16.3k
  g_free (priv->variable_name);
273
16.3k
  g_free (priv->filename);
274
275
16.3k
  G_OBJECT_CLASS (json_parser_parent_class)->finalize (gobject);
276
16.3k
}
277
278
static void
279
json_parser_set_property (GObject      *gobject,
280
                          guint         prop_id,
281
                          const GValue *value,
282
                          GParamSpec   *pspec)
283
16.3k
{
284
16.3k
  JsonParserPrivate *priv = JSON_PARSER (gobject)->priv;
285
286
16.3k
  switch (prop_id)
287
16.3k
    {
288
16.3k
    case PROP_IMMUTABLE:
289
      /* Construct-only. */
290
16.3k
      priv->is_immutable = g_value_get_boolean (value);
291
16.3k
      break;
292
293
0
    case PROP_STRICT:
294
0
      json_parser_set_strict (JSON_PARSER (gobject),
295
0
                              g_value_get_boolean (value));
296
0
      break;
297
298
0
    default:
299
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
300
0
      break;
301
16.3k
    }
302
16.3k
}
303
304
static void
305
json_parser_get_property (GObject    *gobject,
306
                          guint       prop_id,
307
                          GValue     *value,
308
                          GParamSpec *pspec)
309
0
{
310
0
  JsonParserPrivate *priv = JSON_PARSER (gobject)->priv;
311
312
0
  switch (prop_id)
313
0
    {
314
0
    case PROP_IMMUTABLE:
315
0
      g_value_set_boolean (value, priv->is_immutable);
316
0
      break;
317
318
0
    case PROP_STRICT:
319
0
      g_value_set_boolean (value, priv->is_strict);
320
0
      break;
321
322
0
    default:
323
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
324
0
      break;
325
0
    }
326
0
}
327
328
static void
329
json_parser_class_init (JsonParserClass *klass)
330
1
{
331
1
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
332
333
1
  gobject_class->set_property = json_parser_set_property;
334
1
  gobject_class->get_property = json_parser_get_property;
335
1
  gobject_class->dispose = json_parser_dispose;
336
1
  gobject_class->finalize = json_parser_finalize;
337
338
  /**
339
   * JsonParser:immutable:
340
   *
341
   * Whether the tree built by the parser should be immutable
342
   * when created.
343
   *
344
   * Making the output immutable on creation avoids the expense
345
   * of traversing it to make it immutable later.
346
   *
347
   * Since: 1.2
348
   */
349
1
  parser_props[PROP_IMMUTABLE] =
350
1
    g_param_spec_boolean ("immutable", NULL, NULL,
351
1
                          FALSE,
352
1
                          G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
353
354
  /**
355
   * JsonParser:strict:
356
   *
357
   * Whether the parser should be strictly conforming to the
358
   * JSON format, or allow custom extensions like comments.
359
   *
360
   * Since: 1.10
361
   */
362
1
  parser_props[PROP_STRICT] =
363
1
    g_param_spec_boolean ("strict", NULL, NULL, FALSE,
364
1
                          G_PARAM_READWRITE |
365
1
                          G_PARAM_EXPLICIT_NOTIFY);
366
367
1
  g_object_class_install_properties (gobject_class, PROP_LAST, parser_props);
368
369
  /**
370
   * JsonParser::parse-start:
371
   * @parser: the parser that emitted the signal
372
   * 
373
   * This signal is emitted when a parser starts parsing a JSON data stream.
374
   *
375
   * Deprecated: 1.10: Derive your own parser type from `JsonParser` and
376
   *   override the [vfunc@Json.Parser.parse_start] virtual function
377
   */
378
1
  parser_signals[PARSE_START] =
379
1
    g_signal_new ("parse-start",
380
1
                  G_OBJECT_CLASS_TYPE (gobject_class),
381
1
                  G_SIGNAL_RUN_LAST,
382
1
                  G_STRUCT_OFFSET (JsonParserClass, parse_start),
383
1
                  NULL, NULL,
384
1
                  NULL,
385
1
                  G_TYPE_NONE, 0);
386
  /**
387
   * JsonParser::parse-end:
388
   * @parser: the parser that emitted the signal
389
   *
390
   * This signal is emitted when a parser successfully finished parsing a
391
   * JSON data stream.
392
   *
393
   * Deprecated: 1.10: Derive your own parser type from `JsonParser` and
394
   *   override the [vfunc@Json.Parser.parse_end] virtual function
395
   */
396
1
  parser_signals[PARSE_END] =
397
1
    g_signal_new ("parse-end",
398
1
                  G_OBJECT_CLASS_TYPE (gobject_class),
399
1
                  G_SIGNAL_RUN_LAST,
400
1
                  G_STRUCT_OFFSET (JsonParserClass, parse_end),
401
1
                  NULL, NULL, NULL,
402
1
                  G_TYPE_NONE, 0);
403
  /**
404
   * JsonParser::object-start:
405
   * @parser: the parser that emitted the signal
406
   *
407
   * This signal is emitted each time a parser starts parsing a JSON object.
408
   *
409
   * Deprecated: 1.10: Derive your own parser type from `JsonParser` and
410
   *   override the [vfunc@Json.Parser.object_start] virtual function
411
   */
412
1
  parser_signals[OBJECT_START] =
413
1
    g_signal_new ("object-start",
414
1
                  G_OBJECT_CLASS_TYPE (gobject_class),
415
1
                  G_SIGNAL_RUN_LAST,
416
1
                  G_STRUCT_OFFSET (JsonParserClass, object_start),
417
1
                  NULL, NULL, NULL,
418
1
                  G_TYPE_NONE, 0);
419
  /**
420
   * JsonParser::object-member:
421
   * @parser: the parser that emitted the signal
422
   * @object: the JSON object being parsed
423
   * @member_name: the name of the newly parsed member
424
   *
425
   * The `::object-member` signal is emitted each time a parser
426
   * has successfully parsed a single member of a JSON object.
427
   *
428
   * Deprecated: 1.10: Derive your own parser type from `JsonParser` and
429
   *   override the [vfunc@Json.Parser.object_member] virtual function
430
   */
431
1
  parser_signals[OBJECT_MEMBER] =
432
1
    g_signal_new ("object-member",
433
1
                  G_OBJECT_CLASS_TYPE (gobject_class),
434
1
                  G_SIGNAL_RUN_LAST,
435
1
                  G_STRUCT_OFFSET (JsonParserClass, object_member),
436
1
                  NULL, NULL, NULL,
437
1
                  G_TYPE_NONE, 2,
438
1
                  JSON_TYPE_OBJECT,
439
1
                  G_TYPE_STRING);
440
  /**
441
   * JsonParser::object-end:
442
   * @parser: the parser that emitted the signal
443
   * @object: the parsed JSON object
444
   *
445
   * The `::object-end` signal is emitted each time a parser
446
   * has successfully parsed an entire JSON object.
447
   *
448
   * Deprecated: 1.10: Derive your own parser type from `JsonParser` and
449
   *   override the [vfunc@Json.Parser.object_end] virtual function
450
   */
451
1
  parser_signals[OBJECT_END] =
452
1
    g_signal_new ("object-end",
453
1
                  G_OBJECT_CLASS_TYPE (gobject_class),
454
1
                  G_SIGNAL_RUN_LAST,
455
1
                  G_STRUCT_OFFSET (JsonParserClass, object_end),
456
1
                  NULL, NULL, NULL,
457
1
                  G_TYPE_NONE, 1,
458
1
                  JSON_TYPE_OBJECT);
459
  /**
460
   * JsonParser::array-start:
461
   * @parser: the parser that emitted the signal
462
   *
463
   * The `::array-start` signal is emitted each time a parser
464
   * starts parsing a JSON array.
465
   *
466
   * Deprecated: 1.10: Derive your own parser type from `JsonParser` and
467
   *   override the [vfunc@Json.Parser.array_start] virtual function
468
   */
469
1
  parser_signals[ARRAY_START] =
470
1
    g_signal_new ("array-start",
471
1
                  G_OBJECT_CLASS_TYPE (gobject_class),
472
1
                  G_SIGNAL_RUN_LAST,
473
1
                  G_STRUCT_OFFSET (JsonParserClass, array_start),
474
1
                  NULL, NULL, NULL,
475
1
                  G_TYPE_NONE, 0);
476
  /**
477
   * JsonParser::array-element:
478
   * @parser: the parser that emitted the signal
479
   * @array: a JSON array
480
   * @index_: the index of the newly parsed array element
481
   *
482
   * The `::array-element` signal is emitted each time a parser
483
   * has successfully parsed a single element of a JSON array.
484
   *
485
   * Deprecated: 1.10: Derive your own parser type from `JsonParser` and
486
   *   override the [vfunc@Json.Parser.array_element] virtual function
487
   */
488
1
  parser_signals[ARRAY_ELEMENT] =
489
1
    g_signal_new ("array-element",
490
1
                  G_OBJECT_CLASS_TYPE (gobject_class),
491
1
                  G_SIGNAL_RUN_LAST,
492
1
                  G_STRUCT_OFFSET (JsonParserClass, array_element),
493
1
                  NULL, NULL, NULL,
494
1
                  G_TYPE_NONE, 2,
495
1
                  JSON_TYPE_ARRAY,
496
1
                  G_TYPE_INT);
497
  /**
498
   * JsonParser::array-end:
499
   * @parser: the parser that emitted the signal
500
   * @array: the parsed JSON array
501
   *
502
   * The `::array-end` signal is emitted each time a parser
503
   * has successfully parsed an entire JSON array.
504
   *
505
   * Deprecated: 1.10: Derive your own parser type from `JsonParser` and
506
   *   override the [vfunc@Json.Parser.array_end] virtual function
507
   */
508
1
  parser_signals[ARRAY_END] =
509
1
    g_signal_new ("array-end",
510
1
                  G_OBJECT_CLASS_TYPE (gobject_class),
511
1
                  G_SIGNAL_RUN_LAST,
512
1
                  G_STRUCT_OFFSET (JsonParserClass, array_end),
513
1
                  NULL, NULL, NULL,
514
1
                  G_TYPE_NONE, 1,
515
1
                  JSON_TYPE_ARRAY);
516
  /**
517
   * JsonParser::error:
518
   * @parser: the parser that emitted the signal
519
   * @error: the error
520
   *
521
   * The `::error` signal is emitted each time a parser encounters
522
   * an error in a JSON stream.
523
   *
524
   * Deprecated: 1.10: Derive your own parser type from `JsonParser` and
525
   *   override the [vfunc@Json.Parser.error] virtual function
526
   */
527
1
  parser_signals[ERROR] =
528
1
    g_signal_new ("error",
529
1
                  G_OBJECT_CLASS_TYPE (gobject_class),
530
1
                  G_SIGNAL_RUN_LAST,
531
1
                  G_STRUCT_OFFSET (JsonParserClass, error),
532
1
                  NULL, NULL, NULL,
533
1
                  G_TYPE_NONE, 1,
534
1
                  G_TYPE_POINTER);
535
1
}
536
537
static void
538
json_parser_init (JsonParser *parser)
539
16.3k
{
540
16.3k
  JsonParserPrivate *priv = json_parser_get_instance_private (parser);
541
542
16.3k
  parser->priv = priv;
543
544
16.3k
  priv->root = NULL;
545
16.3k
  priv->current_node = NULL;
546
547
16.3k
  priv->error_code = JSON_PARSER_ERROR_PARSE;
548
16.3k
  priv->last_error = NULL;
549
550
16.3k
  priv->has_assignment = FALSE;
551
16.3k
  priv->variable_name = NULL;
552
553
16.3k
  priv->is_filename = FALSE;
554
16.3k
  priv->filename = FALSE;
555
16.3k
}
556
557
static guint
558
json_parse_value (JsonParser   *parser,
559
                  JsonScanner  *scanner,
560
                  guint         token,
561
                  JsonNode    **node)
562
854k
{
563
854k
  JsonParserPrivate *priv = parser->priv;
564
854k
  JsonNode *current_node = priv->current_node;
565
566
854k
  switch (token)
567
854k
    {
568
210k
    case JSON_TOKEN_INT:
569
210k
      {
570
210k
        gint64 value = json_scanner_get_int64_value (scanner);
571
572
210k
        JSON_NOTE (PARSER, "node: %" G_GINT64_FORMAT, value);
573
210k
        *node = json_node_init_int (json_node_alloc (), value);
574
210k
      }
575
210k
      break;
576
577
941
    case JSON_TOKEN_FLOAT:
578
941
      {
579
941
        double value = json_scanner_get_float_value (scanner);
580
581
941
        JSON_NOTE (PARSER, "abs(node): %.6f", value);
582
941
        *node = json_node_init_double (json_node_alloc (), value);
583
941
      }
584
941
      break;
585
586
641k
    case JSON_TOKEN_STRING:
587
641k
      {
588
641k
        const char *value = json_scanner_get_string_value (scanner);
589
590
641k
        JSON_NOTE (PARSER, "node: '%s'", value);
591
641k
        *node = json_node_init_string (json_node_alloc (), value);
592
641k
      }
593
641k
      break;
594
595
213
    case JSON_TOKEN_TRUE:
596
408
    case JSON_TOKEN_FALSE:
597
408
      JSON_NOTE (PARSER, "node: '%s'",
598
408
                 JSON_TOKEN_TRUE ? "<true>" : "<false>");
599
408
      *node = json_node_init_boolean (json_node_alloc (), token == JSON_TOKEN_TRUE ? TRUE : FALSE);
600
408
      break;
601
602
396
    case JSON_TOKEN_NULL:
603
396
      JSON_NOTE (PARSER, "node: <null>");
604
396
      *node = json_node_init_null (json_node_alloc ());
605
396
      break;
606
607
480
    case JSON_TOKEN_IDENTIFIER:
608
480
      JSON_NOTE (PARSER, "node: identifier '%s'", json_scanner_get_identifier (scanner));
609
480
      priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
610
480
      *node = NULL;
611
480
      return JSON_TOKEN_SYMBOL;
612
613
1.17k
    default:
614
1.17k
      {
615
1.17k
        JsonNodeType cur_type;
616
617
1.17k
        *node = NULL;
618
619
1.17k
        JSON_NOTE (PARSER, "node: invalid token");
620
621
1.17k
        cur_type = json_node_get_node_type (current_node);
622
1.17k
        if (cur_type == JSON_NODE_ARRAY)
623
108
          {
624
108
            priv->error_code = JSON_PARSER_ERROR_PARSE;
625
108
            return JSON_TOKEN_RIGHT_BRACE;
626
108
          }
627
1.06k
        else if (cur_type == JSON_NODE_OBJECT)
628
1.06k
          {
629
1.06k
            priv->error_code = JSON_PARSER_ERROR_PARSE;
630
1.06k
            return JSON_TOKEN_RIGHT_CURLY;
631
1.06k
          }
632
0
        else
633
0
          {
634
0
            priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
635
0
            return JSON_TOKEN_SYMBOL;
636
0
          }
637
1.17k
      }
638
0
      break;
639
854k
    }
640
641
853k
  if (priv->is_immutable && *node != NULL)
642
0
    json_node_seal (*node);
643
644
853k
  return JSON_TOKEN_NONE;
645
854k
}
646
647
static guint
648
json_parse_array (JsonParser    *parser,
649
                  JsonScanner   *scanner,
650
                  JsonNode     **node,
651
                  unsigned int   nesting_level)
652
189k
{
653
189k
  JsonParserPrivate *priv = parser->priv;
654
189k
  JsonNode *old_current;
655
189k
  JsonArray *array;
656
189k
  guint token;
657
189k
  gint idx;
658
659
189k
  if (nesting_level >= JSON_PARSER_MAX_RECURSION_DEPTH)
660
1
    {
661
1
      priv->error_code = JSON_PARSER_ERROR_NESTING;
662
1
      return JSON_TOKEN_RIGHT_BRACE;
663
1
    }
664
665
189k
  old_current = priv->current_node;
666
189k
  priv->current_node = json_node_init_array (json_node_alloc (), NULL);
667
668
189k
  array = json_array_new ();
669
670
189k
  token = json_scanner_get_next_token (scanner);
671
189k
  g_assert (token == JSON_TOKEN_LEFT_BRACE);
672
673
189k
  json_parser_emit_array_start (parser);
674
675
189k
  idx = 0;
676
575k
  while (token != JSON_TOKEN_RIGHT_BRACE)
677
398k
    {
678
398k
      guint next_token = json_scanner_peek_next_token (scanner);
679
398k
      JsonNode *element = NULL;
680
681
      /* parse the element */
682
398k
      switch (next_token)
683
398k
        {
684
9.17k
        case JSON_TOKEN_LEFT_BRACE:
685
9.17k
          JSON_NOTE (PARSER, "Nested array at index %d", idx);
686
9.17k
          token = json_parse_array (parser, scanner, &element, nesting_level + 1);
687
9.17k
          break;
688
689
178k
        case JSON_TOKEN_LEFT_CURLY:
690
178k
          JSON_NOTE (PARSER, "Nested object at index %d", idx);
691
178k
          token = json_parse_object (parser, scanner, &element, nesting_level + 1);
692
178k
          break;
693
694
2.53k
        case JSON_TOKEN_RIGHT_BRACE:
695
2.53k
          goto array_done;
696
697
208k
        default:
698
208k
          token = json_scanner_get_next_token (scanner);
699
208k
          token = json_parse_value (parser, scanner, token, &element);
700
208k
          break;
701
398k
        }
702
703
396k
      if (token != JSON_TOKEN_NONE || element == NULL)
704
9.72k
        {
705
          /* the json_parse_* functions will have set the error code */
706
9.72k
          json_array_unref (array);
707
9.72k
          json_node_unref (priv->current_node);
708
9.72k
          priv->current_node = old_current;
709
710
9.72k
          return token;
711
9.72k
        }
712
713
386k
      next_token = json_scanner_peek_next_token (scanner);
714
715
      /* look for missing commas */
716
386k
      if (next_token != JSON_TOKEN_COMMA && next_token != JSON_TOKEN_RIGHT_BRACE)
717
133
        {
718
133
          priv->error_code = JSON_PARSER_ERROR_MISSING_COMMA;
719
720
133
          json_array_unref (array);
721
133
          json_node_free (priv->current_node);
722
133
          json_node_free (element);
723
133
          priv->current_node = old_current;
724
725
133
          return JSON_TOKEN_COMMA;
726
133
        }
727
728
      /* look for trailing commas */
729
386k
      if (next_token == JSON_TOKEN_COMMA)
730
209k
        {
731
          /* advance the cursor */
732
209k
          json_scanner_get_next_token (scanner);
733
734
209k
          next_token = json_scanner_peek_next_token (scanner);
735
209k
          if (next_token == JSON_TOKEN_RIGHT_BRACE)
736
1
            {
737
1
              priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
738
739
1
              json_array_unref (array);
740
1
              json_node_unref (priv->current_node);
741
1
              json_node_unref (element);
742
1
              priv->current_node = old_current;
743
744
1
              return JSON_TOKEN_RIGHT_BRACE;
745
1
            }
746
209k
        }
747
748
386k
      JSON_NOTE (PARSER, "Array element %d completed", idx);
749
386k
      json_node_set_parent (element, priv->current_node);
750
386k
      if (priv->is_immutable)
751
0
        json_node_seal (element);
752
386k
      json_array_add_element (array, element);
753
754
386k
      json_parser_emit_array_element (parser, array, idx);
755
756
386k
      idx += 1;
757
386k
      token = next_token;
758
386k
    }
759
760
179k
array_done:
761
179k
  json_scanner_get_next_token (scanner);
762
763
179k
  if (priv->is_immutable)
764
0
    json_array_seal (array);
765
766
179k
  json_node_take_array (priv->current_node, array);
767
179k
  if (priv->is_immutable)
768
0
    json_node_seal (priv->current_node);
769
179k
  json_node_set_parent (priv->current_node, old_current);
770
771
179k
  json_parser_emit_array_end (parser, array);
772
773
179k
  if (node != NULL && *node == NULL)
774
179k
    *node = priv->current_node;
775
776
179k
  priv->current_node = old_current;
777
778
179k
  return JSON_TOKEN_NONE;
779
189k
}
780
781
static guint
782
json_parse_object (JsonParser    *parser,
783
                   JsonScanner   *scanner,
784
                   JsonNode     **node,
785
                   unsigned int   nesting)
786
1.63M
{
787
1.63M
  JsonParserPrivate *priv = parser->priv;
788
1.63M
  JsonObject *object;
789
1.63M
  JsonNode *old_current;
790
1.63M
  guint token;
791
792
1.63M
  if (nesting >= JSON_PARSER_MAX_RECURSION_DEPTH)
793
2
    {
794
2
      priv->error_code = JSON_PARSER_ERROR_NESTING;
795
2
      return JSON_TOKEN_RIGHT_CURLY;
796
2
    }
797
798
1.63M
  old_current = priv->current_node;
799
1.63M
  priv->current_node = json_node_init_object (json_node_alloc (), NULL);
800
801
1.63M
  object = json_object_new ();
802
803
1.63M
  token = json_scanner_get_next_token (scanner);
804
1.63M
  g_assert (token == JSON_TOKEN_LEFT_CURLY);
805
806
1.63M
  json_parser_emit_object_start (parser);
807
808
3.46M
  while (token != JSON_TOKEN_RIGHT_CURLY)
809
1.91M
    {
810
1.91M
      guint next_token = json_scanner_peek_next_token (scanner);
811
1.91M
      JsonNode *member = NULL;
812
1.91M
      gchar *name;
813
814
      /* we need to abort here because empty objects do not
815
       * have member names
816
       */
817
1.91M
      if (next_token == JSON_TOKEN_RIGHT_CURLY)
818
72.2k
        break;
819
820
      /* parse the member's name */
821
1.83M
      if (next_token != JSON_TOKEN_STRING)
822
323
        {
823
323
          JSON_NOTE (PARSER, "Missing object member name");
824
825
323
          priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
826
827
323
          json_object_unref (object);
828
323
          json_node_unref (priv->current_node);
829
323
          priv->current_node = old_current;
830
831
323
          return JSON_TOKEN_STRING;
832
323
        }
833
834
      /* member name */
835
1.83M
      json_scanner_get_next_token (scanner);
836
837
1.83M
      name = json_scanner_dup_string_value (scanner);
838
1.83M
      if (name == NULL)
839
0
        {
840
0
          JSON_NOTE (PARSER, "Empty object member name");
841
842
0
          priv->error_code = JSON_PARSER_ERROR_EMPTY_MEMBER_NAME;
843
844
0
          json_object_unref (object);
845
0
          json_node_unref (priv->current_node);
846
0
          priv->current_node = old_current;
847
848
0
          return JSON_TOKEN_STRING;
849
0
        }
850
851
1.83M
      JSON_NOTE (PARSER, "Object member '%s'", name);
852
853
      /* a colon separates names from values */
854
1.83M
      next_token = json_scanner_peek_next_token (scanner);
855
1.83M
      if (next_token != JSON_TOKEN_COLON)
856
390
        {
857
390
          JSON_NOTE (PARSER, "Missing object member name separator");
858
859
390
          priv->error_code = JSON_PARSER_ERROR_MISSING_COLON;
860
861
390
          g_free (name);
862
390
          json_object_unref (object);
863
390
          json_node_unref (priv->current_node);
864
390
          priv->current_node = old_current;
865
866
390
          return JSON_TOKEN_COLON;
867
390
        }
868
869
      /* we swallow the ':' */
870
1.83M
      token = json_scanner_get_next_token (scanner);
871
1.83M
      g_assert (token == JSON_TOKEN_COLON);
872
1.83M
      next_token = json_scanner_peek_next_token (scanner);
873
874
      /* parse the member's value */
875
1.83M
      switch (next_token)
876
1.83M
        {
877
178k
        case JSON_TOKEN_LEFT_BRACE:
878
178k
          JSON_NOTE (PARSER, "Nested array at member %s", name);
879
178k
          token = json_parse_array (parser, scanner, &member, nesting + 1);
880
178k
          break;
881
882
1.01M
        case JSON_TOKEN_LEFT_CURLY:
883
1.01M
          JSON_NOTE (PARSER, "Nested object at member %s", name);
884
1.01M
          token = json_parse_object (parser, scanner, &member, nesting + 1);
885
1.01M
          break;
886
887
645k
        default:
888
          /* once a member name is defined we need a value */
889
645k
          token = json_scanner_get_next_token (scanner);
890
645k
          token = json_parse_value (parser, scanner, token, &member);
891
645k
          break;
892
1.83M
        }
893
894
1.83M
      if (token != JSON_TOKEN_NONE || member == NULL)
895
5.27k
        {
896
          /* the json_parse_* functions will have set the error code */
897
5.27k
          g_free (name);
898
5.27k
          json_object_unref (object);
899
5.27k
          json_node_unref (priv->current_node);
900
5.27k
          priv->current_node = old_current;
901
902
5.27k
          return token;
903
5.27k
        }
904
905
1.83M
      next_token = json_scanner_peek_next_token (scanner);
906
1.83M
      if (next_token == JSON_TOKEN_COMMA)
907
276k
        {
908
276k
          json_scanner_get_next_token (scanner);
909
910
          /* look for trailing commas */
911
276k
          next_token = json_scanner_peek_next_token (scanner);
912
276k
          if (next_token == JSON_TOKEN_RIGHT_CURLY)
913
1
            {
914
1
              priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
915
916
1
              g_free (name);
917
1
              json_object_unref (object);
918
1
              json_node_unref (member);
919
1
              json_node_unref (priv->current_node);
920
1
              priv->current_node = old_current;
921
922
1
              return JSON_TOKEN_RIGHT_BRACE;
923
1
            }
924
276k
        }
925
1.55M
      else if (next_token == JSON_TOKEN_STRING)
926
3
        {
927
3
          priv->error_code = JSON_PARSER_ERROR_MISSING_COMMA;
928
929
3
          g_free (name);
930
3
          json_object_unref (object);
931
3
          json_node_unref (member);
932
3
          json_node_unref (priv->current_node);
933
3
          priv->current_node = old_current;
934
935
3
          return JSON_TOKEN_COMMA;
936
3
        }
937
938
1.83M
      JSON_NOTE (PARSER, "Object member '%s' completed", name);
939
1.83M
      json_node_set_parent (member, priv->current_node);
940
1.83M
      if (priv->is_immutable)
941
0
        json_node_seal (member);
942
1.83M
      json_object_set_member (object, name, member);
943
944
1.83M
      json_parser_emit_object_member (parser, object, name);
945
946
1.83M
      g_free (name);
947
948
1.83M
      token = next_token;
949
1.83M
    }
950
951
1.62M
  json_scanner_get_next_token (scanner);
952
953
1.62M
  if (priv->is_immutable)
954
0
    json_object_seal (object);
955
956
1.62M
  json_node_take_object (priv->current_node, object);
957
1.62M
  if (priv->is_immutable)
958
0
    json_node_seal (priv->current_node);
959
1.62M
  json_node_set_parent (priv->current_node, old_current);
960
961
1.62M
  json_parser_emit_object_end (parser, object);
962
963
1.62M
  if (node != NULL && *node == NULL)
964
1.62M
    *node = priv->current_node;
965
966
1.62M
  priv->current_node = old_current;
967
968
1.62M
  return JSON_TOKEN_NONE;
969
1.63M
}
970
971
static guint
972
json_parse_statement (JsonParser  *parser,
973
                      JsonScanner *scanner)
974
451k
{
975
451k
  JsonParserPrivate *priv = parser->priv;
976
451k
  guint token;
977
978
451k
  token = json_scanner_peek_next_token (scanner);
979
451k
  switch (token)
980
451k
    {
981
442k
    case JSON_TOKEN_LEFT_CURLY:
982
442k
      if (priv->is_strict && priv->root != NULL)
983
0
        {
984
0
          JSON_NOTE (PARSER, "Only one top level object is possible");
985
0
          json_scanner_get_next_token (scanner);
986
0
          priv->error_code = JSON_PARSER_ERROR_INVALID_STRUCTURE;
987
0
          return JSON_TOKEN_EOF;
988
0
        }
989
442k
      else if (priv->root != NULL)
990
426k
        {
991
426k
          JsonArray *array;
992
993
426k
          if (!priv->multi_root)
994
3.85k
            {
995
3.85k
              JSON_NOTE (PARSER, "Replacing new root with an array");
996
997
3.85k
              JsonNode *old_root = g_steal_pointer (&priv->root);
998
3.85k
              priv->root = json_node_new (JSON_NODE_ARRAY);
999
1000
3.85k
              array = json_array_new ();
1001
3.85k
              json_array_add_element (array, old_root);
1002
3.85k
              json_node_set_parent (old_root, priv->root);
1003
1004
3.85k
              json_node_take_array (priv->root, array);
1005
1006
3.85k
              priv->multi_root = true;
1007
3.85k
            }
1008
422k
          else
1009
422k
            {
1010
422k
              g_assert (JSON_NODE_HOLDS_ARRAY (priv->root));
1011
422k
              array = json_node_get_array (priv->root);
1012
422k
            }
1013
1014
426k
          JsonNode *node = NULL;
1015
426k
          guint res;
1016
1017
426k
          res = json_parse_object (parser, scanner, &node, 0);
1018
426k
          if (node != NULL)
1019
425k
            json_array_add_element (array, node);
1020
426k
          return res;
1021
426k
        }
1022
15.8k
      else
1023
15.8k
        {
1024
15.8k
          JSON_NOTE (PARSER, "Statement is object declaration");
1025
15.8k
          return json_parse_object (parser, scanner, &priv->root, 0);
1026
15.8k
        }
1027
0
      break;
1028
1029
1.42k
    case JSON_TOKEN_LEFT_BRACE:
1030
1.42k
      if (priv->is_strict && priv->root != NULL)
1031
0
        {
1032
0
          JSON_NOTE (PARSER, "Only one top level array is possible");
1033
0
          json_scanner_get_next_token (scanner);
1034
0
          priv->error_code = JSON_PARSER_ERROR_INVALID_STRUCTURE;
1035
0
          return JSON_TOKEN_EOF;
1036
0
        }
1037
1.42k
      else if (priv->root != NULL)
1038
949
        {
1039
949
          JsonArray *array;
1040
1041
949
          if (!priv->multi_root)
1042
139
            {
1043
139
              JSON_NOTE (PARSER, "Replacing new root with an array");
1044
1045
139
              JsonNode *old_root = g_steal_pointer (&priv->root);
1046
139
              priv->root = json_node_new (JSON_NODE_ARRAY);
1047
1048
139
              array = json_array_new ();
1049
139
              json_array_add_element (array, old_root);
1050
139
              json_node_set_parent (old_root, priv->root);
1051
1052
139
              json_node_take_array (priv->root, array);
1053
1054
139
              priv->multi_root = true;
1055
139
            }
1056
810
          else
1057
810
            {
1058
810
              g_assert (JSON_NODE_HOLDS_ARRAY (priv->root));
1059
810
              array = json_node_get_array (priv->root);
1060
810
            }
1061
1062
949
          JsonNode *node = NULL;
1063
949
          guint res;
1064
1065
949
          res = json_parse_array (parser, scanner, &node, 0);
1066
949
          if (node != NULL)
1067
846
            json_array_add_element (array, node);
1068
949
          return res;
1069
949
        }
1070
473
      else
1071
473
        {
1072
473
          JSON_NOTE (PARSER, "Statement is array declaration");
1073
473
          return json_parse_array (parser, scanner, &priv->root, 0);
1074
473
        }
1075
0
      break;
1076
1077
    /* some web APIs are not only passing the data structures: they are
1078
     * also passing an assigment, which makes parsing horribly complicated
1079
     * only because web developers are lazy, and writing "var foo = " is
1080
     * evidently too much to request from them.
1081
     */
1082
6.04k
    case JSON_TOKEN_VAR:
1083
6.04k
      {
1084
6.04k
        guint next_token;
1085
6.04k
        gchar *name;
1086
1087
6.04k
        JSON_NOTE (PARSER, "Statement is an assignment");
1088
1089
6.04k
        if (priv->is_strict)
1090
0
          {
1091
0
            json_scanner_get_next_token (scanner);
1092
0
            priv->error_code = JSON_PARSER_ERROR_INVALID_ASSIGNMENT;
1093
0
            return JSON_TOKEN_EOF;
1094
0
          }
1095
1096
        /* swallow the 'var' token... */
1097
6.04k
        json_scanner_get_next_token (scanner);
1098
1099
        /* ... swallow the variable name... */
1100
6.04k
        next_token = json_scanner_get_next_token (scanner);
1101
6.04k
        if (next_token != JSON_TOKEN_IDENTIFIER)
1102
527
          {
1103
527
            priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
1104
527
            return JSON_TOKEN_IDENTIFIER;
1105
527
          }
1106
1107
5.51k
        name = json_scanner_dup_identifier (scanner);
1108
1109
        /* ... and finally swallow the '=' */
1110
5.51k
        next_token = json_scanner_get_next_token (scanner);
1111
5.51k
        if (next_token != '=')
1112
667
          {
1113
667
            priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
1114
667
            g_free (name);
1115
667
            return '=';
1116
667
          }
1117
1118
4.85k
        if (priv->has_assignment)
1119
4.69k
          g_free (priv->variable_name);
1120
4.85k
        priv->has_assignment = TRUE;
1121
4.85k
        priv->variable_name = name;
1122
1123
4.85k
        token = json_parse_statement (parser, scanner);
1124
1125
        /* remove the trailing semi-colon */
1126
4.85k
        next_token = json_scanner_peek_next_token (scanner);
1127
4.85k
        if (next_token == ';')
1128
4.10k
          {
1129
4.10k
            json_scanner_get_next_token (scanner);
1130
4.10k
            return JSON_TOKEN_NONE;
1131
4.10k
          }
1132
1133
747
        return token;
1134
4.85k
      }
1135
0
      break;
1136
1137
10
    case JSON_TOKEN_NULL:
1138
18
    case JSON_TOKEN_TRUE:
1139
21
    case JSON_TOKEN_FALSE:
1140
21
    case '-':
1141
281
    case JSON_TOKEN_INT:
1142
304
    case JSON_TOKEN_FLOAT:
1143
362
    case JSON_TOKEN_STRING:
1144
1.04k
    case JSON_TOKEN_IDENTIFIER:
1145
1.04k
      if (priv->root != NULL)
1146
262
        {
1147
262
          JSON_NOTE (PARSER, "Only one top level statement is possible");
1148
262
          json_scanner_get_next_token (scanner);
1149
262
          priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
1150
262
          return JSON_TOKEN_EOF;
1151
262
        }
1152
1153
1.04k
      JSON_NOTE (PARSER, "Statement is a value");
1154
787
      token = json_scanner_get_next_token (scanner);
1155
787
      return json_parse_value (parser, scanner, token, &priv->root);
1156
1157
959
    default:
1158
959
      JSON_NOTE (PARSER, "Unknown statement");
1159
959
      json_scanner_get_next_token (scanner);
1160
959
      priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
1161
959
      return priv->root != NULL ? JSON_TOKEN_EOF : JSON_TOKEN_SYMBOL;
1162
451k
    }
1163
451k
}
1164
1165
static void
1166
json_scanner_msg_handler (JsonScanner *scanner,
1167
                          const char  *message,
1168
                          gpointer     user_data)
1169
1.44k
{
1170
1.44k
  JsonParser *parser = user_data;
1171
1.44k
  JsonParserPrivate *priv = parser->priv;
1172
1.44k
  GError *error = NULL;
1173
1174
1.44k
  g_set_error (&error, JSON_PARSER_ERROR,
1175
1.44k
               priv->error_code,
1176
               /* translators: %s: is the file name, the first %d is the line
1177
                * number, the second %d is the position on the line, and %s is
1178
                * the error message
1179
                */
1180
1.44k
               _("%s:%d:%d: Parse error: %s"),
1181
1.44k
               priv->is_filename ? priv->filename : "<data>",
1182
1.44k
               json_scanner_get_current_line (scanner),
1183
1.44k
               json_scanner_get_current_position (scanner),
1184
1.44k
               message);
1185
      
1186
1.44k
  parser->priv->last_error = error;
1187
1188
1.44k
  json_parser_emit_error (parser, error);
1189
1.44k
}
1190
1191
static JsonScanner *
1192
json_scanner_create (JsonParser *parser)
1193
16.3k
{
1194
16.3k
  JsonParserPrivate *priv = json_parser_get_instance_private (parser);
1195
16.3k
  JsonScanner *scanner;
1196
1197
16.3k
  scanner = json_scanner_new (priv->is_strict);
1198
16.3k
  json_scanner_set_msg_handler (scanner, json_scanner_msg_handler, parser);
1199
1200
16.3k
  return scanner;
1201
16.3k
}
1202
1203
/**
1204
 * json_parser_new:
1205
 * 
1206
 * Creates a new JSON parser.
1207
 *
1208
 * You can use the `JsonParser` to load a JSON stream from either a file or a
1209
 * buffer and then walk the hierarchy using the data types API.
1210
 *
1211
 * Returns: (transfer full): the newly created parser
1212
 */
1213
JsonParser *
1214
json_parser_new (void)
1215
16.3k
{
1216
16.3k
  return g_object_new (JSON_TYPE_PARSER, NULL);
1217
16.3k
}
1218
1219
/**
1220
 * json_parser_new_immutable:
1221
 *
1222
 * Creates a new parser instance with its [property@Json.Parser:immutable]
1223
 * property set to `TRUE` to create immutable output trees.
1224
 *
1225
 * Since: 1.2
1226
 * Returns: (transfer full): the newly created parser 
1227
 */
1228
JsonParser *
1229
json_parser_new_immutable (void)
1230
0
{
1231
0
  return g_object_new (JSON_TYPE_PARSER, "immutable", TRUE, NULL);
1232
0
}
1233
1234
static gboolean
1235
json_parser_load (JsonParser   *parser,
1236
                  const gchar  *input_data,
1237
                  gsize         length,
1238
                  GError      **error)
1239
16.3k
{
1240
16.3k
  JsonParserPrivate *priv = parser->priv;
1241
16.3k
  JsonScanner *scanner;
1242
16.3k
  gboolean done;
1243
16.3k
  gboolean retval = TRUE;
1244
16.3k
  const char *data = input_data;
1245
1246
16.3k
  if (priv->is_strict && (length == 0 || data == NULL || *data == '\0'))
1247
0
    {
1248
0
      g_set_error_literal (error, JSON_PARSER_ERROR,
1249
0
                           JSON_PARSER_ERROR_INVALID_DATA,
1250
0
                           "JSON data must not be empty");
1251
0
      json_parser_emit_error (parser, *error);
1252
0
      return FALSE;
1253
0
    }
1254
1255
16.3k
  json_parser_clear (parser);
1256
1257
16.3k
  if (!g_utf8_validate (data, length, NULL))
1258
78
    {
1259
78
      g_set_error_literal (error, JSON_PARSER_ERROR,
1260
78
                           JSON_PARSER_ERROR_INVALID_DATA,
1261
78
                           _("JSON data must be UTF-8 encoded"));
1262
78
      json_parser_emit_error (parser, *error);
1263
78
      return FALSE;
1264
78
    }
1265
1266
16.3k
  if (length >= 3)
1267
16.1k
    {
1268
      /* Check for UTF-8 signature and skip it if necessary */
1269
16.1k
       if (((data[0] & 0xFF) == 0xEF) &&
1270
16.1k
           ((data[1] & 0xFF) == 0xBB) &&
1271
16.1k
           ((data[2] & 0xFF) == 0xBF))
1272
1
         {
1273
1
           JSON_NOTE (PARSER, "Skipping BOM");
1274
1
           data += 3;
1275
1
           length -= 3;
1276
1
         }
1277
1278
16.1k
       if (priv->is_strict && length == 0)
1279
0
         {
1280
0
           g_set_error_literal (error, JSON_PARSER_ERROR,
1281
0
                                JSON_PARSER_ERROR_INVALID_DATA,
1282
0
                                "JSON data must not be empty after BOM character");
1283
0
           json_parser_emit_error (parser, *error);
1284
0
           return FALSE;
1285
0
         }
1286
16.1k
    }
1287
1288
  /* Skip leading space */
1289
16.3k
  if (priv->is_strict)
1290
0
    {
1291
0
      const char *p = data;
1292
0
      while (length > 0 && (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n'))
1293
0
        {
1294
0
          length -= 1;
1295
0
          data += 1;
1296
0
          p = data;
1297
0
        }
1298
1299
0
      if (length == 0)
1300
0
        {
1301
0
          g_set_error_literal (error, JSON_PARSER_ERROR,
1302
0
                               JSON_PARSER_ERROR_INVALID_DATA,
1303
0
                               "JSON data must not be empty after leading whitespace");
1304
0
          json_parser_emit_error (parser, *error);
1305
0
          return FALSE;
1306
0
        }
1307
0
    }
1308
1309
16.3k
  scanner = json_scanner_create (parser);
1310
16.3k
  json_scanner_input_text (scanner, data, length);
1311
1312
16.3k
  priv->scanner = scanner;
1313
1314
16.3k
  json_parser_emit_parse_start (parser);
1315
1316
16.3k
  done = FALSE;
1317
477k
  while (!done)
1318
461k
    {
1319
461k
      if (json_scanner_peek_next_token (scanner) == JSON_TOKEN_EOF)
1320
14.8k
        done = TRUE;
1321
446k
      else
1322
446k
        {
1323
446k
          unsigned int expected_token;
1324
1325
          /* we try to show the expected token, if possible */
1326
446k
          expected_token = json_parse_statement (parser, scanner);
1327
446k
          if (expected_token != JSON_TOKEN_NONE)
1328
1.44k
            {
1329
              /* this will emit the ::error signal via the custom
1330
               * message handler we install
1331
               */
1332
1.44k
              json_scanner_unknown_token (scanner, expected_token);
1333
1334
              /* and this will propagate the error we create in the
1335
               * same message handler
1336
               */
1337
1.44k
              if (priv->last_error)
1338
1.44k
                {
1339
1.44k
                  g_propagate_error (error, priv->last_error);
1340
1.44k
                  priv->last_error = NULL;
1341
1.44k
                }
1342
1343
1.44k
              retval = FALSE;
1344
1.44k
              done = TRUE;
1345
1.44k
            }
1346
446k
        }
1347
461k
    }
1348
1349
16.3k
  json_parser_emit_parse_end (parser);
1350
1351
  /* remove the scanner */
1352
16.3k
  json_scanner_destroy (scanner);
1353
16.3k
  priv->scanner = NULL;
1354
16.3k
  priv->current_node = NULL;
1355
1356
16.3k
  return retval;
1357
16.3k
}
1358
1359
/**
1360
 * json_parser_load_from_file:
1361
 * @parser: a parser
1362
 * @filename: (type filename): the path for the file to parse
1363
 * @error: return location for a #GError
1364
 *
1365
 * Loads a JSON stream from the content of `filename` and parses it.
1366
 *
1367
 * If the file is large or shared between processes,
1368
 * [method@Json.Parser.load_from_mapped_file] may be a more efficient
1369
 * way to load it.
1370
 *
1371
 * See also: [method@Json.Parser.load_from_data]
1372
 *
1373
 * Returns: `TRUE` if the file was successfully loaded and parsed.
1374
 */
1375
gboolean
1376
json_parser_load_from_file (JsonParser   *parser,
1377
                            const gchar  *filename,
1378
                            GError      **error)
1379
0
{
1380
0
  JsonParserPrivate *priv;
1381
0
  GError *internal_error;
1382
0
  gchar *data;
1383
0
  gsize length;
1384
0
  gboolean retval = TRUE;
1385
1386
0
  g_return_val_if_fail (JSON_IS_PARSER (parser), FALSE);
1387
0
  g_return_val_if_fail (filename != NULL, FALSE);
1388
1389
0
  priv = parser->priv;
1390
1391
0
  internal_error = NULL;
1392
0
  if (!g_file_get_contents (filename, &data, &length, &internal_error))
1393
0
    {
1394
0
      g_propagate_error (error, internal_error);
1395
0
      return FALSE;
1396
0
    }
1397
1398
0
  g_free (priv->filename);
1399
1400
0
  priv->is_filename = TRUE;
1401
0
  priv->filename = g_strdup (filename);
1402
1403
0
  if (!json_parser_load (parser, data, length, &internal_error))
1404
0
    {
1405
0
      g_propagate_error (error, internal_error);
1406
0
      retval = FALSE;
1407
0
    }
1408
1409
0
  g_free (data);
1410
1411
0
  return retval;
1412
0
}
1413
1414
/**
1415
 * json_parser_load_from_mapped_file:
1416
 * @parser: a parser
1417
 * @filename: (type filename): the path for the file to parse
1418
 * @error: return location for a #GError
1419
 *
1420
 * Loads a JSON stream from the content of `filename` and parses it.
1421
 *
1422
 * Unlike [method@Json.Parser.load_from_file], `filename` will be memory
1423
 * mapped as read-only and parsed. `filename` will be unmapped before this
1424
 * function returns.
1425
 *
1426
 * If mapping or reading the file fails, a `G_FILE_ERROR` will be returned.
1427
 *
1428
 * Returns: `TRUE` if the file was successfully loaded and parsed.
1429
 * Since: 1.6
1430
 */
1431
gboolean
1432
json_parser_load_from_mapped_file (JsonParser   *parser,
1433
                                   const gchar  *filename,
1434
                                   GError      **error)
1435
0
{
1436
0
  JsonParserPrivate *priv;
1437
0
  GError *internal_error = NULL;
1438
0
  gboolean retval = TRUE;
1439
0
  GMappedFile *mapped_file = NULL;
1440
1441
0
  g_return_val_if_fail (JSON_IS_PARSER (parser), FALSE);
1442
0
  g_return_val_if_fail (filename != NULL, FALSE);
1443
1444
0
  priv = parser->priv;
1445
1446
0
  mapped_file = g_mapped_file_new (filename, FALSE, &internal_error);
1447
0
  if (mapped_file == NULL)
1448
0
    {
1449
0
      g_propagate_error (error, internal_error);
1450
0
      return FALSE;
1451
0
    }
1452
1453
0
  g_free (priv->filename);
1454
1455
0
  priv->is_filename = TRUE;
1456
0
  priv->filename = g_strdup (filename);
1457
1458
0
  if (!json_parser_load (parser, g_mapped_file_get_contents (mapped_file),
1459
0
                         g_mapped_file_get_length (mapped_file), &internal_error))
1460
0
    {
1461
0
      g_propagate_error (error, internal_error);
1462
0
      retval = FALSE;
1463
0
    }
1464
1465
0
  g_clear_pointer (&mapped_file, g_mapped_file_unref);
1466
1467
0
  return retval;
1468
0
}
1469
1470
/**
1471
 * json_parser_load_from_data:
1472
 * @parser: a parser
1473
 * @data: the buffer to parse
1474
 * @length: the length of the buffer, or -1 if it is `NUL` terminated
1475
 * @error: return location for a #GError
1476
 *
1477
 * Loads a JSON stream from a buffer and parses it.
1478
 *
1479
 * You can call this function multiple times with the same parser, but the
1480
 * contents of the parser will be destroyed each time.
1481
 *
1482
 * Returns: `TRUE` if the buffer was succesfully parsed
1483
 */
1484
gboolean
1485
json_parser_load_from_data (JsonParser   *parser,
1486
                            const gchar  *data,
1487
                            gssize        length,
1488
                            GError      **error)
1489
0
{
1490
0
  JsonParserPrivate *priv;
1491
0
  GError *internal_error;
1492
0
  gboolean retval = TRUE;
1493
1494
0
  g_return_val_if_fail (JSON_IS_PARSER (parser), FALSE);
1495
0
  g_return_val_if_fail (data != NULL, FALSE);
1496
1497
0
  priv = parser->priv;
1498
1499
0
  if (length < 0)
1500
0
    length = strlen (data);
1501
1502
0
  priv->is_filename = FALSE;
1503
0
  g_free (priv->filename);
1504
0
  priv->filename = NULL;
1505
1506
0
  internal_error = NULL;
1507
0
  if (!json_parser_load (parser, data, length, &internal_error))
1508
0
    {
1509
0
      g_propagate_error (error, internal_error);
1510
0
      retval = FALSE;
1511
0
    }
1512
1513
0
  return retval;
1514
0
}
1515
1516
/**
1517
 * json_parser_get_root:
1518
 * @parser: a parser
1519
 *
1520
 * Retrieves the top level node from the parsed JSON stream.
1521
 *
1522
 * If the parser input was an empty string, or if parsing failed, the root
1523
 * will be `NULL`. It will also be `NULL` if it has been stolen using
1524
 * [method@Json.Parser.steal_root].
1525
 *
1526
 * Returns: (transfer none) (nullable): the root node.
1527
 */
1528
JsonNode *
1529
json_parser_get_root (JsonParser *parser)
1530
14.8k
{
1531
14.8k
  g_return_val_if_fail (JSON_IS_PARSER (parser), NULL);
1532
1533
  /* Sanity check. */
1534
14.8k
  g_assert (parser->priv->root == NULL ||
1535
14.8k
            !parser->priv->is_immutable ||
1536
14.8k
            json_node_is_immutable (parser->priv->root));
1537
1538
14.8k
  return parser->priv->root;
1539
14.8k
}
1540
1541
/**
1542
 * json_parser_steal_root:
1543
 * @parser: a parser
1544
 *
1545
 * Steals the top level node from the parsed JSON stream.
1546
 *
1547
 * This will be `NULL` in the same situations as [method@Json.Parser.get_root]
1548
 * return `NULL`.
1549
 *
1550
 * Returns: (transfer full) (nullable): the root node
1551
 *
1552
 * Since: 1.4
1553
 */
1554
JsonNode *
1555
json_parser_steal_root (JsonParser *parser)
1556
0
{
1557
0
  JsonParserPrivate *priv = json_parser_get_instance_private (parser);
1558
1559
0
  g_return_val_if_fail (JSON_IS_PARSER (parser), NULL);
1560
1561
  /* Sanity check. */
1562
0
  g_assert (parser->priv->root == NULL ||
1563
0
            !parser->priv->is_immutable ||
1564
0
            json_node_is_immutable (parser->priv->root));
1565
1566
0
  return g_steal_pointer (&priv->root);
1567
0
}
1568
1569
/**
1570
 * json_parser_get_current_line:
1571
 * @parser: a parser
1572
 *
1573
 * Retrieves the line currently parsed, starting from 1.
1574
 *
1575
 * This function has defined behaviour only while parsing; calling this
1576
 * function from outside the signal handlers emitted by the parser will
1577
 * yield 0.
1578
 *
1579
 * Returns: the currently parsed line, or 0.
1580
 */
1581
guint
1582
json_parser_get_current_line (JsonParser *parser)
1583
0
{
1584
0
  g_return_val_if_fail (JSON_IS_PARSER (parser), 0);
1585
1586
0
  if (parser->priv->scanner != NULL)
1587
0
    return json_scanner_get_current_line (parser->priv->scanner);
1588
1589
0
  return 0;
1590
0
}
1591
1592
/**
1593
 * json_parser_get_current_pos:
1594
 * @parser: a parser
1595
 *
1596
 * Retrieves the current position inside the current line, starting
1597
 * from 0.
1598
 *
1599
 * This function has defined behaviour only while parsing; calling this
1600
 * function from outside the signal handlers emitted by the parser will
1601
 * yield 0.
1602
 *
1603
 * Returns: the position in the current line, or 0.
1604
 */
1605
guint
1606
json_parser_get_current_pos (JsonParser *parser)
1607
0
{
1608
0
  g_return_val_if_fail (JSON_IS_PARSER (parser), 0);
1609
1610
0
  if (parser->priv->scanner != NULL)
1611
0
    return json_scanner_get_current_position (parser->priv->scanner);
1612
1613
0
  return 0;
1614
0
}
1615
1616
/**
1617
 * json_parser_has_assignment:
1618
 * @parser: a parser
1619
 * @variable_name: (out) (optional) (transfer none): the variable name
1620
 *
1621
 * A JSON data stream might sometimes contain an assignment, like:
1622
 *
1623
 * ```
1624
 * var _json_data = { "member_name" : [ ...
1625
 * ```
1626
 *
1627
 * even though it would technically constitute a violation of the RFC.
1628
 *
1629
 * `JsonParser` will ignore the left hand identifier and parse the right
1630
 * hand value of the assignment. `JsonParser` will record, though, the
1631
 * existence of the assignment in the data stream and the variable name
1632
 * used.
1633
 *
1634
 * Returns: `TRUE` if there was an assignment, and `FALSE` otherwise
1635
 *
1636
 * Since: 0.4
1637
 */
1638
gboolean
1639
json_parser_has_assignment (JsonParser  *parser,
1640
                            gchar      **variable_name)
1641
0
{
1642
0
  JsonParserPrivate *priv;
1643
1644
0
  g_return_val_if_fail (JSON_IS_PARSER (parser), FALSE);
1645
1646
0
  priv = parser->priv;
1647
1648
0
  if (priv->has_assignment && variable_name)
1649
0
    *variable_name = priv->variable_name;
1650
1651
0
  return priv->has_assignment;
1652
0
}
1653
1654
124k
#define GET_DATA_BLOCK_SIZE     8192
1655
1656
/**
1657
 * json_parser_load_from_stream:
1658
 * @parser: a parser
1659
 * @stream: the input stream with the JSON data
1660
 * @cancellable: (nullable): a #GCancellable
1661
 * @error: the return location for a #GError
1662
 *
1663
 * Loads the contents of an input stream and parses them.
1664
 *
1665
 * If `cancellable` is not `NULL`, then the operation can be cancelled by
1666
 * triggering the cancellable object from another thread. If the
1667
 * operation was cancelled, `G_IO_ERROR_CANCELLED` will be set
1668
 * on the given `error`.
1669
 *
1670
 * Returns: `TRUE` if the data stream was successfully read and
1671
 *   parsed, and `FALSE` otherwise
1672
 *
1673
 * Since: 0.12
1674
 */
1675
gboolean
1676
json_parser_load_from_stream (JsonParser    *parser,
1677
                              GInputStream  *stream,
1678
                              GCancellable  *cancellable,
1679
                              GError       **error)
1680
16.3k
{
1681
16.3k
  GByteArray *content;
1682
16.3k
  gsize pos;
1683
16.3k
  gssize res;
1684
16.3k
  gboolean retval = FALSE;
1685
16.3k
  GError *internal_error;
1686
1687
16.3k
  g_return_val_if_fail (JSON_IS_PARSER (parser), FALSE);
1688
16.3k
  g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE);
1689
16.3k
  g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
1690
1691
16.3k
  if (g_cancellable_set_error_if_cancelled (cancellable, error))
1692
0
    return FALSE;
1693
1694
16.3k
  content = g_byte_array_new ();
1695
16.3k
  pos = 0;
1696
1697
16.3k
  g_byte_array_set_size (content, pos + GET_DATA_BLOCK_SIZE + 1);
1698
62.4k
  while ((res = g_input_stream_read (stream, content->data + pos,
1699
62.4k
                                     GET_DATA_BLOCK_SIZE,
1700
62.4k
                                     cancellable, error)) > 0)
1701
46.0k
    {
1702
46.0k
      pos += res;
1703
46.0k
      g_byte_array_set_size (content, pos + GET_DATA_BLOCK_SIZE + 1);
1704
46.0k
    }
1705
1706
16.3k
  if (res < 0)
1707
0
    {
1708
      /* error has already been set */
1709
0
      retval = FALSE;
1710
0
      goto out;
1711
0
    }
1712
1713
  /* zero-terminate the content; we allocated an extra byte for this */
1714
16.3k
  content->data[pos] = 0;
1715
1716
16.3k
  internal_error = NULL;
1717
16.3k
  retval = json_parser_load (parser, (const gchar *) content->data, pos, &internal_error);
1718
1719
16.3k
  if (internal_error != NULL)
1720
1.52k
    g_propagate_error (error, internal_error);
1721
1722
16.3k
out:
1723
16.3k
  g_byte_array_free (content, TRUE);
1724
1725
16.3k
  return retval;
1726
16.3k
}
1727
1728
typedef struct {
1729
  GInputStream *stream;
1730
  GByteArray *content;
1731
  gsize pos;
1732
} LoadData;
1733
1734
static void
1735
load_data_free (gpointer data_)
1736
0
{
1737
0
  if (data_ != NULL)
1738
0
    {
1739
0
      LoadData *data = data_;
1740
1741
0
      g_object_unref (data->stream);
1742
0
      g_byte_array_unref (data->content);
1743
0
      g_free (data);
1744
0
    }
1745
0
}
1746
1747
/**
1748
 * json_parser_load_from_stream_finish:
1749
 * @parser: a parser
1750
 * @result: the result of the asynchronous operation
1751
 * @error: the return location for a #GError
1752
 *
1753
 * Finishes an asynchronous stream loading started with
1754
 * [method@Json.Parser.load_from_stream_async].
1755
 *
1756
 * Returns: `TRUE` if the content of the stream was successfully retrieved
1757
 *   and parsed, and `FALSE` otherwise
1758
 *
1759
 * Since: 0.12
1760
 */
1761
gboolean
1762
json_parser_load_from_stream_finish (JsonParser    *parser,
1763
                                     GAsyncResult  *result,
1764
                                     GError       **error)
1765
0
{
1766
0
  gboolean res;
1767
1768
0
  g_return_val_if_fail (JSON_IS_PARSER (parser), FALSE);
1769
0
  g_return_val_if_fail (g_task_is_valid (result, parser), FALSE);
1770
1771
0
  res = g_task_propagate_boolean (G_TASK (result), error);
1772
0
  if (res)
1773
0
    {
1774
0
      LoadData *data = g_task_get_task_data (G_TASK (result));
1775
0
      GError *internal_error = NULL;
1776
1777
      /* We need to do this inside the finish() function because JsonParser will emit
1778
       * signals, and we need to ensure that the signals are emitted in the right
1779
       * context; it's easier to do that if we just rely on the async callback being
1780
       * called in the right context, even if it means making the finish() function
1781
       * necessary to complete the async operation.
1782
       */
1783
0
      res = json_parser_load (parser, (const gchar *) data->content->data, data->pos, &internal_error);
1784
0
      if (internal_error != NULL)
1785
0
        g_propagate_error (error, internal_error);
1786
0
    }
1787
1788
0
  return res;
1789
0
}
1790
1791
static void
1792
read_from_stream (GTask *task,
1793
                  gpointer source_obj G_GNUC_UNUSED,
1794
                  gpointer task_data,
1795
                  GCancellable *cancellable)
1796
0
{
1797
0
  LoadData *data = task_data;
1798
0
  GError *error = NULL;
1799
0
  gssize res;
1800
1801
0
  data->pos = 0;
1802
0
  g_byte_array_set_size (data->content, data->pos + GET_DATA_BLOCK_SIZE + 1);
1803
0
  while ((res = g_input_stream_read (data->stream,
1804
0
                                     data->content->data + data->pos,
1805
0
                                     GET_DATA_BLOCK_SIZE,
1806
0
                                     cancellable, &error)) > 0)
1807
0
    {
1808
0
      data->pos += res;
1809
0
      g_byte_array_set_size (data->content, data->pos + GET_DATA_BLOCK_SIZE + 1);
1810
0
    }
1811
1812
0
  if (res < 0)
1813
0
    {
1814
0
      g_task_return_error (task, error);
1815
0
      return;
1816
0
    }
1817
1818
  /* zero-terminate the content; we allocated an extra byte for this */
1819
0
  data->content->data[data->pos] = 0;
1820
0
  g_task_return_boolean (task, TRUE);
1821
0
}
1822
1823
/**
1824
 * json_parser_load_from_stream_async:
1825
 * @parser: a parser
1826
 * @stream: the input stream with the JSON data
1827
 * @cancellable: (nullable): a #GCancellable
1828
 * @callback: (scope async): the function to call when the request is satisfied
1829
 * @user_data: the data to pass to @callback
1830
 *
1831
 * Asynchronously reads the contents of a stream.
1832
 *
1833
 * For more details, see [method@Json.Parser.load_from_stream], which is the
1834
 * synchronous version of this call.
1835
 *
1836
 * When the operation is finished, @callback will be called. You should
1837
 * then call [method@Json.Parser.load_from_stream_finish] to get the result
1838
 * of the operation.
1839
 *
1840
 * Since: 0.12
1841
 */
1842
void
1843
json_parser_load_from_stream_async (JsonParser          *parser,
1844
                                    GInputStream        *stream,
1845
                                    GCancellable        *cancellable,
1846
                                    GAsyncReadyCallback  callback,
1847
                                    gpointer             user_data)
1848
0
{
1849
0
  LoadData *data;
1850
0
  GTask *task;
1851
1852
0
  g_return_if_fail (JSON_IS_PARSER (parser));
1853
0
  g_return_if_fail (G_IS_INPUT_STREAM (stream));
1854
0
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1855
1856
0
  data = g_new (LoadData, 1);
1857
0
  data->stream = g_object_ref (stream);
1858
0
  data->content = g_byte_array_new ();
1859
0
  data->pos = 0;
1860
1861
0
  task = g_task_new (parser, cancellable, callback, user_data);
1862
0
  g_task_set_task_data (task, data, load_data_free);
1863
1864
0
  g_task_run_in_thread (task, read_from_stream);
1865
0
  g_object_unref (task);
1866
0
}
1867
1868
/**
1869
 * json_parser_set_strict:
1870
 * @parser: the JSON parser
1871
 * @strict: whether the parser should be strict
1872
 *
1873
 * Sets whether the parser should operate in strict mode.
1874
 *
1875
 * If @strict is true, `JsonParser` will strictly conform to
1876
 * the JSON format.
1877
 *
1878
 * If @strict is false, `JsonParser` will allow custom extensions
1879
 * to the JSON format, like comments.
1880
 *
1881
 * Since: 1.10
1882
 */
1883
void
1884
json_parser_set_strict (JsonParser *parser,
1885
                        gboolean    strict)
1886
0
{
1887
0
  g_return_if_fail (JSON_IS_PARSER (parser));
1888
1889
0
  JsonParserPrivate *priv = json_parser_get_instance_private (parser);
1890
1891
0
  strict = !!strict;
1892
1893
0
  if (priv->is_strict != strict)
1894
0
    {
1895
0
      priv->is_strict = strict;
1896
0
      g_object_notify_by_pspec (G_OBJECT (parser), parser_props[PROP_STRICT]);
1897
0
    }
1898
0
}
1899
1900
/**
1901
 * json_parser_get_strict:
1902
 * @parser: the JSON parser
1903
 *
1904
 * Retrieves whether the parser is operating in strict mode.
1905
 *
1906
 * Returns: true if the parser is strict, and false otherwise
1907
 *
1908
 * Since: 1.10
1909
 */
1910
gboolean
1911
json_parser_get_strict (JsonParser *parser)
1912
0
{
1913
0
  g_return_val_if_fail (JSON_IS_PARSER (parser), FALSE);
1914
1915
0
  JsonParserPrivate *priv = json_parser_get_instance_private (parser);
1916
1917
0
  return priv->is_strict;
1918
0
}