Imported Upstream version 1.2.4
[platform/upstream/json-glib.git] / json-glib / json-reader.c
1 /* json-reader.h - JSON cursor parser
2  * 
3  * This file is part of JSON-GLib
4  * Copyright (C) 2010  Intel Corp.
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  *   Emmanuele Bassi  <ebassi@linux.intel.com>
21  */
22
23 /**
24  * SECTION:json-reader
25  * @Title: JsonReader
26  * @short_description: A cursor-based parser
27  *
28  * #JsonReader provides a simple, cursor-based API for parsing a JSON DOM. It
29  * is similar, in spirit, to the XML Reader API.
30  *
31  * In case of error, #JsonReader will be set in an error state; all subsequent
32  * calls will simply be ignored until a function that resets the error state is
33  * called, e.g.:
34  *
35  * |[
36  * // ask for the 7th element; if the element does not exist, the
37  * // reader will be put in an error state
38  * json_reader_read_element (reader, 6);
39  *
40  * // in case of error, this will return NULL, otherwise it will
41  * // return the value of the element
42  * str = json_reader_get_string_value (value);
43  *
44  * // this function resets the error state if any was set
45  * json_reader_end_element (reader);
46  * ]|
47  *
48  * If you want to detect the error state as soon as possible, you can use
49  * json_reader_get_error():
50  *
51  * |[<!-- language="C" -->
52  * // like the example above, but in this case we print out the
53  * // error immediately
54  * if (!json_reader_read_element (reader, 6))
55  *   {
56  *     const GError *error = json_reader_get_error (reader);
57  *     g_print ("Unable to read the element: %s", error->message);
58  *   }
59  * ]|
60  *
61  * #JsonReader is available since JSON-GLib 0.12.
62  */
63
64 #include "config.h"
65
66 #include <string.h>
67
68 #include <glib/gi18n-lib.h>
69
70 #include "json-reader.h"
71 #include "json-types-private.h"
72 #include "json-debug.h"
73
74 #define json_reader_return_if_error_set(r)      G_STMT_START {  \
75         if (((JsonReader *) (r))->priv->error != NULL)          \
76           return;                               } G_STMT_END
77
78 #define json_reader_return_val_if_error_set(r,v) G_STMT_START {  \
79         if (((JsonReader *) (r))->priv->error != NULL)           \
80           return (v);                           } G_STMT_END
81
82 struct _JsonReaderPrivate
83 {
84   JsonNode *root;
85
86   JsonNode *current_node;
87   JsonNode *previous_node;
88
89   /* Stack of member names. */
90   GPtrArray *members;
91
92   GError *error;
93 };
94
95 enum
96 {
97   PROP_0,
98
99   PROP_ROOT,
100
101   PROP_LAST
102 };
103
104 static GParamSpec *reader_properties[PROP_LAST] = { NULL, };
105
106 G_DEFINE_TYPE_WITH_PRIVATE (JsonReader, json_reader, G_TYPE_OBJECT)
107
108 G_DEFINE_QUARK (json-reader-error-quark, json_reader_error)
109
110 static void
111 json_reader_finalize (GObject *gobject)
112 {
113   JsonReaderPrivate *priv = JSON_READER (gobject)->priv;
114
115   if (priv->root != NULL)
116     json_node_unref (priv->root);
117
118   if (priv->error != NULL)
119     g_clear_error (&priv->error);
120
121   if (priv->members != NULL)
122     g_ptr_array_unref (priv->members);
123
124   G_OBJECT_CLASS (json_reader_parent_class)->finalize (gobject);
125 }
126
127 static void
128 json_reader_set_property (GObject      *gobject,
129                           guint         prop_id,
130                           const GValue *value,
131                           GParamSpec   *pspec)
132 {
133   switch (prop_id)
134     {
135     case PROP_ROOT:
136       json_reader_set_root (JSON_READER (gobject), g_value_get_boxed (value));
137       break;
138
139     default:
140       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
141       break;
142     }
143 }
144
145 static void
146 json_reader_get_property (GObject    *gobject,
147                           guint       prop_id,
148                           GValue     *value,
149                           GParamSpec *pspec)
150 {
151   switch (prop_id)
152     {
153     case PROP_ROOT:
154       g_value_set_boxed (value, JSON_READER (gobject)->priv->root);
155       break;
156
157     default:
158       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
159       break;
160     }
161 }
162
163 static void
164 json_reader_class_init (JsonReaderClass *klass)
165 {
166   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
167
168   /**
169    * JsonReader:root:
170    *
171    * The root of the JSON tree that the #JsonReader should read.
172    *
173    * Since: 0.12
174    */
175   reader_properties[PROP_ROOT] =
176     g_param_spec_boxed ("root",
177                         "Root Node",
178                         "The root of the tree to read",
179                         JSON_TYPE_NODE,
180                         G_PARAM_READWRITE |
181                         G_PARAM_CONSTRUCT |
182                         G_PARAM_STATIC_STRINGS);
183
184   gobject_class->finalize = json_reader_finalize;
185   gobject_class->set_property = json_reader_set_property;
186   gobject_class->get_property = json_reader_get_property;
187   g_object_class_install_properties (gobject_class, PROP_LAST, reader_properties);
188 }
189
190 static void
191 json_reader_init (JsonReader *self)
192 {
193   self->priv = json_reader_get_instance_private (self);
194   self->priv->members = g_ptr_array_new_with_free_func (g_free);
195 }
196
197 /**
198  * json_reader_new:
199  * @node: (allow-none): a #JsonNode, or %NULL
200  *
201  * Creates a new #JsonReader. You can use this object to read the contents of
202  * the JSON tree starting from @node
203  *
204  * Return value: the newly created #JsonReader. Use g_object_unref() to
205  *   release the allocated resources when done
206  *
207  * Since: 0.12
208  */
209 JsonReader *
210 json_reader_new (JsonNode *node)
211 {
212   return g_object_new (JSON_TYPE_READER, "root", node, NULL);
213 }
214
215 /*
216  * json_reader_unset_error:
217  * @reader: a #JsonReader
218  *
219  * Unsets the error state of @reader, if set
220  *
221  * Return value: TRUE if an error was set.
222  */
223 static inline gboolean
224 json_reader_unset_error (JsonReader *reader)
225 {
226   if (reader->priv->error != NULL)
227     {
228       g_clear_error (&(reader->priv->error));
229       return TRUE;
230     }
231   return FALSE;
232 }
233
234 /**
235  * json_reader_set_root:
236  * @reader: a #JsonReader
237  * @root: (allow-none): a #JsonNode
238  *
239  * Sets the root #JsonNode to be read by @reader. The @reader will take
240  * a copy of @root
241  *
242  * If another #JsonNode is currently set as root, it will be replaced.
243  *
244  * Since: 0.12
245  */
246 void
247 json_reader_set_root (JsonReader *reader,
248                       JsonNode   *root)
249 {
250   JsonReaderPrivate *priv;
251
252   g_return_if_fail (JSON_IS_READER (reader));
253
254   priv = reader->priv;
255
256   if (priv->root == root)
257     return;
258
259   if (priv->root != NULL)
260     {
261       json_node_unref (priv->root);
262       priv->root = NULL;
263       priv->current_node = NULL;
264       priv->previous_node = NULL;
265     }
266
267   if (root != NULL)
268     {
269       priv->root = json_node_copy (root);
270       priv->current_node = priv->root;
271       priv->previous_node = NULL;
272     }
273
274   g_object_notify_by_pspec (G_OBJECT (reader), reader_properties[PROP_ROOT]);
275 }
276
277 /*
278  * json_reader_ser_error:
279  * @reader: a #JsonReader
280  * @error_code: the #JsonReaderError code for the error
281  * @error_fmt: format string
282  * @Varargs: list of arguments for the @error_fmt string
283  *
284  * Sets the error state of @reader using the given error code
285  * and string
286  *
287  * Return value: %FALSE, to be used to return immediately from
288  *   the caller function
289  */
290 G_GNUC_PRINTF (3, 4)
291 static gboolean
292 json_reader_set_error (JsonReader      *reader,
293                        JsonReaderError  error_code,
294                        const gchar     *error_fmt,
295                        ...)
296 {
297   JsonReaderPrivate *priv = reader->priv;
298   va_list args;
299   gchar *error_msg;
300
301   if (priv->error != NULL)
302     g_clear_error (&priv->error);
303
304   va_start (args, error_fmt);
305   error_msg = g_strdup_vprintf (error_fmt, args);
306   va_end (args);
307
308   g_set_error_literal (&priv->error, JSON_READER_ERROR,
309                        error_code,
310                        error_msg);
311
312   g_free (error_msg);
313
314   return FALSE;
315 }
316
317 /**
318  * json_reader_get_error:
319  * @reader: a #JsonReader
320  *
321  * Retrieves the #GError currently set on @reader, if the #JsonReader
322  * is in error state
323  *
324  * Return value: (transfer none): the pointer to the error, or %NULL
325  *
326  * Since: 0.12
327  */
328 const GError *
329 json_reader_get_error (JsonReader *reader)
330 {
331   g_return_val_if_fail (JSON_IS_READER (reader), NULL);
332
333   return reader->priv->error;
334 }
335
336 /**
337  * json_reader_is_array:
338  * @reader: a #JsonReader
339  *
340  * Checks whether the @reader is currently on an array
341  *
342  * Return value: %TRUE if the #JsonReader is on an array, and %FALSE
343  *   otherwise
344  *
345  * Since: 0.12
346  */
347 gboolean
348 json_reader_is_array (JsonReader *reader)
349 {
350   g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
351   json_reader_return_val_if_error_set (reader, FALSE);
352
353   if (reader->priv->current_node == NULL)
354     return FALSE;
355
356   return JSON_NODE_HOLDS_ARRAY (reader->priv->current_node);
357 }
358
359 /**
360  * json_reader_is_object:
361  * @reader: a #JsonReader
362  *
363  * Checks whether the @reader is currently on an object
364  *
365  * Return value: %TRUE if the #JsonReader is on an object, and %FALSE
366  *   otherwise
367  *
368  * Since: 0.12
369  */
370 gboolean
371 json_reader_is_object (JsonReader *reader)
372 {
373   g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
374   json_reader_return_val_if_error_set (reader, FALSE);
375
376   if (reader->priv->current_node == NULL)
377     return FALSE;
378
379   return JSON_NODE_HOLDS_OBJECT (reader->priv->current_node);
380 }
381
382 /**
383  * json_reader_is_value:
384  * @reader: a #JsonReader
385  *
386  * Checks whether the @reader is currently on a value
387  *
388  * Return value: %TRUE if the #JsonReader is on a value, and %FALSE
389  *   otherwise
390  *
391  * Since: 0.12
392  */
393 gboolean
394 json_reader_is_value (JsonReader *reader)
395 {
396   g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
397   json_reader_return_val_if_error_set (reader, FALSE);
398
399   if (reader->priv->current_node == NULL)
400     return FALSE;
401
402   return JSON_NODE_HOLDS_VALUE (reader->priv->current_node) ||
403          JSON_NODE_HOLDS_NULL (reader->priv->current_node);
404 }
405
406 /**
407  * json_reader_read_element:
408  * @reader: a #JsonReader
409  * @index_: the index of the element
410  *
411  * Advances the cursor of @reader to the element @index_ of the array
412  * or the object at the current position.
413  *
414  * You can use the json_reader_get_value* family of functions to retrieve
415  * the value of the element; for instance:
416  *
417  * |[
418  * json_reader_read_element (reader, 0);
419  * int_value = json_reader_get_int_value (reader);
420  * ]|
421  *
422  * After reading the value, json_reader_end_element() should be called to
423  * reposition the cursor inside the #JsonReader, e.g.:
424  *
425  * |[
426  * json_reader_read_element (reader, 1);
427  * str_value = json_reader_get_string_value (reader);
428  * json_reader_end_element (reader);
429  *
430  * json_reader_read_element (reader, 2);
431  * str_value = json_reader_get_string_value (reader);
432  * json_reader_end_element (reader);
433  * ]|
434  *
435  * If @reader is not currently on an array or an object, or if the @index_ is
436  * bigger than the size of the array or the object, the #JsonReader will be
437  * put in an error state until json_reader_end_element() is called. This means
438  * that if used conditionally, json_reader_end_element() must be called on both
439  * code paths:
440  *
441  * |[
442  * if (!json_reader_read_element (reader, 1))
443  *   {
444  *     json_reader_end_element (reader);
445  *     g_set_error (error, â€¦);
446  *     return FALSE;
447  *   }
448  *
449  * str_value = json_reader_get_string_value (reader);
450  * json_reader_end_element (reader);
451  * ]|
452  *
453  * Return value: %TRUE on success, and %FALSE otherwise
454  *
455  * Since: 0.12
456  */
457 gboolean
458 json_reader_read_element (JsonReader *reader,
459                           guint       index_)
460 {
461   JsonReaderPrivate *priv;
462
463   g_return_val_if_fail (JSON_READER (reader), FALSE);
464   json_reader_return_val_if_error_set (reader, FALSE);
465
466   priv = reader->priv;
467
468   if (priv->current_node == NULL)
469     priv->current_node = priv->root;
470
471   if (!(JSON_NODE_HOLDS_ARRAY (priv->current_node) ||
472         JSON_NODE_HOLDS_OBJECT (priv->current_node)))
473     return json_reader_set_error (reader, JSON_READER_ERROR_NO_ARRAY,
474                                   _("The current node is of type '%s', but "
475                                     "an array or an object was expected."),
476                                   json_node_type_name (priv->current_node));
477
478   switch (json_node_get_node_type (priv->current_node))
479     {
480     case JSON_NODE_ARRAY:
481       {
482         JsonArray *array = json_node_get_array (priv->current_node);
483
484         if (index_ >= json_array_get_length (array))
485           return json_reader_set_error (reader, JSON_READER_ERROR_INVALID_INDEX,
486                                         _("The index '%d' is greater than the size "
487                                           "of the array at the current position."),
488                                         index_);
489
490         priv->previous_node = priv->current_node;
491         priv->current_node = json_array_get_element (array, index_);
492       }
493       break;
494
495     case JSON_NODE_OBJECT:
496       {
497         JsonObject *object = json_node_get_object (priv->current_node);
498         GList *members;
499         const gchar *name;
500
501         if (index_ >= json_object_get_size (object))
502           return json_reader_set_error (reader, JSON_READER_ERROR_INVALID_INDEX,
503                                         _("The index '%d' is greater than the size "
504                                           "of the object at the current position."),
505                                         index_);
506
507         priv->previous_node = priv->current_node;
508
509         members = json_object_get_members (object);
510         name = g_list_nth_data (members, index_);
511
512         priv->current_node = json_object_get_member (object, name);
513         g_ptr_array_add (priv->members, g_strdup (name));
514
515         g_list_free (members);
516       }
517       break;
518
519     default:
520       g_assert_not_reached ();
521       return FALSE;
522     }
523
524   return TRUE;
525 }
526
527 /**
528  * json_reader_end_element:
529  * @reader: a #JsonReader
530  *
531  * Moves the cursor back to the previous node after being positioned
532  * inside an array
533  *
534  * This function resets the error state of @reader, if any was set
535  *
536  * Since: 0.12
537  */
538 void
539 json_reader_end_element (JsonReader *reader)
540 {
541   JsonReaderPrivate *priv;
542   JsonNode *tmp;
543
544   g_return_if_fail (JSON_IS_READER (reader));
545
546   if (json_reader_unset_error (reader))
547     return;
548
549   priv = reader->priv;
550
551   if (priv->previous_node != NULL)
552     tmp = json_node_get_parent (priv->previous_node);
553   else
554     tmp = NULL;
555
556   if (json_node_get_node_type (priv->previous_node) == JSON_NODE_OBJECT)
557     g_ptr_array_remove_index (priv->members, priv->members->len - 1);
558
559   priv->current_node = priv->previous_node;
560   priv->previous_node = tmp;
561 }
562
563 /**
564  * json_reader_count_elements:
565  * @reader: a #JsonReader
566  *
567  * Counts the elements of the current position, if @reader is
568  * positioned on an array
569  *
570  * Return value: the number of elements, or -1. In case of failure
571  *   the #JsonReader is set in an error state
572  *
573  * Since: 0.12
574  */
575 gint
576 json_reader_count_elements (JsonReader *reader)
577 {
578   JsonReaderPrivate *priv;
579
580   g_return_val_if_fail (JSON_IS_READER (reader), -1);
581
582   priv = reader->priv;
583
584   if (priv->current_node == NULL)
585     {
586       json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
587                              _("No node available at the current position"));
588       return -1;
589     }
590
591   if (!JSON_NODE_HOLDS_ARRAY (priv->current_node))
592     {
593       json_reader_set_error (reader, JSON_READER_ERROR_NO_ARRAY,
594                              _("The current position holds a '%s' and not an array"),
595                              json_node_type_get_name (JSON_NODE_TYPE (priv->current_node)));
596       return -1;
597     }
598
599   return json_array_get_length (json_node_get_array (priv->current_node));
600 }
601
602 /**
603  * json_reader_read_member:
604  * @reader: a #JsonReader
605  * @member_name: the name of the member to read
606  *
607  * Advances the cursor of @reader to the @member_name of the object at the
608  * current position.
609  *
610  * You can use the json_reader_get_value* family of functions to retrieve
611  * the value of the member; for instance:
612  *
613  * |[
614  * json_reader_read_member (reader, "width");
615  * width = json_reader_get_int_value (reader);
616  * ]|
617  *
618  * After reading the value, json_reader_end_member() should be called to
619  * reposition the cursor inside the #JsonReader, e.g.:
620  *
621  * |[
622  * json_reader_read_member (reader, "author");
623  * author = json_reader_get_string_value (reader);
624  * json_reader_end_member (reader);
625  *
626  * json_reader_read_member (reader, "title");
627  * title = json_reader_get_string_value (reader);
628  * json_reader_end_member (reader);
629  * ]|
630  *
631  * If @reader is not currently on an object, or if the @member_name is not
632  * defined in the object, the #JsonReader will be put in an error state until
633  * json_reader_end_member() is called. This means that if used conditionally,
634  * json_reader_end_member() must be called on both code paths:
635  *
636  * |[
637  * if (!json_reader_read_member (reader, "title"))
638  *   {
639  *     json_reader_end_member (reader);
640  *     g_set_error (error, â€¦);
641  *     return FALSE;
642  *   }
643  *
644  * str_value = json_reader_get_string_value (reader);
645  * json_reader_end_member (reader);
646  * ]|
647  *
648  * Return value: %TRUE on success, and %FALSE otherwise
649  *
650  * Since: 0.12
651  */
652 gboolean
653 json_reader_read_member (JsonReader  *reader,
654                          const gchar *member_name)
655 {
656   JsonReaderPrivate *priv;
657   JsonObject *object;
658
659   g_return_val_if_fail (JSON_READER (reader), FALSE);
660   g_return_val_if_fail (member_name != NULL, FALSE);
661   json_reader_return_val_if_error_set (reader, FALSE);
662
663   priv = reader->priv;
664
665   if (priv->current_node == NULL)
666     priv->current_node = priv->root;
667
668   if (!JSON_NODE_HOLDS_OBJECT (priv->current_node))
669     return json_reader_set_error (reader, JSON_READER_ERROR_NO_OBJECT,
670                                   _("The current node is of type '%s', but "
671                                     "an object was expected."),
672                                   json_node_type_name (priv->current_node));
673
674   object = json_node_get_object (priv->current_node);
675   if (!json_object_has_member (object, member_name))
676     return json_reader_set_error (reader, JSON_READER_ERROR_INVALID_MEMBER,
677                                   _("The member '%s' is not defined in the "
678                                     "object at the current position."),
679                                   member_name);
680
681   priv->previous_node = priv->current_node;
682   priv->current_node = json_object_get_member (object, member_name);
683   g_ptr_array_add (priv->members, g_strdup (member_name));
684
685   return TRUE;
686 }
687
688 /**
689  * json_reader_end_member:
690  * @reader: a #JsonReader
691  *
692  * Moves the cursor back to the previous node after being positioned
693  * inside an object
694  *
695  * This function resets the error state of @reader, if any was set
696  *
697  * Since: 0.12
698  */
699 void
700 json_reader_end_member (JsonReader *reader)
701 {
702   JsonReaderPrivate *priv;
703   JsonNode *tmp;
704
705   g_return_if_fail (JSON_IS_READER (reader));
706
707   if (json_reader_unset_error (reader))
708     return;
709
710   priv = reader->priv;
711
712   if (priv->previous_node != NULL)
713     tmp = json_node_get_parent (priv->previous_node);
714   else
715     tmp = NULL;
716
717   g_ptr_array_remove_index (priv->members, priv->members->len - 1);
718
719   priv->current_node = priv->previous_node;
720   priv->previous_node = tmp;
721 }
722
723 /**
724  * json_reader_list_members:
725  * @reader: a #JsonReader
726  *
727  * Retrieves a list of member names from the current position, if @reader
728  * is positioned on an object.
729  *
730  * Return value: (transfer full): a newly allocated, %NULL-terminated
731  *   array of strings holding the members name. Use g_strfreev() when
732  *   done.
733  *
734  * Since: 0.14
735  */
736 gchar **
737 json_reader_list_members (JsonReader *reader)
738 {
739   JsonReaderPrivate *priv;
740   GList *members, *l;
741   gchar **retval;
742   gint i;
743
744   g_return_val_if_fail (JSON_IS_READER (reader), NULL);
745
746   priv = reader->priv;
747
748   if (priv->current_node == NULL)
749     {
750       json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
751                              _("No node available at the current position"));
752       return NULL;
753     }
754
755   if (!JSON_NODE_HOLDS_OBJECT (priv->current_node))
756     {
757       json_reader_set_error (reader, JSON_READER_ERROR_NO_OBJECT,
758                              _("The current position holds a '%s' and not an object"),
759                              json_node_type_get_name (JSON_NODE_TYPE (priv->current_node)));
760       return NULL;
761     }
762
763   members = json_object_get_members (json_node_get_object (priv->current_node));
764   if (members == NULL)
765     return NULL;
766
767   retval = g_new (gchar*, g_list_length (members) + 1);
768   for (l = members, i = 0; l != NULL; l = l->next, i += 1)
769     retval[i] = g_strdup (l->data);
770
771   retval[i] = NULL;
772
773   g_list_free (members);
774
775   return retval;
776 }
777
778 /**
779  * json_reader_count_members:
780  * @reader: a #JsonReader
781  *
782  * Counts the members of the current position, if @reader is
783  * positioned on an object
784  *
785  * Return value: the number of members, or -1. In case of failure
786  *   the #JsonReader is set in an error state
787  *
788  * Since: 0.12
789  */
790 gint
791 json_reader_count_members (JsonReader *reader)
792 {
793   JsonReaderPrivate *priv;
794
795   g_return_val_if_fail (JSON_IS_READER (reader), -1);
796
797   priv = reader->priv;
798
799   if (priv->current_node == NULL)
800     {
801       json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
802                              _("No node available at the current position"));
803       return -1;
804     }
805
806   if (!JSON_NODE_HOLDS_OBJECT (priv->current_node))
807     {
808       json_reader_set_error (reader, JSON_READER_ERROR_NO_OBJECT,
809                              _("The current position holds a '%s' and not an object"),
810                              json_node_type_get_name (JSON_NODE_TYPE (priv->current_node)));
811       return -1;
812     }
813
814   return json_object_get_size (json_node_get_object (priv->current_node));
815 }
816
817 /**
818  * json_reader_get_value:
819  * @reader: a #JsonReader
820  *
821  * Retrieves the #JsonNode of the current position of @reader
822  *
823  * Return value: (transfer none): a #JsonNode, or %NULL. The returned node
824  *   is owned by the #JsonReader and it should not be modified or freed
825  *   directly
826  *
827  * Since: 0.12
828  */
829 JsonNode *
830 json_reader_get_value (JsonReader *reader)
831 {
832   JsonNode *node;
833
834   g_return_val_if_fail (JSON_IS_READER (reader), NULL);
835   json_reader_return_val_if_error_set (reader, NULL);
836
837   if (reader->priv->current_node == NULL)
838     {
839       json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
840                              _("No node available at the current position"));
841       return NULL;
842     }
843
844   node = reader->priv->current_node;
845
846   if (!JSON_NODE_HOLDS_VALUE (node))
847     {
848       json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
849                              _("The current position holds a '%s' and not a value"),
850                              json_node_type_get_name (JSON_NODE_TYPE (node)));
851       return NULL;
852     }
853
854   return reader->priv->current_node;
855 }
856
857 /**
858  * json_reader_get_int_value:
859  * @reader: a #JsonReader
860  *
861  * Retrieves the integer value of the current position of @reader
862  *
863  * Return value: the integer value
864  *
865  * Since: 0.12
866  */
867 gint64
868 json_reader_get_int_value (JsonReader *reader)
869 {
870   JsonNode *node;
871
872   g_return_val_if_fail (JSON_IS_READER (reader), 0);
873   json_reader_return_val_if_error_set (reader, 0);
874
875   if (reader->priv->current_node == NULL)
876     {
877       json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
878                              _("No node available at the current position"));
879       return 0;
880     }
881
882   node = reader->priv->current_node;
883
884   if (!JSON_NODE_HOLDS_VALUE (node))
885     {
886       json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
887                              _("The current position holds a '%s' and not a value"),
888                              json_node_type_get_name (JSON_NODE_TYPE (node)));
889       return 0;
890     }
891
892   return json_node_get_int (reader->priv->current_node);
893 }
894
895 /**
896  * json_reader_get_double_value:
897  * @reader: a #JsonReader
898  *
899  * Retrieves the floating point value of the current position of @reader
900  *
901  * Return value: the floating point value
902  *
903  * Since: 0.12
904  */
905 gdouble
906 json_reader_get_double_value (JsonReader *reader)
907 {
908   JsonNode *node;
909
910   g_return_val_if_fail (JSON_IS_READER (reader), 0.0);
911   json_reader_return_val_if_error_set (reader, 0.0);
912
913   if (reader->priv->current_node == NULL)
914     {
915       json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
916                              _("No node available at the current position"));
917       return 0.0;
918     }
919
920   node = reader->priv->current_node;
921
922   if (!JSON_NODE_HOLDS_VALUE (node))
923     {
924       json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
925                              _("The current position holds a '%s' and not a value"),
926                              json_node_type_get_name (JSON_NODE_TYPE (node)));
927       return 0.0;
928     }
929
930   return json_node_get_double (reader->priv->current_node);
931 }
932
933 /**
934  * json_reader_get_string_value:
935  * @reader: a #JsonReader
936  *
937  * Retrieves the string value of the current position of @reader
938  *
939  * Return value: the string value
940  *
941  * Since: 0.12
942  */
943 const gchar *
944 json_reader_get_string_value (JsonReader *reader)
945 {
946   JsonNode *node;
947
948   g_return_val_if_fail (JSON_IS_READER (reader), NULL);
949   json_reader_return_val_if_error_set (reader, NULL);
950
951   if (reader->priv->current_node == NULL)
952     {
953       json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
954                              _("No node available at the current position"));
955       return NULL;
956     }
957
958   node = reader->priv->current_node;
959
960   if (!JSON_NODE_HOLDS_VALUE (node))
961     {
962       json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
963                              _("The current position holds a '%s' and not a value"),
964                              json_node_type_get_name (JSON_NODE_TYPE (node)));
965       return NULL;
966     }
967
968   if (json_node_get_value_type (node) != G_TYPE_STRING)
969     {
970       json_reader_set_error (reader, JSON_READER_ERROR_INVALID_TYPE,
971                              _("The current position does not hold a string type"));
972       return NULL;
973     }
974
975   return json_node_get_string (reader->priv->current_node);
976 }
977
978 /**
979  * json_reader_get_boolean_value:
980  * @reader: a #JsonReader
981  *
982  * Retrieves the boolean value of the current position of @reader
983  *
984  * Return value: the boolean value
985  *
986  * Since: 0.12
987  */
988 gboolean
989 json_reader_get_boolean_value (JsonReader *reader)
990 {
991   JsonNode *node;
992
993   g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
994   json_reader_return_val_if_error_set (reader, FALSE);
995
996   if (reader->priv->current_node == NULL)
997     {
998       json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
999                              _("No node available at the current position"));
1000       return FALSE;
1001     }
1002
1003   node = reader->priv->current_node;
1004
1005   if (!JSON_NODE_HOLDS_VALUE (node))
1006     {
1007       json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
1008                              _("The current position holds a '%s' and not a value"),
1009                              json_node_type_get_name (JSON_NODE_TYPE (node)));
1010       return FALSE;
1011     }
1012
1013   return json_node_get_boolean (node);
1014 }
1015
1016 /**
1017  * json_reader_get_null_value:
1018  * @reader: a #JsonReader
1019  *
1020  * Checks whether the value of the current position of @reader is 'null'
1021  *
1022  * Return value: %TRUE if 'null' is set, and %FALSE otherwise
1023  *
1024  * Since: 0.12
1025  */
1026 gboolean
1027 json_reader_get_null_value (JsonReader *reader)
1028 {
1029   g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
1030   json_reader_return_val_if_error_set (reader, FALSE);
1031
1032   if (reader->priv->current_node == NULL)
1033     {
1034       json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
1035                              _("No node available at the current position"));
1036       return FALSE;
1037     }
1038
1039   return JSON_NODE_HOLDS_NULL (reader->priv->current_node);
1040 }
1041
1042 /**
1043  * json_reader_get_member_name:
1044  * @reader: a #JsonReader
1045  *
1046  * Retrieves the name of the current member.
1047  *
1048  * Return value: (transfer none): the name of the member, or %NULL
1049  *
1050  * Since: 0.14
1051  */
1052 const gchar *
1053 json_reader_get_member_name (JsonReader *reader)
1054 {
1055   g_return_val_if_fail (JSON_IS_READER (reader), NULL);
1056   json_reader_return_val_if_error_set (reader, NULL);
1057
1058   if (reader->priv->current_node == NULL)
1059     {
1060       json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
1061                              _("No node available at the current position"));
1062       return NULL;
1063     }
1064
1065   if (reader->priv->members->len == 0)
1066     return NULL;
1067
1068   return g_ptr_array_index (reader->priv->members,
1069                             reader->priv->members->len - 1);
1070 }