Coverage Report

Created: 2025-06-22 06:29

/src/json-glib/json-glib/json-builder.c
Line
Count
Source (jump to first uncovered line)
1
/* json-generator.c - JSON tree builder
2
 *
3
 * This file is part of JSON-GLib
4
 * Copyright (C) 2010  Luca Bruno <lethalman88@gmail.com>
5
 * Copyright (C) 2015  Collabora Ltd.
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19
 *
20
 * Author:
21
 *   Luca Bruno  <lethalman88@gmail.com>
22
 *   Philip Withnall  <philip.withnall@collabora.co.uk>
23
 */
24
25
/**
26
 * JsonBuilder:
27
 *
28
 * `JsonBuilder` provides an object for generating a JSON tree.
29
 *
30
 * The root of the JSON tree can be either a [struct@Json.Object] or a [struct@Json.Array].
31
 * Thus the first call must necessarily be either
32
 * [method@Json.Builder.begin_object] or [method@Json.Builder.begin_array].
33
 *
34
 * For convenience to language bindings, most `JsonBuilder` method return the
35
 * instance, making it easy to chain function calls.
36
 *
37
 * ## Using `JsonBuilder`
38
 *
39
 * ```c
40
 * g_autoptr(JsonBuilder) builder = json_builder_new ();
41
 *
42
 * json_builder_begin_object (builder);
43
 *
44
 * json_builder_set_member_name (builder, "url");
45
 * json_builder_add_string_value (builder, "http://www.gnome.org/img/flash/two-thirty.png");
46
 *
47
 * json_builder_set_member_name (builder, "size");
48
 * json_builder_begin_array (builder);
49
 * json_builder_add_int_value (builder, 652);
50
 * json_builder_add_int_value (builder, 242);
51
 * json_builder_end_array (builder);
52
 *
53
 * json_builder_end_object (builder);
54
 *
55
 * g_autoptr(JsonNode) root = json_builder_get_root (builder);
56
 *
57
 * g_autoptr(JsonGenerator) gen = json_generator_new ();
58
 * json_generator_set_root (gen, root);
59
 * g_autofree char *str = json_generator_to_data (gen, NULL);
60
 *
61
 * // str now contains the following JSON data
62
 * // { "url" : "http://www.gnome.org/img/flash/two-thirty.png", "size" : [ 652, 242 ] }
63
 * ```
64
 */
65
66
#include "config.h"
67
68
#include <stdlib.h>
69
#include <string.h>
70
71
#include "json-types-private.h"
72
73
#include "json-builder.h"
74
75
struct _JsonBuilderPrivate
76
{
77
  GQueue *stack;
78
  JsonNode *root;
79
  gboolean immutable;
80
};
81
82
enum
83
{
84
  PROP_IMMUTABLE = 1,
85
  PROP_LAST
86
};
87
88
static GParamSpec *builder_props[PROP_LAST] = { NULL, };
89
90
typedef enum
91
{
92
  JSON_BUILDER_MODE_OBJECT,
93
  JSON_BUILDER_MODE_ARRAY,
94
  JSON_BUILDER_MODE_MEMBER
95
} JsonBuilderMode;
96
97
typedef struct
98
{
99
  JsonBuilderMode mode;
100
101
  union
102
  {
103
    JsonObject *object;
104
    JsonArray *array;
105
  } data;
106
  gchar *member_name;
107
} JsonBuilderState;
108
109
static void
110
json_builder_state_free (JsonBuilderState *state)
111
0
{
112
0
  if (G_LIKELY (state))
113
0
    {
114
0
      switch (state->mode)
115
0
        {
116
0
        case JSON_BUILDER_MODE_OBJECT:
117
0
        case JSON_BUILDER_MODE_MEMBER:
118
0
          json_object_unref (state->data.object);
119
0
          g_free (state->member_name);
120
0
          state->data.object = NULL;
121
0
          state->member_name = NULL;
122
0
          break;
123
124
0
        case JSON_BUILDER_MODE_ARRAY:
125
0
          json_array_unref (state->data.array);
126
0
          state->data.array = NULL;
127
0
          break;
128
129
0
        default:
130
0
          g_assert_not_reached ();
131
0
        }
132
133
0
      g_slice_free (JsonBuilderState, state);
134
0
    }
135
0
}
136
137
G_DEFINE_TYPE_WITH_PRIVATE (JsonBuilder, json_builder, G_TYPE_OBJECT)
138
139
static void
140
json_builder_free_all_state (JsonBuilder *builder)
141
0
{
142
0
  JsonBuilderState *state;
143
144
0
  while (!g_queue_is_empty (builder->priv->stack))
145
0
    {
146
0
      state = g_queue_pop_head (builder->priv->stack);
147
0
      json_builder_state_free (state);
148
0
    }
149
150
0
  if (builder->priv->root)
151
0
    {
152
0
      json_node_unref (builder->priv->root);
153
0
      builder->priv->root = NULL;
154
0
    }
155
0
}
156
157
static void
158
json_builder_finalize (GObject *gobject)
159
0
{
160
0
  JsonBuilderPrivate *priv = json_builder_get_instance_private ((JsonBuilder *) gobject);
161
162
0
  json_builder_free_all_state (JSON_BUILDER (gobject));
163
164
0
  g_queue_free (priv->stack);
165
0
  priv->stack = NULL;
166
167
0
  G_OBJECT_CLASS (json_builder_parent_class)->finalize (gobject);
168
0
}
169
170
static void
171
json_builder_set_property (GObject      *gobject,
172
                           guint         prop_id,
173
                           const GValue *value,
174
                           GParamSpec   *pspec)
175
0
{
176
0
  JsonBuilderPrivate *priv = JSON_BUILDER (gobject)->priv;
177
178
0
  switch (prop_id)
179
0
    {
180
0
    case PROP_IMMUTABLE:
181
      /* Construct-only. */
182
0
      priv->immutable = g_value_get_boolean (value);
183
0
      break;
184
0
    default:
185
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
186
0
      break;
187
0
    }
188
0
}
189
190
static void
191
json_builder_get_property (GObject    *gobject,
192
                           guint       prop_id,
193
                           GValue     *value,
194
                           GParamSpec *pspec)
195
0
{
196
0
  JsonBuilderPrivate *priv = JSON_BUILDER (gobject)->priv;
197
198
0
  switch (prop_id)
199
0
    {
200
0
    case PROP_IMMUTABLE:
201
0
      g_value_set_boolean (value, priv->immutable);
202
0
      break;
203
0
    default:
204
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
205
0
      break;
206
0
    }
207
0
}
208
209
static void
210
json_builder_class_init (JsonBuilderClass *klass)
211
0
{
212
0
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
213
214
  /**
215
   * JsonBuilder:immutable:
216
   *
217
   * Whether the tree should be immutable when created.
218
   *
219
   * Making the output immutable on creation avoids the expense
220
   * of traversing it to make it immutable later.
221
   *
222
   * Since: 1.2
223
   */
224
0
  builder_props[PROP_IMMUTABLE] =
225
0
    g_param_spec_boolean ("immutable",
226
0
                          "Immutable Output",
227
0
                          "Whether the builder output is immutable.",
228
0
                          FALSE,
229
0
                          G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
230
231
0
  gobject_class->set_property = json_builder_set_property;
232
0
  gobject_class->get_property = json_builder_get_property;
233
0
  gobject_class->finalize = json_builder_finalize;
234
235
0
  g_object_class_install_properties (gobject_class, PROP_LAST, builder_props);
236
0
}
237
238
static void
239
json_builder_init (JsonBuilder *builder)
240
0
{
241
0
  JsonBuilderPrivate *priv = json_builder_get_instance_private (builder);
242
243
0
  builder->priv = priv;
244
245
0
  priv->stack = g_queue_new ();
246
0
  priv->root = NULL;
247
0
}
248
249
static inline JsonBuilderMode
250
json_builder_current_mode (JsonBuilder *builder)
251
0
{
252
0
  JsonBuilderState *state = g_queue_peek_head (builder->priv->stack);
253
0
  return state->mode;
254
0
}
255
256
static inline gboolean
257
json_builder_is_valid_add_mode (JsonBuilder *builder)
258
0
{
259
0
  JsonBuilderMode mode = json_builder_current_mode (builder);
260
0
  return mode == JSON_BUILDER_MODE_MEMBER || mode == JSON_BUILDER_MODE_ARRAY;
261
0
}
262
263
/**
264
 * json_builder_new:
265
 *
266
 * Creates a new `JsonBuilder`.
267
 *
268
 * You can use this object to generate a JSON tree and obtain the root node.
269
 *
270
 * Return value: the newly created builder instance
271
 */
272
JsonBuilder *
273
json_builder_new (void)
274
0
{
275
0
  return g_object_new (JSON_TYPE_BUILDER, NULL);
276
0
}
277
278
/**
279
 * json_builder_new_immutable: (constructor)
280
 *
281
 * Creates a new, immutable `JsonBuilder` instance.
282
 *
283
 * It is equivalent to setting the [property@Json.Builder:immutable] property
284
 * set to `TRUE` at construction time.
285
 *
286
 * Since: 1.2
287
 * Returns: (transfer full): the newly create builder instance
288
 */
289
JsonBuilder *
290
json_builder_new_immutable (void)
291
0
{
292
0
  return g_object_new (JSON_TYPE_BUILDER, "immutable", TRUE, NULL);
293
0
}
294
295
/**
296
 * json_builder_get_root:
297
 * @builder: a builder
298
 *
299
 * Returns the root of the currently constructed tree.
300
 *
301
 * if the build is incomplete (ie: if there are any opened objects, or any
302
 * open object members and array elements) then this function will return
303
 * `NULL`.
304
 *
305
 * Return value: (nullable) (transfer full): the root node
306
 */
307
JsonNode *
308
json_builder_get_root (JsonBuilder *builder)
309
0
{
310
0
  JsonNode *root = NULL;
311
312
0
  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
313
314
0
  if (builder->priv->root)
315
0
    root = json_node_copy (builder->priv->root);
316
317
  /* Sanity check. */
318
0
  g_assert (!builder->priv->immutable ||
319
0
            root == NULL ||
320
0
            json_node_is_immutable (root));
321
322
0
  return root;
323
0
}
324
325
/**
326
 * json_builder_reset:
327
 * @builder: a builder
328
 *
329
 * Resets the state of the builder back to its initial state.
330
 */
331
void
332
json_builder_reset (JsonBuilder *builder)
333
0
{
334
0
  g_return_if_fail (JSON_IS_BUILDER (builder));
335
336
0
  json_builder_free_all_state (builder);
337
0
}
338
339
/**
340
 * json_builder_begin_object:
341
 * @builder: a builder
342
 *
343
 * Opens an object inside the given builder.
344
 *
345
 * You can add a new member to the object by using [method@Json.Builder.set_member_name],
346
 * followed by [method@Json.Builder.add_value].
347
 *
348
 * Once you added all members to the object, you must call [method@Json.Builder.end_object]
349
 * to close the object.
350
 *
351
 * If the builder is in an inconsistent state, this function will return `NULL`.
352
 *
353
 * Return value: (nullable) (transfer none): the builder instance
354
 */
355
JsonBuilder *
356
json_builder_begin_object (JsonBuilder *builder)
357
0
{
358
0
  JsonObject *object;
359
0
  JsonBuilderState *state;
360
0
  JsonBuilderState *cur_state;
361
362
0
  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
363
0
  g_return_val_if_fail (builder->priv->root == NULL, NULL);
364
0
  g_return_val_if_fail (g_queue_is_empty (builder->priv->stack) || json_builder_is_valid_add_mode (builder), NULL);
365
366
0
  object = json_object_new ();
367
0
  cur_state = g_queue_peek_head (builder->priv->stack);
368
0
  if (cur_state)
369
0
    {
370
0
      switch (cur_state->mode)
371
0
        {
372
0
        case JSON_BUILDER_MODE_ARRAY:
373
0
          json_array_add_object_element (cur_state->data.array, json_object_ref (object));
374
0
          break;
375
376
0
        case JSON_BUILDER_MODE_MEMBER:
377
0
          json_object_set_object_member (cur_state->data.object, cur_state->member_name, json_object_ref (object));
378
0
          g_free (cur_state->member_name);
379
0
          cur_state->member_name = NULL;
380
0
          cur_state->mode = JSON_BUILDER_MODE_OBJECT;
381
0
          break;
382
383
0
        default:
384
0
          g_assert_not_reached ();
385
0
        }
386
0
    }
387
388
0
  state = g_slice_new (JsonBuilderState);
389
0
  state->data.object = object;
390
0
  state->member_name = NULL;
391
0
  state->mode = JSON_BUILDER_MODE_OBJECT;
392
0
  g_queue_push_head (builder->priv->stack, state);
393
394
0
  return builder;
395
0
}
396
397
/**
398
 * json_builder_end_object:
399
 * @builder: a builder
400
 *
401
 * Closes the object inside the given builder that was opened by the most
402
 * recent call to [method@Json.Builder.begin_object].
403
 *
404
 * This function cannot be called after [method@Json.Builder.set_member_name].
405
 *
406
 * Return value: (nullable) (transfer none): the builder instance
407
 */
408
JsonBuilder *
409
json_builder_end_object (JsonBuilder *builder)
410
0
{
411
0
  JsonBuilderState *state;
412
413
0
  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
414
0
  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
415
0
  g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_OBJECT, NULL);
416
417
0
  state = g_queue_pop_head (builder->priv->stack);
418
419
0
  if (builder->priv->immutable)
420
0
    json_object_seal (state->data.object);
421
422
0
  if (g_queue_is_empty (builder->priv->stack))
423
0
    {
424
0
      builder->priv->root = json_node_new (JSON_NODE_OBJECT);
425
0
      json_node_take_object (builder->priv->root, json_object_ref (state->data.object));
426
427
0
      if (builder->priv->immutable)
428
0
        json_node_seal (builder->priv->root);
429
0
    }
430
431
0
  json_builder_state_free (state);
432
433
0
  return builder;
434
0
}
435
436
/**
437
 * json_builder_begin_array:
438
 * @builder: a builder
439
 *
440
 * Opens an array inside the given builder.
441
 *
442
 * You can add a new element to the array by using [method@Json.Builder.add_value].
443
 *
444
 * Once you added all elements to the array, you must call
445
 * [method@Json.Builder.end_array] to close the array.
446
 *
447
 * Return value: (nullable) (transfer none): the builder instance
448
 */
449
JsonBuilder *
450
json_builder_begin_array (JsonBuilder *builder)
451
0
{
452
0
  JsonArray *array;
453
0
  JsonBuilderState *state;
454
0
  JsonBuilderState *cur_state;
455
456
0
  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
457
0
  g_return_val_if_fail (builder->priv->root == NULL, NULL);
458
0
  g_return_val_if_fail (g_queue_is_empty (builder->priv->stack) || json_builder_is_valid_add_mode (builder), NULL);
459
460
0
  array = json_array_new ();
461
0
  cur_state = g_queue_peek_head (builder->priv->stack);
462
0
  if (cur_state)
463
0
    {
464
0
      switch (cur_state->mode)
465
0
        {
466
0
        case JSON_BUILDER_MODE_ARRAY:
467
0
          json_array_add_array_element (cur_state->data.array, json_array_ref (array));
468
0
          break;
469
470
0
        case JSON_BUILDER_MODE_MEMBER:
471
0
          json_object_set_array_member (cur_state->data.object, cur_state->member_name, json_array_ref (array));
472
0
          g_free (cur_state->member_name);
473
0
          cur_state->member_name = NULL;
474
0
          cur_state->mode = JSON_BUILDER_MODE_OBJECT;
475
0
          break;
476
477
0
        default:
478
0
          g_assert_not_reached ();
479
0
        }
480
0
    }
481
482
0
  state = g_slice_new (JsonBuilderState);
483
0
  state->data.array = array;
484
0
  state->mode = JSON_BUILDER_MODE_ARRAY;
485
0
  g_queue_push_head (builder->priv->stack, state);
486
487
0
  return builder;
488
0
}
489
490
/**
491
 * json_builder_end_array:
492
 * @builder: a builder
493
 *
494
 * Closes the array inside the given builder that was opened by the most
495
 * recent call to [method@Json.Builder.begin_array].
496
 *
497
 * This function cannot be called after [method@Json.Builder.set_member_name].
498
 *
499
 * Return value: (nullable) (transfer none): the builder instance
500
 */
501
JsonBuilder *
502
json_builder_end_array (JsonBuilder *builder)
503
0
{
504
0
  JsonBuilderState *state;
505
506
0
  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
507
0
  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
508
0
  g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_ARRAY, NULL);
509
510
0
  state = g_queue_pop_head (builder->priv->stack);
511
512
0
  if (builder->priv->immutable)
513
0
    json_array_seal (state->data.array);
514
515
0
  if (g_queue_is_empty (builder->priv->stack))
516
0
    {
517
0
      builder->priv->root = json_node_new (JSON_NODE_ARRAY);
518
0
      json_node_take_array (builder->priv->root, json_array_ref (state->data.array));
519
520
0
      if (builder->priv->immutable)
521
0
        json_node_seal (builder->priv->root);
522
0
    }
523
524
0
  json_builder_state_free (state);
525
526
0
  return builder;
527
0
}
528
529
/**
530
 * json_builder_set_member_name:
531
 * @builder: a builder
532
 * @member_name: the name of the member
533
 *
534
 * Sets the name of the member in an object.
535
 *
536
 * This function must be followed by of these functions:
537
 *
538
 *  - [method@Json.Builder.add_value], to add a scalar value to the member
539
 *  - [method@Json.Builder.begin_object], to add an object to the member
540
 *  - [method@Json.Builder.begin_array], to add an array to the member
541
 *
542
 * This function can only be called within an open object.
543
 *
544
 * Return value: (nullable) (transfer none): the builder instance
545
 */
546
JsonBuilder *
547
json_builder_set_member_name (JsonBuilder *builder,
548
                              const gchar *member_name)
549
0
{
550
0
  JsonBuilderState *state;
551
552
0
  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
553
0
  g_return_val_if_fail (member_name != NULL, NULL);
554
0
  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
555
0
  g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_OBJECT, NULL);
556
557
0
  state = g_queue_peek_head (builder->priv->stack);
558
0
  state->member_name = g_strdup (member_name);
559
0
  state->mode = JSON_BUILDER_MODE_MEMBER;
560
561
0
  return builder;
562
0
}
563
564
/**
565
 * json_builder_add_value:
566
 * @builder: a builder
567
 * @node: (transfer full): the value of the member or element
568
 *
569
 * Adds a value to the currently open object member or array.
570
 *
571
 * If called after [method@Json.Builder.set_member_name], sets the given node
572
 * as the value of the current member in the open object; otherwise, the node
573
 * is appended to the elements of the open array.
574
 *
575
 * The builder will take ownership of the node.
576
 *
577
 * Return value: (nullable) (transfer none): the builder instance
578
 */
579
JsonBuilder *
580
json_builder_add_value (JsonBuilder *builder,
581
                        JsonNode    *node)
582
0
{
583
0
  JsonBuilderState *state;
584
585
0
  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
586
0
  g_return_val_if_fail (node != NULL, NULL);
587
0
  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
588
0
  g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
589
590
0
  state = g_queue_peek_head (builder->priv->stack);
591
592
0
  if (builder->priv->immutable)
593
0
    json_node_seal (node);
594
595
0
  switch (state->mode)
596
0
    {
597
0
    case JSON_BUILDER_MODE_MEMBER:
598
0
      json_object_set_member (state->data.object, state->member_name, node);
599
0
      g_free (state->member_name);
600
0
      state->member_name = NULL;
601
0
      state->mode = JSON_BUILDER_MODE_OBJECT;
602
0
      break;
603
604
0
    case JSON_BUILDER_MODE_ARRAY:
605
0
      json_array_add_element (state->data.array, node);
606
0
      break;
607
608
0
    default:
609
0
      g_assert_not_reached ();
610
0
    }
611
612
0
  return builder;
613
0
}
614
615
/**
616
 * json_builder_add_int_value:
617
 * @builder: a builder
618
 * @value: the value of the member or element
619
 *
620
 * Adds an integer value to the currently open object member or array.
621
 *
622
 * If called after [method@Json.Builder.set_member_name], sets the given value
623
 * as the value of the current member in the open object; otherwise, the value
624
 * is appended to the elements of the open array.
625
 *
626
 * See also: [method@Json.Builder.add_value]
627
 *
628
 * Return value: (nullable) (transfer none): the builder instance
629
 */
630
JsonBuilder *
631
json_builder_add_int_value (JsonBuilder *builder,
632
                            gint64       value)
633
0
{
634
0
  JsonBuilderState *state;
635
636
0
  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
637
0
  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
638
0
  g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
639
640
0
  state = g_queue_peek_head (builder->priv->stack);
641
0
  switch (state->mode)
642
0
    {
643
0
    case JSON_BUILDER_MODE_MEMBER:
644
0
      json_object_set_int_member (state->data.object, state->member_name, value);
645
0
      g_free (state->member_name);
646
0
      state->member_name = NULL;
647
0
      state->mode = JSON_BUILDER_MODE_OBJECT;
648
0
      break;
649
650
0
    case JSON_BUILDER_MODE_ARRAY:
651
0
      json_array_add_int_element (state->data.array, value);
652
0
      break;
653
654
0
    default:
655
0
      g_assert_not_reached ();
656
0
    }
657
658
0
  return builder;
659
0
}
660
661
/**
662
 * json_builder_add_double_value:
663
 * @builder: a builder
664
 * @value: the value of the member or element
665
 *
666
 * Adds a floating point value to the currently open object member or array.
667
 *
668
 * If called after [method@Json.Builder.set_member_name], sets the given value
669
 * as the value of the current member in the open object; otherwise, the value
670
 * is appended to the elements of the open array.
671
 *
672
 * See also: [method@Json.Builder.add_value]
673
 *
674
 * Return value: (nullable) (transfer none): the builder instance
675
 */
676
JsonBuilder *
677
json_builder_add_double_value (JsonBuilder *builder,
678
                               gdouble      value)
679
0
{
680
0
  JsonBuilderState *state;
681
682
0
  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
683
0
  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
684
0
  g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
685
686
0
  state = g_queue_peek_head (builder->priv->stack);
687
688
0
  switch (state->mode)
689
0
    {
690
0
    case JSON_BUILDER_MODE_MEMBER:
691
0
      json_object_set_double_member (state->data.object, state->member_name, value);
692
0
      g_free (state->member_name);
693
0
      state->member_name = NULL;
694
0
      state->mode = JSON_BUILDER_MODE_OBJECT;
695
0
      break;
696
697
0
    case JSON_BUILDER_MODE_ARRAY:
698
0
      json_array_add_double_element (state->data.array, value);
699
0
      break;
700
701
0
    default:
702
0
      g_assert_not_reached ();
703
0
    }
704
705
0
  return builder;
706
0
}
707
708
/**
709
 * json_builder_add_boolean_value:
710
 * @builder: a builder
711
 * @value: the value of the member or element
712
 *
713
 * Adds a boolean value to the currently open object member or array.
714
 *
715
 * If called after [method@Json.Builder.set_member_name], sets the given value
716
 * as the value of the current member in the open object; otherwise, the value
717
 * is appended to the elements of the open array.
718
 *
719
 * See also: [method@Json.Builder.add_value]
720
 *
721
 * Return value: (nullable) (transfer none): the builder instance
722
 */
723
JsonBuilder *
724
json_builder_add_boolean_value (JsonBuilder *builder,
725
                                gboolean     value)
726
0
{
727
0
  JsonBuilderState *state;
728
729
0
  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
730
0
  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
731
0
  g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
732
733
0
  state = g_queue_peek_head (builder->priv->stack);
734
735
0
  switch (state->mode)
736
0
    {
737
0
    case JSON_BUILDER_MODE_MEMBER:
738
0
      json_object_set_boolean_member (state->data.object, state->member_name, value);
739
0
      g_free (state->member_name);
740
0
      state->member_name = NULL;
741
0
      state->mode = JSON_BUILDER_MODE_OBJECT;
742
0
      break;
743
744
0
    case JSON_BUILDER_MODE_ARRAY:
745
0
      json_array_add_boolean_element (state->data.array, value);
746
0
      break;
747
748
0
    default:
749
0
      g_assert_not_reached ();
750
0
    }
751
752
0
  return builder;
753
0
}
754
755
/**
756
 * json_builder_add_string_value:
757
 * @builder: a builder
758
 * @value: the value of the member or element
759
 *
760
 * Adds a boolean value to the currently open object member or array.
761
 *
762
 * If called after [method@Json.Builder.set_member_name], sets the given value
763
 * as the value of the current member in the open object; otherwise, the value
764
 * is appended to the elements of the open array.
765
 *
766
 * See also: [method@Json.Builder.add_value]
767
 *
768
 * Return value: (nullable) (transfer none): the builder instance
769
 */
770
JsonBuilder *
771
json_builder_add_string_value (JsonBuilder *builder,
772
                               const gchar *value)
773
0
{
774
0
  JsonBuilderState *state;
775
776
0
  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
777
0
  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
778
0
  g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
779
780
0
  state = g_queue_peek_head (builder->priv->stack);
781
782
0
  switch (state->mode)
783
0
    {
784
0
    case JSON_BUILDER_MODE_MEMBER:
785
0
      json_object_set_string_member (state->data.object, state->member_name, value);
786
0
      g_free (state->member_name);
787
0
      state->member_name = NULL;
788
0
      state->mode = JSON_BUILDER_MODE_OBJECT;
789
0
      break;
790
791
0
    case JSON_BUILDER_MODE_ARRAY:
792
0
      json_array_add_string_element (state->data.array, value);
793
0
      break;
794
795
0
    default:
796
0
      g_assert_not_reached ();
797
0
    }
798
799
0
  return builder;
800
0
}
801
802
/**
803
 * json_builder_add_null_value:
804
 * @builder: a builder
805
 *
806
 * Adds a null value to the currently open object member or array.
807
 *
808
 * If called after [method@Json.Builder.set_member_name], sets the given value
809
 * as the value of the current member in the open object; otherwise, the value
810
 * is appended to the elements of the open array.
811
 *
812
 * See also: [method@Json.Builder.add_value]
813
 *
814
 * Return value: (nullable) (transfer none): the builder instance
815
 */
816
JsonBuilder *
817
json_builder_add_null_value (JsonBuilder *builder)
818
0
{
819
0
  JsonBuilderState *state;
820
821
0
  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
822
0
  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
823
0
  g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
824
825
0
  state = g_queue_peek_head (builder->priv->stack);
826
827
0
  switch (state->mode)
828
0
    {
829
0
    case JSON_BUILDER_MODE_MEMBER:
830
0
      json_object_set_null_member (state->data.object, state->member_name);
831
0
      g_free (state->member_name);
832
0
      state->member_name = NULL;
833
0
      state->mode = JSON_BUILDER_MODE_OBJECT;
834
0
      break;
835
836
0
    case JSON_BUILDER_MODE_ARRAY:
837
0
      json_array_add_null_element (state->data.array);
838
0
      break;
839
840
0
    default:
841
0
      g_assert_not_reached ();
842
0
    }
843
844
0
  return builder;
845
0
}