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
G_DEFINE_TYPE_WITH_PRIVATE(JsonReader,json_reader,G_TYPE_OBJECT)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
json_reader_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * pspec)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
json_reader_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * pspec)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
json_reader_class_init(JsonReaderClass * klass)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
json_reader_init(JsonReader * self)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 *
json_reader_new(JsonNode * node)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
json_reader_unset_error(JsonReader * reader)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
json_reader_set_root(JsonReader * reader,JsonNode * root)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
json_reader_set_error(JsonReader * reader,JsonReaderError error_code,const gchar * error_fmt,...)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: (nullable) (transfer none): the pointer to the error, or %NULL
325 *
326 * Since: 0.12
327 */
328 const GError *
json_reader_get_error(JsonReader * reader)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
json_reader_is_array(JsonReader * reader)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
json_reader_is_object(JsonReader * reader)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
json_reader_is_value(JsonReader * reader)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
json_reader_read_element(JsonReader * reader,guint index_)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 GQueue *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_internal (object);
510 name = g_queue_peek_nth (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 break;
516
517 default:
518 g_assert_not_reached ();
519 return FALSE;
520 }
521
522 return TRUE;
523 }
524
525 /**
526 * json_reader_end_element:
527 * @reader: a #JsonReader
528 *
529 * Moves the cursor back to the previous node after being positioned
530 * inside an array
531 *
532 * This function resets the error state of @reader, if any was set
533 *
534 * Since: 0.12
535 */
536 void
json_reader_end_element(JsonReader * reader)537 json_reader_end_element (JsonReader *reader)
538 {
539 JsonReaderPrivate *priv;
540 JsonNode *tmp;
541
542 g_return_if_fail (JSON_IS_READER (reader));
543
544 if (json_reader_unset_error (reader))
545 return;
546
547 priv = reader->priv;
548
549 if (priv->previous_node != NULL)
550 tmp = json_node_get_parent (priv->previous_node);
551 else
552 tmp = NULL;
553
554 if (json_node_get_node_type (priv->previous_node) == JSON_NODE_OBJECT)
555 g_ptr_array_remove_index (priv->members, priv->members->len - 1);
556
557 priv->current_node = priv->previous_node;
558 priv->previous_node = tmp;
559 }
560
561 /**
562 * json_reader_count_elements:
563 * @reader: a #JsonReader
564 *
565 * Counts the elements of the current position, if @reader is
566 * positioned on an array
567 *
568 * Return value: the number of elements, or -1. In case of failure
569 * the #JsonReader is set in an error state
570 *
571 * Since: 0.12
572 */
573 gint
json_reader_count_elements(JsonReader * reader)574 json_reader_count_elements (JsonReader *reader)
575 {
576 JsonReaderPrivate *priv;
577
578 g_return_val_if_fail (JSON_IS_READER (reader), -1);
579
580 priv = reader->priv;
581
582 if (priv->current_node == NULL)
583 {
584 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
585 _("No node available at the current position"));
586 return -1;
587 }
588
589 if (!JSON_NODE_HOLDS_ARRAY (priv->current_node))
590 {
591 json_reader_set_error (reader, JSON_READER_ERROR_NO_ARRAY,
592 _("The current position holds a “%s” and not an array"),
593 json_node_type_get_name (JSON_NODE_TYPE (priv->current_node)));
594 return -1;
595 }
596
597 return json_array_get_length (json_node_get_array (priv->current_node));
598 }
599
600 /**
601 * json_reader_read_member:
602 * @reader: a #JsonReader
603 * @member_name: the name of the member to read
604 *
605 * Advances the cursor of @reader to the @member_name of the object at the
606 * current position.
607 *
608 * You can use the json_reader_get_value* family of functions to retrieve
609 * the value of the member; for instance:
610 *
611 * |[
612 * json_reader_read_member (reader, "width");
613 * width = json_reader_get_int_value (reader);
614 * ]|
615 *
616 * After reading the value, json_reader_end_member() should be called to
617 * reposition the cursor inside the #JsonReader, e.g.:
618 *
619 * |[
620 * json_reader_read_member (reader, "author");
621 * author = json_reader_get_string_value (reader);
622 * json_reader_end_member (reader);
623 *
624 * json_reader_read_member (reader, "title");
625 * title = json_reader_get_string_value (reader);
626 * json_reader_end_member (reader);
627 * ]|
628 *
629 * If @reader is not currently on an object, or if the @member_name is not
630 * defined in the object, the #JsonReader will be put in an error state until
631 * json_reader_end_member() is called. This means that if used conditionally,
632 * json_reader_end_member() must be called on both code paths:
633 *
634 * |[
635 * if (!json_reader_read_member (reader, "title"))
636 * {
637 * json_reader_end_member (reader);
638 * g_set_error (error, …);
639 * return FALSE;
640 * }
641 *
642 * str_value = json_reader_get_string_value (reader);
643 * json_reader_end_member (reader);
644 * ]|
645 *
646 * Return value: %TRUE on success, and %FALSE otherwise
647 *
648 * Since: 0.12
649 */
650 gboolean
json_reader_read_member(JsonReader * reader,const gchar * member_name)651 json_reader_read_member (JsonReader *reader,
652 const gchar *member_name)
653 {
654 JsonReaderPrivate *priv;
655 JsonObject *object;
656
657 g_return_val_if_fail (JSON_READER (reader), FALSE);
658 g_return_val_if_fail (member_name != NULL, FALSE);
659 json_reader_return_val_if_error_set (reader, FALSE);
660
661 priv = reader->priv;
662
663 if (priv->current_node == NULL)
664 priv->current_node = priv->root;
665
666 if (!JSON_NODE_HOLDS_OBJECT (priv->current_node))
667 return json_reader_set_error (reader, JSON_READER_ERROR_NO_OBJECT,
668 _("The current node is of type “%s”, but "
669 "an object was expected."),
670 json_node_type_name (priv->current_node));
671
672 object = json_node_get_object (priv->current_node);
673 if (!json_object_has_member (object, member_name))
674 return json_reader_set_error (reader, JSON_READER_ERROR_INVALID_MEMBER,
675 _("The member “%s” is not defined in the "
676 "object at the current position."),
677 member_name);
678
679 priv->previous_node = priv->current_node;
680 priv->current_node = json_object_get_member (object, member_name);
681 g_ptr_array_add (priv->members, g_strdup (member_name));
682
683 return TRUE;
684 }
685
686 /**
687 * json_reader_end_member:
688 * @reader: a #JsonReader
689 *
690 * Moves the cursor back to the previous node after being positioned
691 * inside an object
692 *
693 * This function resets the error state of @reader, if any was set
694 *
695 * Since: 0.12
696 */
697 void
json_reader_end_member(JsonReader * reader)698 json_reader_end_member (JsonReader *reader)
699 {
700 JsonReaderPrivate *priv;
701 JsonNode *tmp;
702
703 g_return_if_fail (JSON_IS_READER (reader));
704
705 if (json_reader_unset_error (reader))
706 return;
707
708 priv = reader->priv;
709
710 if (priv->previous_node != NULL)
711 tmp = json_node_get_parent (priv->previous_node);
712 else
713 tmp = NULL;
714
715 g_ptr_array_remove_index (priv->members, priv->members->len - 1);
716
717 priv->current_node = priv->previous_node;
718 priv->previous_node = tmp;
719 }
720
721 /**
722 * json_reader_list_members:
723 * @reader: a #JsonReader
724 *
725 * Retrieves a list of member names from the current position, if @reader
726 * is positioned on an object.
727 *
728 * Return value: (transfer full): a newly allocated, %NULL-terminated
729 * array of strings holding the members name. Use g_strfreev() when
730 * done.
731 *
732 * Since: 0.14
733 */
734 gchar **
json_reader_list_members(JsonReader * reader)735 json_reader_list_members (JsonReader *reader)
736 {
737 JsonReaderPrivate *priv;
738 JsonObject *object;
739 GQueue *members;
740 GList *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 object = json_node_get_object (priv->current_node);
764 members = json_object_get_members_internal (object);
765
766 retval = g_new (gchar*, g_queue_get_length (members) + 1);
767 for (l = members->head, i = 0; l != NULL; l = l->next, i += 1)
768 retval[i] = g_strdup (l->data);
769
770 retval[i] = NULL;
771
772 return retval;
773 }
774
775 /**
776 * json_reader_count_members:
777 * @reader: a #JsonReader
778 *
779 * Counts the members of the current position, if @reader is
780 * positioned on an object
781 *
782 * Return value: the number of members, or -1. In case of failure
783 * the #JsonReader is set in an error state
784 *
785 * Since: 0.12
786 */
787 gint
json_reader_count_members(JsonReader * reader)788 json_reader_count_members (JsonReader *reader)
789 {
790 JsonReaderPrivate *priv;
791
792 g_return_val_if_fail (JSON_IS_READER (reader), -1);
793
794 priv = reader->priv;
795
796 if (priv->current_node == NULL)
797 {
798 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
799 _("No node available at the current position"));
800 return -1;
801 }
802
803 if (!JSON_NODE_HOLDS_OBJECT (priv->current_node))
804 {
805 json_reader_set_error (reader, JSON_READER_ERROR_NO_OBJECT,
806 _("The current position holds a “%s” and not an object"),
807 json_node_type_get_name (JSON_NODE_TYPE (priv->current_node)));
808 return -1;
809 }
810
811 return json_object_get_size (json_node_get_object (priv->current_node));
812 }
813
814 /**
815 * json_reader_get_value:
816 * @reader: a #JsonReader
817 *
818 * Retrieves the #JsonNode of the current position of @reader
819 *
820 * Return value: (nullable) (transfer none): a #JsonNode, or %NULL. The
821 * returned node is owned by the #JsonReader and it should not be
822 * modified or freed directly
823 *
824 * Since: 0.12
825 */
826 JsonNode *
json_reader_get_value(JsonReader * reader)827 json_reader_get_value (JsonReader *reader)
828 {
829 JsonNode *node;
830
831 g_return_val_if_fail (JSON_IS_READER (reader), NULL);
832 json_reader_return_val_if_error_set (reader, NULL);
833
834 if (reader->priv->current_node == NULL)
835 {
836 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
837 _("No node available at the current position"));
838 return NULL;
839 }
840
841 node = reader->priv->current_node;
842
843 if (!JSON_NODE_HOLDS_VALUE (node) && !JSON_NODE_HOLDS_NULL (node))
844 {
845 json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
846 _("The current position holds a “%s” and not a value"),
847 json_node_type_get_name (JSON_NODE_TYPE (node)));
848 return NULL;
849 }
850
851 return reader->priv->current_node;
852 }
853
854 /**
855 * json_reader_get_int_value:
856 * @reader: a #JsonReader
857 *
858 * Retrieves the integer value of the current position of @reader
859 *
860 * Return value: the integer value
861 *
862 * Since: 0.12
863 */
864 gint64
json_reader_get_int_value(JsonReader * reader)865 json_reader_get_int_value (JsonReader *reader)
866 {
867 JsonNode *node;
868
869 g_return_val_if_fail (JSON_IS_READER (reader), 0);
870 json_reader_return_val_if_error_set (reader, 0);
871
872 if (reader->priv->current_node == NULL)
873 {
874 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
875 _("No node available at the current position"));
876 return 0;
877 }
878
879 node = reader->priv->current_node;
880
881 if (!JSON_NODE_HOLDS_VALUE (node))
882 {
883 json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
884 _("The current position holds a “%s” and not a value"),
885 json_node_type_get_name (JSON_NODE_TYPE (node)));
886 return 0;
887 }
888
889 return json_node_get_int (reader->priv->current_node);
890 }
891
892 /**
893 * json_reader_get_double_value:
894 * @reader: a #JsonReader
895 *
896 * Retrieves the floating point value of the current position of @reader
897 *
898 * Return value: the floating point value
899 *
900 * Since: 0.12
901 */
902 gdouble
json_reader_get_double_value(JsonReader * reader)903 json_reader_get_double_value (JsonReader *reader)
904 {
905 JsonNode *node;
906
907 g_return_val_if_fail (JSON_IS_READER (reader), 0.0);
908 json_reader_return_val_if_error_set (reader, 0.0);
909
910 if (reader->priv->current_node == NULL)
911 {
912 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
913 _("No node available at the current position"));
914 return 0.0;
915 }
916
917 node = reader->priv->current_node;
918
919 if (!JSON_NODE_HOLDS_VALUE (node))
920 {
921 json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
922 _("The current position holds a “%s” and not a value"),
923 json_node_type_get_name (JSON_NODE_TYPE (node)));
924 return 0.0;
925 }
926
927 return json_node_get_double (reader->priv->current_node);
928 }
929
930 /**
931 * json_reader_get_string_value:
932 * @reader: a #JsonReader
933 *
934 * Retrieves the string value of the current position of @reader
935 *
936 * Return value: the string value
937 *
938 * Since: 0.12
939 */
940 const gchar *
json_reader_get_string_value(JsonReader * reader)941 json_reader_get_string_value (JsonReader *reader)
942 {
943 JsonNode *node;
944
945 g_return_val_if_fail (JSON_IS_READER (reader), NULL);
946 json_reader_return_val_if_error_set (reader, NULL);
947
948 if (reader->priv->current_node == NULL)
949 {
950 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
951 _("No node available at the current position"));
952 return NULL;
953 }
954
955 node = reader->priv->current_node;
956
957 if (!JSON_NODE_HOLDS_VALUE (node))
958 {
959 json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
960 _("The current position holds a “%s” and not a value"),
961 json_node_type_get_name (JSON_NODE_TYPE (node)));
962 return NULL;
963 }
964
965 if (json_node_get_value_type (node) != G_TYPE_STRING)
966 {
967 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_TYPE,
968 _("The current position does not hold a string type"));
969 return NULL;
970 }
971
972 return json_node_get_string (reader->priv->current_node);
973 }
974
975 /**
976 * json_reader_get_boolean_value:
977 * @reader: a #JsonReader
978 *
979 * Retrieves the boolean value of the current position of @reader
980 *
981 * Return value: the boolean value
982 *
983 * Since: 0.12
984 */
985 gboolean
json_reader_get_boolean_value(JsonReader * reader)986 json_reader_get_boolean_value (JsonReader *reader)
987 {
988 JsonNode *node;
989
990 g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
991 json_reader_return_val_if_error_set (reader, FALSE);
992
993 if (reader->priv->current_node == NULL)
994 {
995 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
996 _("No node available at the current position"));
997 return FALSE;
998 }
999
1000 node = reader->priv->current_node;
1001
1002 if (!JSON_NODE_HOLDS_VALUE (node))
1003 {
1004 json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
1005 _("The current position holds a “%s” and not a value"),
1006 json_node_type_get_name (JSON_NODE_TYPE (node)));
1007 return FALSE;
1008 }
1009
1010 return json_node_get_boolean (node);
1011 }
1012
1013 /**
1014 * json_reader_get_null_value:
1015 * @reader: a #JsonReader
1016 *
1017 * Checks whether the value of the current position of @reader is 'null'
1018 *
1019 * Return value: %TRUE if 'null' is set, and %FALSE otherwise
1020 *
1021 * Since: 0.12
1022 */
1023 gboolean
json_reader_get_null_value(JsonReader * reader)1024 json_reader_get_null_value (JsonReader *reader)
1025 {
1026 g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
1027 json_reader_return_val_if_error_set (reader, FALSE);
1028
1029 if (reader->priv->current_node == NULL)
1030 {
1031 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
1032 _("No node available at the current position"));
1033 return FALSE;
1034 }
1035
1036 return JSON_NODE_HOLDS_NULL (reader->priv->current_node);
1037 }
1038
1039 /**
1040 * json_reader_get_member_name:
1041 * @reader: a #JsonReader
1042 *
1043 * Retrieves the name of the current member.
1044 *
1045 * Return value: (nullable) (transfer none): the name of the member, or %NULL
1046 *
1047 * Since: 0.14
1048 */
1049 const gchar *
json_reader_get_member_name(JsonReader * reader)1050 json_reader_get_member_name (JsonReader *reader)
1051 {
1052 g_return_val_if_fail (JSON_IS_READER (reader), NULL);
1053 json_reader_return_val_if_error_set (reader, NULL);
1054
1055 if (reader->priv->current_node == NULL)
1056 {
1057 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
1058 _("No node available at the current position"));
1059 return NULL;
1060 }
1061
1062 if (reader->priv->members->len == 0)
1063 return NULL;
1064
1065 return g_ptr_array_index (reader->priv->members,
1066 reader->priv->members->len - 1);
1067 }
1068