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