Initial Import
[profile/ivi/json-glib.git] / json-glib / json-builder.c
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  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  * Author:
20  *   Luca Bruno  <lethalman88@gmail.com>
21  */
22
23 /**
24  * SECTION:json-builder
25  * @Title: JsonBuilder
26  * @short_description: Generates JSON trees
27  * @See_Also: JsonGenerator
28  *
29  * #JsonBuilder provides an object for generating a JSON tree.
30  * You can generate only one tree with one #JsonBuilder instance.
31  *
32  * The root of the JSON tree can be either a #JsonObject or a #JsonArray.
33  * Thus the first call must necessarily be either
34  * json_builder_begin_object() or json_builder_begin_array().
35  *
36  * For convenience to language bindings, #JsonBuilder returns itself from
37  * most of functions, making it easy to chain function calls.
38  */
39
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
43
44 #include <stdlib.h>
45 #include <string.h>
46
47 #include "json-types-private.h"
48
49 #include "json-builder.h"
50
51 #define JSON_BUILDER_GET_PRIVATE(obj) \
52         (G_TYPE_INSTANCE_GET_PRIVATE ((obj), JSON_TYPE_BUILDER, JsonBuilderPrivate))
53
54 struct _JsonBuilderPrivate
55 {
56   GQueue *stack;
57   JsonNode *root;
58 };
59
60 typedef enum
61 {
62   JSON_BUILDER_MODE_OBJECT,
63   JSON_BUILDER_MODE_ARRAY,
64   JSON_BUILDER_MODE_MEMBER
65 } JsonBuilderMode;
66
67 typedef struct
68 {
69   JsonBuilderMode mode;
70
71   union
72   {
73     JsonObject *object;
74     JsonArray *array;
75   } data;
76   gchar *member_name;
77 } JsonBuilderState;
78
79 static void
80 json_builder_state_free (JsonBuilderState *state)
81 {
82   if (G_LIKELY (state))
83     {
84       switch (state->mode)
85         {
86         case JSON_BUILDER_MODE_OBJECT:
87         case JSON_BUILDER_MODE_MEMBER:
88           json_object_unref (state->data.object);
89           g_free (state->member_name);
90           state->data.object = NULL;
91           state->member_name = NULL;
92           break;
93         case JSON_BUILDER_MODE_ARRAY:
94           json_array_unref (state->data.array);
95           state->data.array = NULL;
96           break;
97         default:
98           g_assert_not_reached ();
99         }
100
101       g_slice_free (JsonBuilderState, state);
102     }
103 }
104
105 G_DEFINE_TYPE (JsonBuilder, json_builder, G_TYPE_OBJECT);
106
107 static void
108 json_builder_free_all_state (JsonBuilder *builder)
109 {
110   JsonBuilderState *state;
111
112   while (!g_queue_is_empty (builder->priv->stack))
113     {
114       state = g_queue_pop_head (builder->priv->stack);
115       json_builder_state_free (state);
116     }
117
118   if (builder->priv->root)
119     {
120       json_node_free (builder->priv->root);
121       builder->priv->root = NULL;
122     }
123 }
124
125 static void
126 json_builder_finalize (GObject *gobject)
127 {
128   JsonBuilderPrivate *priv = JSON_BUILDER_GET_PRIVATE (gobject);
129
130   json_builder_free_all_state (JSON_BUILDER (gobject));
131
132   g_queue_free (priv->stack);
133   priv->stack = NULL;
134
135   G_OBJECT_CLASS (json_builder_parent_class)->finalize (gobject);
136 }
137
138 static void
139 json_builder_class_init (JsonBuilderClass *klass)
140 {
141   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
142
143   g_type_class_add_private (klass, sizeof (JsonBuilderPrivate));
144
145   gobject_class->finalize = json_builder_finalize;
146 }
147
148 static void
149 json_builder_init (JsonBuilder *builder)
150 {
151   JsonBuilderPrivate *priv;
152
153   builder->priv = priv = JSON_BUILDER_GET_PRIVATE (builder);
154
155   priv->stack = g_queue_new ();
156   priv->root = NULL;
157 }
158
159 static inline JsonBuilderMode
160 json_builder_current_mode (JsonBuilder *builder)
161 {
162   JsonBuilderState *state = g_queue_peek_head (builder->priv->stack);
163   return state->mode;
164 }
165
166 static inline gboolean
167 json_builder_is_valid_add_mode (JsonBuilder *builder)
168 {
169   JsonBuilderMode mode = json_builder_current_mode (builder);
170   return mode == JSON_BUILDER_MODE_MEMBER || mode == JSON_BUILDER_MODE_ARRAY;
171 }
172
173 /**
174  * json_builder_new:
175  *
176  * Creates a new #JsonBuilder. You can use this object to generate a
177  * JSON tree and obtain the root #JsonNode<!-- -->s.
178  *
179  * Return value: the newly created #JsonBuilder instance
180  */
181 JsonBuilder *
182 json_builder_new (void)
183 {
184   return g_object_new (JSON_TYPE_BUILDER, NULL);
185 }
186
187 /**
188  * json_builder_get_root:
189  * @builder: a #JsonBuilder
190  *
191  * Returns the root of the current constructed tree, if the build is complete
192  * (ie: all opened objects, object members and arrays are being closed).
193  *
194  * Return value: (transfer full): the #JsonNode, or %NULL if the build is not complete.
195  *   Free the returned value with json_node_free().
196  */
197 JsonNode *
198 json_builder_get_root (JsonBuilder *builder)
199 {
200   JsonNode *root = NULL;
201
202   g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
203
204   if (builder->priv->root)
205     root = json_node_copy (builder->priv->root);
206
207   return root;
208 }
209
210 /**
211  * json_builder_reset:
212  * @builder: a #JsonBuilder
213  *
214  * Resets the state of the @builder back to its initial state.
215  */
216 void
217 json_builder_reset (JsonBuilder *builder)
218 {
219   g_return_if_fail (JSON_IS_BUILDER (builder));
220
221   json_builder_free_all_state (builder);
222 }
223
224 /**
225  * json_builder_begin_object:
226  * @builder: a #JsonBuilder
227  *
228  * Opens a subobject inside the given @builder. When done adding members to
229  * the subobject, json_builder_end_object() must be called.
230  *
231  * Can be called for first or only if the call is associated to an object member
232  * or an array element.
233  *
234  * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
235  */
236 JsonBuilder *
237 json_builder_begin_object (JsonBuilder *builder)
238 {
239   JsonObject *object;
240   JsonBuilderState *state;
241   JsonBuilderState *cur_state;
242
243   g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
244   g_return_val_if_fail (builder->priv->root == NULL, NULL);
245   g_return_val_if_fail (g_queue_is_empty (builder->priv->stack) || json_builder_is_valid_add_mode (builder), NULL);
246
247   object = json_object_new ();
248   cur_state = g_queue_peek_head (builder->priv->stack);
249   if (cur_state)
250     {
251       switch (cur_state->mode)
252         {
253         case JSON_BUILDER_MODE_ARRAY:
254           json_array_add_object_element (cur_state->data.array, json_object_ref (object));
255           break;
256
257         case JSON_BUILDER_MODE_MEMBER:
258           json_object_set_object_member (cur_state->data.object, cur_state->member_name, json_object_ref (object));
259           g_free (cur_state->member_name);
260           cur_state->member_name = NULL;
261           cur_state->mode = JSON_BUILDER_MODE_OBJECT;
262           break;
263
264         default:
265           g_assert_not_reached ();
266         }
267     }
268
269   state = g_slice_new (JsonBuilderState);
270   state->data.object = object;
271   state->member_name = NULL;
272   state->mode = JSON_BUILDER_MODE_OBJECT;
273   g_queue_push_head (builder->priv->stack, state);
274
275   return builder;
276 }
277
278 /**
279  * json_builder_end_object:
280  * @builder: a #JsonBuilder
281  *
282  * Closes the subobject inside the given @builder that was opened by the most
283  * recent call to json_builder_begin_object().
284  *
285  * Cannot be called after json_builder_set_member_name().
286  *
287  * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
288  */
289 JsonBuilder *
290 json_builder_end_object (JsonBuilder *builder)
291 {
292   JsonBuilderState *state;
293
294   g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
295   g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
296   g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_OBJECT, NULL);
297
298   state = g_queue_pop_head (builder->priv->stack);
299
300   if (g_queue_is_empty (builder->priv->stack))
301     {
302       builder->priv->root = json_node_new (JSON_NODE_OBJECT);
303       json_node_take_object (builder->priv->root, json_object_ref (state->data.object));
304     }
305
306   json_builder_state_free (state);
307
308   return builder;
309 }
310
311 /**
312  * json_builder_begin_array:
313  * @builder: a #JsonBuilder
314  *
315  * Opens a subarray inside the given @builder. When done adding members to
316  * the subarray, json_builder_end_array() must be called.
317  *
318  * Can be called for first or only if the call is associated to an object member
319  * or an array element.
320  *
321  * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
322  */
323 JsonBuilder *
324 json_builder_begin_array (JsonBuilder *builder)
325 {
326   JsonArray *array;
327   JsonBuilderState *state;
328   JsonBuilderState *cur_state;
329
330   g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
331   g_return_val_if_fail (builder->priv->root == NULL, NULL);
332   g_return_val_if_fail (g_queue_is_empty (builder->priv->stack) || json_builder_is_valid_add_mode (builder), NULL);
333
334   array = json_array_new ();
335   cur_state = g_queue_peek_head (builder->priv->stack);
336   if (cur_state)
337     {
338       switch (cur_state->mode)
339         {
340         case JSON_BUILDER_MODE_ARRAY:
341           json_array_add_array_element (cur_state->data.array, json_array_ref (array));
342           break;
343
344         case JSON_BUILDER_MODE_MEMBER:
345           json_object_set_array_member (cur_state->data.object, cur_state->member_name, json_array_ref (array));
346           g_free (cur_state->member_name);
347           cur_state->member_name = NULL;
348           cur_state->mode = JSON_BUILDER_MODE_OBJECT;
349           break;
350
351         default:
352           g_assert_not_reached ();
353         }
354     }
355
356   state = g_slice_new (JsonBuilderState);
357   state->data.array = array;
358   state->mode = JSON_BUILDER_MODE_ARRAY;
359   g_queue_push_head (builder->priv->stack, state);
360
361   return builder;
362 }
363
364 /**
365  * json_builder_end_array:
366  * @builder: a #JsonBuilder
367  *
368  * Closes the subarray inside the given @builder that was opened by the most
369  * recent call to json_builder_begin_array().
370  *
371  * Cannot be called after json_builder_set_member_name().
372  *
373  * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
374  */
375 JsonBuilder *
376 json_builder_end_array (JsonBuilder *builder)
377 {
378   JsonBuilderState *state;
379
380   g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
381   g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
382   g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_ARRAY, NULL);
383
384   state = g_queue_pop_head (builder->priv->stack);
385
386   if (g_queue_is_empty (builder->priv->stack))
387     {
388       builder->priv->root = json_node_new (JSON_NODE_ARRAY);
389       json_node_take_array (builder->priv->root, json_array_ref (state->data.array));
390     }
391
392   json_builder_state_free (state);
393
394   return builder;
395 }
396
397 /**
398  * json_builder_set_member_name:
399  * @builder: a #JsonBuilder
400  * @member_name: the name of the member
401  *
402  * Set the name of the next member in an object. The next call must add a value,
403  * open an object or an array.
404  *
405  * Can be called only if the call is associated to an object.
406  *
407  * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
408  */
409 JsonBuilder *
410 json_builder_set_member_name (JsonBuilder *builder, const gchar *member_name)
411 {
412   JsonBuilderState *state;
413
414   g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
415   g_return_val_if_fail (member_name != NULL, NULL);
416   g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
417   g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_OBJECT, NULL);
418
419   state = g_queue_peek_head (builder->priv->stack);
420   state->member_name = g_strdup (member_name);
421   state->mode = JSON_BUILDER_MODE_MEMBER;
422
423   return builder;
424 }
425
426 /**
427  * json_builder_add_value:
428  * @builder: a #JsonBuilder
429  * @node: the value of the member or element
430  *
431  * If called after json_builder_set_member_name(), sets @node as member of the
432  * most recent opened object, otherwise @node is added as element of the most
433  * recent opened array.
434  *
435  * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
436  */
437 JsonBuilder *
438 json_builder_add_value (JsonBuilder *builder, JsonNode *node)
439 {
440   JsonBuilderState *state;
441
442   g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
443   g_return_val_if_fail (node != NULL, NULL);
444   g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
445   g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
446
447   state = g_queue_peek_head (builder->priv->stack);
448   switch (state->mode)
449     {
450     case JSON_BUILDER_MODE_MEMBER:
451       json_object_set_member (state->data.object, state->member_name, node);
452       g_free (state->member_name);
453       state->member_name = NULL;
454       state->mode = JSON_BUILDER_MODE_OBJECT;
455       break;
456
457     case JSON_BUILDER_MODE_ARRAY:
458       json_array_add_element (state->data.array, node);
459       break;
460
461     default:
462       g_assert_not_reached ();
463     }
464
465   return builder;
466 }
467
468 /**
469  * json_builder_add_int_value:
470  * @builder: a #JsonBuilder
471  * @value: the value of the member or element
472  *
473  * If called after json_builder_set_member_name(), sets @value as member of the
474  * most recent opened object, otherwise @value is added as element of the most
475  * recent opened array.
476  *
477  * See also: json_builder_add_value()
478  *
479  * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
480  */
481 JsonBuilder *
482 json_builder_add_int_value (JsonBuilder *builder, gint64 value)
483 {
484   JsonBuilderState *state;
485
486   g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
487   g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
488   g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
489
490   state = g_queue_peek_head (builder->priv->stack);
491   switch (state->mode)
492     {
493     case JSON_BUILDER_MODE_MEMBER:
494       json_object_set_int_member (state->data.object, state->member_name, value);
495       g_free (state->member_name);
496       state->member_name = NULL;
497       state->mode = JSON_BUILDER_MODE_OBJECT;
498       break;
499
500     case JSON_BUILDER_MODE_ARRAY:
501       json_array_add_int_element (state->data.array, value);
502       break;
503
504     default:
505       g_assert_not_reached ();
506     }
507
508   return builder;
509 }
510
511 /**
512  * json_builder_add_double_value:
513  * @builder: a #JsonBuilder
514  * @value: the value of the member or element
515  *
516  * If called after json_builder_set_member_name(), sets @value as member of the
517  * most recent opened object, otherwise @value is added as element of the most
518  * recent opened array.
519  *
520  * See also: json_builder_add_value()
521  *
522  * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
523  */
524 JsonBuilder *
525 json_builder_add_double_value (JsonBuilder *builder, gdouble value)
526 {
527   JsonBuilderState *state;
528
529   g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
530   g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
531   g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
532
533   state = g_queue_peek_head (builder->priv->stack);
534
535   switch (state->mode)
536     {
537     case JSON_BUILDER_MODE_MEMBER:
538       json_object_set_double_member (state->data.object, state->member_name, value);
539       g_free (state->member_name);
540       state->member_name = NULL;
541       state->mode = JSON_BUILDER_MODE_OBJECT;
542       break;
543
544     case JSON_BUILDER_MODE_ARRAY:
545       json_array_add_double_element (state->data.array, value);
546       break;
547
548     default:
549       g_assert_not_reached ();
550     }
551
552   return builder;
553 }
554
555 /**
556  * json_builder_add_boolean_value:
557  * @builder: a #JsonBuilder
558  * @value: the value of the member or element
559  *
560  * If called after json_builder_set_member_name(), sets @value as member of the
561  * most recent opened object, otherwise @value is added as element of the most
562  * recent opened array.
563  *
564  * See also: json_builder_add_value()
565  *
566  * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
567  */
568 JsonBuilder *
569 json_builder_add_boolean_value (JsonBuilder *builder, gboolean value)
570 {
571   JsonBuilderState *state;
572
573   g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
574   g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
575   g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
576
577   state = g_queue_peek_head (builder->priv->stack);
578
579   switch (state->mode)
580     {
581     case JSON_BUILDER_MODE_MEMBER:
582       json_object_set_boolean_member (state->data.object, state->member_name, value);
583       g_free (state->member_name);
584       state->member_name = NULL;
585       state->mode = JSON_BUILDER_MODE_OBJECT;
586       break;
587
588     case JSON_BUILDER_MODE_ARRAY:
589       json_array_add_boolean_element (state->data.array, value);
590       break;
591
592     default:
593       g_assert_not_reached ();
594     }
595
596   return builder;
597 }
598
599 /**
600  * json_builder_add_string_value:
601  * @builder: a #JsonBuilder
602  * @value: the value of the member or element
603  *
604  * If called after json_builder_set_member_name(), sets @value as member of the
605  * most recent opened object, otherwise @value is added as element of the most
606  * recent opened array.
607  *
608  * See also: json_builder_add_value()
609  *
610  * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
611  */
612 JsonBuilder *
613 json_builder_add_string_value (JsonBuilder *builder, const gchar *value)
614 {
615   JsonBuilderState *state;
616
617   g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
618   g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
619   g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
620
621   state = g_queue_peek_head (builder->priv->stack);
622
623   switch (state->mode)
624     {
625     case JSON_BUILDER_MODE_MEMBER:
626       json_object_set_string_member (state->data.object, state->member_name, value);
627       g_free (state->member_name);
628       state->member_name = NULL;
629       state->mode = JSON_BUILDER_MODE_OBJECT;
630       break;
631
632     case JSON_BUILDER_MODE_ARRAY:
633       json_array_add_string_element (state->data.array, value);
634       break;
635
636     default:
637       g_assert_not_reached ();
638     }
639
640   return builder;
641 }
642
643 /**
644  * json_builder_add_null_value:
645  * @builder: a #JsonBuilder
646  *
647  * If called after json_builder_set_member_name(), sets null as member of the
648  * most recent opened object, otherwise null is added as element of the most
649  * recent opened array.
650  *
651  * See also: json_builder_add_value()
652  *
653  * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
654  */
655 JsonBuilder *
656 json_builder_add_null_value (JsonBuilder *builder)
657 {
658   JsonBuilderState *state;
659
660   g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
661   g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
662   g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
663
664   state = g_queue_peek_head (builder->priv->stack);
665
666   switch (state->mode)
667     {
668     case JSON_BUILDER_MODE_MEMBER:
669       json_object_set_null_member (state->data.object, state->member_name);
670       g_free (state->member_name);
671       state->member_name = NULL;
672       state->mode = JSON_BUILDER_MODE_OBJECT;
673       break;
674
675     case JSON_BUILDER_MODE_ARRAY:
676       json_array_add_null_element (state->data.array);
677       break;
678
679     default:
680       g_assert_not_reached ();
681     }
682
683   return builder;
684 }