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