1 /* json-node.c - JSON object model node
2  *
3  * This file is part of JSON-GLib
4  * Copyright (C) 2007  OpenedHand Ltd.
5  * Copyright (C) 2009  Intel Corp.
6  * Copyright (C) 2015  Collabora Ltd.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20  *
21  * Author:
22  *   Emmanuele Bassi  <ebassi@linux.intel.com>
23  *   Philip Withnall  <philip.withnall@collabora.co.uk>
24  */
25 
26 #include "config.h"
27 
28 #include <glib.h>
29 
30 #include "json-types.h"
31 #include "json-types-private.h"
32 #include "json-debug.h"
33 
34 /**
35  * SECTION:json-node
36  * @short_description: Node in a JSON object model
37  *
38  * A #JsonNode is a generic container of elements inside a JSON stream.
39  * It can contain fundamental types (integers, booleans, floating point
40  * numbers, strings) and complex types (arrays and objects).
41  *
42  * When parsing a JSON data stream you extract the root node and walk
43  * the node tree by retrieving the type of data contained inside the
44  * node with the %JSON_NODE_TYPE macro. If the node contains a fundamental
45  * type you can retrieve a copy of the #GValue holding it with the
46  * json_node_get_value() function, and then use the #GValue API to extract
47  * the data; if the node contains a complex type you can retrieve the
48  * #JsonObject or the #JsonArray using json_node_get_object() or
49  * json_node_get_array() respectively, and then retrieve the nodes
50  * they contain.
51  *
52  * A #JsonNode may be marked as immutable using json_node_seal(). This marks the
53  * node and all its descendents as read-only, and means that subsequent calls to
54  * setter functions (such as json_node_set_array()) on them will abort as a
55  * programmer error. By marking a node tree as immutable, it may be referenced
56  * in multiple places and its hash value cached for fast lookups, without the
57  * possibility of a value deep within the tree changing and affecting hash
58  * values. Immutable #JsonNodes may be passed to functions which retain a
59  * reference to them without needing to take a copy.
60  *
61  * #JsonNode supports two types of memory management: alloc/free semantics, and
62  * ref/unref semantics. The two may be mixed to a limited extent: nodes may be
63  * allocated (which gives them a reference count of 1), referenced zero or more
64  * times, unreferenced exactly that number of times (using json_node_unref()),
65  * then either unreferenced exactly once more or freed (using json_node_free())
66  * to destroy them. json_node_free() must not be used when a node might have a
67  * reference count not equal to 1. To this end, json-glib uses json_node_copy()
68  * and json_node_unref() internally.
69  */
70 
71 G_DEFINE_BOXED_TYPE (JsonNode, json_node, json_node_copy, json_node_unref);
72 
73 /**
74  * json_node_get_value_type:
75  * @node: a #JsonNode
76  *
77  * Returns the #GType of the payload of the node.
78  *
79  * Return value: a #GType for the payload.
80  *
81  * Since: 0.4
82  */
83 GType
json_node_get_value_type(JsonNode * node)84 json_node_get_value_type (JsonNode *node)
85 {
86   g_return_val_if_fail (node != NULL, G_TYPE_INVALID);
87 
88   switch (node->type)
89     {
90     case JSON_NODE_OBJECT:
91       return JSON_TYPE_OBJECT;
92 
93     case JSON_NODE_ARRAY:
94       return JSON_TYPE_ARRAY;
95 
96     case JSON_NODE_NULL:
97       return G_TYPE_INVALID;
98 
99     case JSON_NODE_VALUE:
100       if (node->data.value)
101         return JSON_VALUE_TYPE (node->data.value);
102       else
103         return G_TYPE_INVALID;
104 
105     default:
106       g_assert_not_reached ();
107       return G_TYPE_INVALID;
108     }
109 }
110 
111 /**
112  * json_node_alloc: (constructor)
113  *
114  * Allocates a new #JsonNode. Use json_node_init() and its variants
115  * to initialize the returned value.
116  *
117  * Return value: (transfer full): the newly allocated #JsonNode. Use
118  *   json_node_free() to free the resources allocated by this function
119  *
120  * Since: 0.16
121  */
122 JsonNode *
json_node_alloc(void)123 json_node_alloc (void)
124 {
125   JsonNode *node = NULL;
126 
127   node = g_slice_new0 (JsonNode);
128   node->ref_count = 1;
129   node->allocated = TRUE;
130 
131   return node;
132 }
133 
134 static void
json_node_unset(JsonNode * node)135 json_node_unset (JsonNode *node)
136 {
137   /* Note: Don't use JSON_NODE_IS_VALID here because this may legitimately be
138    * called with (node->ref_count == 0) from json_node_unref(). */
139   g_assert (node != NULL);
140 
141   switch (node->type)
142     {
143     case JSON_NODE_OBJECT:
144       if (node->data.object)
145         json_object_unref (node->data.object);
146       break;
147 
148     case JSON_NODE_ARRAY:
149       if (node->data.array)
150         json_array_unref (node->data.array);
151       break;
152 
153     case JSON_NODE_VALUE:
154       if (node->data.value)
155         json_value_unref (node->data.value);
156       break;
157 
158     case JSON_NODE_NULL:
159       break;
160     }
161 }
162 
163 /**
164  * json_node_init:
165  * @node: the #JsonNode to initialize
166  * @type: the type of JSON node to initialize @node to
167  *
168  * Initializes a @node to a specific @type.
169  *
170  * If the node has already been initialized once, it will be reset to
171  * the given type, and any data contained will be cleared.
172  *
173  * Return value: (transfer none): the initialized #JsonNode
174  *
175  * Since: 0.16
176  */
177 JsonNode *
json_node_init(JsonNode * node,JsonNodeType type)178 json_node_init (JsonNode *node,
179                 JsonNodeType type)
180 {
181   g_return_val_if_fail (type >= JSON_NODE_OBJECT &&
182                         type <= JSON_NODE_NULL, NULL);
183   g_return_val_if_fail (node->ref_count == 1, NULL);
184 
185   json_node_unset (node);
186 
187   node->type = type;
188 
189   return node;
190 }
191 
192 /**
193  * json_node_init_object:
194  * @node: the #JsonNode to initialize
195  * @object: (allow-none): the #JsonObject to initialize @node with, or %NULL
196  *
197  * Initializes @node to %JSON_NODE_OBJECT and sets @object into it.
198  *
199  * This function will take a reference on @object.
200  *
201  * If the node has already been initialized once, it will be reset to
202  * the given type, and any data contained will be cleared.
203  *
204  * Return value: (transfer none): the initialized #JsonNode
205  *
206  * Since: 0.16
207  */
208 JsonNode *
json_node_init_object(JsonNode * node,JsonObject * object)209 json_node_init_object (JsonNode   *node,
210                        JsonObject *object)
211 {
212   g_return_val_if_fail (node != NULL, NULL);
213 
214   json_node_init (node, JSON_NODE_OBJECT);
215   json_node_set_object (node, object);
216 
217   return node;
218 }
219 
220 /**
221  * json_node_init_array:
222  * @node: the #JsonNode to initialize
223  * @array: (allow-none): the #JsonArray to initialize @node with, or %NULL
224  *
225  * Initializes @node to %JSON_NODE_ARRAY and sets @array into it.
226  *
227  * This function will take a reference on @array.
228  *
229  * If the node has already been initialized once, it will be reset to
230  * the given type, and any data contained will be cleared.
231  *
232  * Return value: (transfer none): the initialized #JsonNode
233  *
234  * Since: 0.16
235  */
236 JsonNode *
json_node_init_array(JsonNode * node,JsonArray * array)237 json_node_init_array (JsonNode  *node,
238                       JsonArray *array)
239 {
240   g_return_val_if_fail (node != NULL, NULL);
241 
242   json_node_init (node, JSON_NODE_ARRAY);
243   json_node_set_array (node, array);
244 
245   return node;
246 }
247 
248 /**
249  * json_node_init_int:
250  * @node: the #JsonNode to initialize
251  * @value: an integer
252  *
253  * Initializes @node to %JSON_NODE_VALUE and sets @value into it.
254  *
255  * If the node has already been initialized once, it will be reset to
256  * the given type, and any data contained will be cleared.
257  *
258  * Return value: (transfer none): the initialized #JsonNode
259  *
260  * Since: 0.16
261  */
262 JsonNode *
json_node_init_int(JsonNode * node,gint64 value)263 json_node_init_int (JsonNode *node,
264                     gint64    value)
265 {
266   g_return_val_if_fail (node != NULL, NULL);
267 
268   json_node_init (node, JSON_NODE_VALUE);
269   json_node_set_int (node, value);
270 
271   return node;
272 }
273 
274 /**
275  * json_node_init_double:
276  * @node: the #JsonNode to initialize
277  * @value: a floating point value
278  *
279  * Initializes @node to %JSON_NODE_VALUE and sets @value into it.
280  *
281  * If the node has already been initialized once, it will be reset to
282  * the given type, and any data contained will be cleared.
283  *
284  * Return value: (transfer none): the initialized #JsonNode
285  *
286  * Since: 0.16
287  */
288 JsonNode *
json_node_init_double(JsonNode * node,gdouble value)289 json_node_init_double (JsonNode *node,
290                        gdouble   value)
291 {
292   g_return_val_if_fail (node != NULL, NULL);
293 
294   json_node_init (node, JSON_NODE_VALUE);
295   json_node_set_double (node, value);
296 
297   return node;
298 }
299 
300 /**
301  * json_node_init_boolean:
302  * @node: the #JsonNode to initialize
303  * @value: a boolean value
304  *
305  * Initializes @node to %JSON_NODE_VALUE and sets @value into it.
306  *
307  * If the node has already been initialized once, it will be reset to
308  * the given type, and any data contained will be cleared.
309  *
310  * Return value: (transfer none): the initialized #JsonNode
311  *
312  * Since: 0.16
313  */
314 JsonNode *
json_node_init_boolean(JsonNode * node,gboolean value)315 json_node_init_boolean (JsonNode *node,
316                         gboolean  value)
317 {
318   g_return_val_if_fail (node != NULL, NULL);
319 
320   json_node_init (node, JSON_NODE_VALUE);
321   json_node_set_boolean (node, value);
322 
323   return node;
324 }
325 
326 /**
327  * json_node_init_string:
328  * @node: the #JsonNode to initialize
329  * @value: (allow-none): a string value
330  *
331  * Initializes @node to %JSON_NODE_VALUE and sets @value into it.
332  *
333  * If the node has already been initialized once, it will be reset to
334  * the given type, and any data contained will be cleared.
335  *
336  * Return value: (transfer none): the initialized #JsonNode
337  *
338  * Since: 0.16
339  */
340 JsonNode *
json_node_init_string(JsonNode * node,const char * value)341 json_node_init_string (JsonNode   *node,
342                        const char *value)
343 {
344   g_return_val_if_fail (node != NULL, NULL);
345 
346   json_node_init (node, JSON_NODE_VALUE);
347   json_node_set_string (node, value);
348 
349   return node;
350 }
351 
352 /**
353  * json_node_init_null:
354  * @node: the #JsonNode to initialize
355  *
356  * Initializes @node to %JSON_NODE_NULL.
357  *
358  * If the node has already been initialized once, it will be reset to
359  * the given type, and any data contained will be cleared.
360  *
361  * Return value: (transfer none): the initialized #JsonNode
362  *
363  * Since: 0.16
364  */
365 JsonNode *
json_node_init_null(JsonNode * node)366 json_node_init_null (JsonNode *node)
367 {
368   g_return_val_if_fail (node != NULL, NULL);
369 
370   return json_node_init (node, JSON_NODE_NULL);
371 }
372 
373 /**
374  * json_node_new: (constructor)
375  * @type: a #JsonNodeType
376  *
377  * Creates a new #JsonNode of @type.
378  *
379  * This is a convenience function for json_node_alloc() and json_node_init(),
380  * and it's the equivalent of:
381  *
382  * |[<!-- language="C" -->
383      json_node_init (json_node_alloc (), type);
384  * ]|
385  *
386  * Return value: (transfer full): the newly created #JsonNode
387  */
388 JsonNode *
json_node_new(JsonNodeType type)389 json_node_new (JsonNodeType type)
390 {
391   g_return_val_if_fail (type >= JSON_NODE_OBJECT &&
392                         type <= JSON_NODE_NULL, NULL);
393 
394   return json_node_init (json_node_alloc (), type);
395 }
396 
397 /**
398  * json_node_copy:
399  * @node: a #JsonNode
400  *
401  * Copies @node. If the node contains complex data types, their reference
402  * counts are increased, regardless of whether the node is mutable or
403  * immutable.
404  *
405  * The copy will be immutable if, and only if, @node is immutable. However,
406  * there should be no need to copy an immutable node.
407  *
408  * Return value: (transfer full): the copied #JsonNode
409  */
410 JsonNode *
json_node_copy(JsonNode * node)411 json_node_copy (JsonNode *node)
412 {
413   JsonNode *copy;
414 
415   g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
416 
417   copy = json_node_alloc ();
418   copy->type = node->type;
419   copy->immutable = node->immutable;
420 
421 #ifdef JSON_ENABLE_DEBUG
422   if (node->immutable)
423     {
424       JSON_NOTE (NODE, "Copying immutable JsonNode %p of type %s",
425                  node,
426                  json_node_type_name (node));
427     }
428 #endif
429 
430   switch (copy->type)
431     {
432     case JSON_NODE_OBJECT:
433       copy->data.object = json_node_dup_object (node);
434       break;
435 
436     case JSON_NODE_ARRAY:
437       copy->data.array = json_node_dup_array (node);
438       break;
439 
440     case JSON_NODE_VALUE:
441       if (node->data.value)
442         copy->data.value = json_value_ref (node->data.value);
443       break;
444 
445     case JSON_NODE_NULL:
446       break;
447 
448     default:
449       g_assert_not_reached ();
450     }
451 
452   return copy;
453 }
454 
455 /**
456  * json_node_ref:
457  * @node: a #JsonNode
458  *
459  * Increment the reference count of @node.
460  *
461  * Since: 1.2
462  * Returns: (transfer full): a pointer to @node
463  */
464 JsonNode *
json_node_ref(JsonNode * node)465 json_node_ref (JsonNode *node)
466 {
467   g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
468 
469   g_atomic_int_inc (&node->ref_count);
470 
471   return node;
472 }
473 
474 /**
475  * json_node_unref:
476  * @node: (transfer full): a #JsonNode
477  *
478  * Decrement the reference count of @node. If it reaches zero, the node is
479  * freed.
480  *
481  * Since: 1.2
482  */
483 void
json_node_unref(JsonNode * node)484 json_node_unref (JsonNode *node)
485 {
486   g_return_if_fail (JSON_NODE_IS_VALID (node));
487 
488   if (g_atomic_int_dec_and_test (&node->ref_count))
489     {
490       json_node_unset (node);
491       if (node->allocated)
492         g_slice_free (JsonNode, node);
493     }
494 }
495 
496 /**
497  * json_node_set_object:
498  * @node: a #JsonNode initialized to %JSON_NODE_OBJECT
499  * @object: (nullable): a #JsonObject
500  *
501  * Sets @objects inside @node. The reference count of @object is increased.
502  *
503  * If @object is %NULL, the node’s existing object is cleared.
504  *
505  * It is an error to call this on an immutable node, or on a node which is not
506  * an object node.
507  */
508 void
json_node_set_object(JsonNode * node,JsonObject * object)509 json_node_set_object (JsonNode   *node,
510                       JsonObject *object)
511 {
512   g_return_if_fail (JSON_NODE_IS_VALID (node));
513   g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT);
514   g_return_if_fail (!node->immutable);
515 
516   if (node->data.object != NULL)
517     json_object_unref (node->data.object);
518 
519   if (object)
520     node->data.object = json_object_ref (object);
521   else
522     node->data.object = NULL;
523 }
524 
525 /**
526  * json_node_take_object:
527  * @node: a #JsonNode initialized to %JSON_NODE_OBJECT
528  * @object: (transfer full): a #JsonObject
529  *
530  * Sets @object inside @node. The reference count of @object is not increased.
531  *
532  * It is an error to call this on an immutable node, or on a node which is not
533  * an object node.
534  */
535 void
json_node_take_object(JsonNode * node,JsonObject * object)536 json_node_take_object (JsonNode   *node,
537                        JsonObject *object)
538 {
539   g_return_if_fail (JSON_NODE_IS_VALID (node));
540   g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT);
541   g_return_if_fail (!node->immutable);
542 
543   if (node->data.object)
544     {
545       json_object_unref (node->data.object);
546       node->data.object = NULL;
547     }
548 
549   if (object)
550     node->data.object = object;
551 }
552 
553 /**
554  * json_node_get_object:
555  * @node: a #JsonNode
556  *
557  * Retrieves the #JsonObject stored inside a #JsonNode. It is a programmer error
558  * to call this on a node which doesn’t hold an object value. Use
559  * %JSON_NODE_HOLDS_OBJECT first.
560  *
561  * Return value: (transfer none) (nullable): the #JsonObject
562  */
563 JsonObject *
json_node_get_object(JsonNode * node)564 json_node_get_object (JsonNode *node)
565 {
566   g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
567   g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT, NULL);
568 
569   return node->data.object;
570 }
571 
572 /**
573  * json_node_dup_object:
574  * @node: a #JsonNode
575  *
576  * Retrieves the #JsonObject inside @node. The reference count of
577  * the returned object is increased. It is a programmer error
578  * to call this on a node which doesn’t hold an object value. Use
579  * %JSON_NODE_HOLDS_OBJECT first.
580  *
581  * Return value: (transfer full) (nullable): the #JsonObject
582  */
583 JsonObject *
json_node_dup_object(JsonNode * node)584 json_node_dup_object (JsonNode *node)
585 {
586   g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
587   g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT, NULL);
588 
589   if (node->data.object)
590     return json_object_ref (node->data.object);
591 
592   return NULL;
593 }
594 
595 /**
596  * json_node_set_array:
597  * @node: a #JsonNode initialized to %JSON_NODE_ARRAY
598  * @array: a #JsonArray
599  *
600  * Sets @array inside @node and increases the #JsonArray reference count.
601  *
602  * It is an error to call this on an immutable node, or on a node which is not
603  * an array node.
604  */
605 void
json_node_set_array(JsonNode * node,JsonArray * array)606 json_node_set_array (JsonNode  *node,
607                      JsonArray *array)
608 {
609   g_return_if_fail (JSON_NODE_IS_VALID (node));
610   g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY);
611   g_return_if_fail (!node->immutable);
612 
613   if (node->data.array)
614     json_array_unref (node->data.array);
615 
616   if (array)
617     node->data.array = json_array_ref (array);
618   else
619     node->data.array = NULL;
620 }
621 
622 /**
623  * json_node_take_array:
624  * @node: a #JsonNode initialized to %JSON_NODE_ARRAY
625  * @array: (transfer full): a #JsonArray
626  *
627  * Sets @array into @node without increasing the #JsonArray reference count.
628  *
629  * It is an error to call this on an immutable node, or a node which is not
630  * an array node.
631  */
632 void
json_node_take_array(JsonNode * node,JsonArray * array)633 json_node_take_array (JsonNode  *node,
634                       JsonArray *array)
635 {
636   g_return_if_fail (JSON_NODE_IS_VALID (node));
637   g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY);
638   g_return_if_fail (!node->immutable);
639 
640   if (node->data.array)
641     {
642       json_array_unref (node->data.array);
643       node->data.array = NULL;
644     }
645 
646   if (array)
647     node->data.array = array;
648 }
649 
650 /**
651  * json_node_get_array:
652  * @node: a #JsonNode
653  *
654  * Retrieves the #JsonArray stored inside a #JsonNode. It is a programmer error
655  * to call this on a node which doesn’t hold an array value. Use
656  * %JSON_NODE_HOLDS_ARRAY first.
657  *
658  * Return value: (transfer none) (nullable): the #JsonArray
659  */
660 JsonArray *
json_node_get_array(JsonNode * node)661 json_node_get_array (JsonNode *node)
662 {
663   g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
664   g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY, NULL);
665 
666   return node->data.array;
667 }
668 
669 /**
670  * json_node_dup_array:
671  * @node: a #JsonNode
672  *
673  * Retrieves the #JsonArray stored inside a #JsonNode and returns it
674  * with its reference count increased by one. It is a programmer error
675  * to call this on a node which doesn’t hold an array value. Use
676  * %JSON_NODE_HOLDS_ARRAY first.
677  *
678  * Return value: (transfer full) (nullable): the #JsonArray with its reference
679  *   count increased.
680  */
681 JsonArray *
json_node_dup_array(JsonNode * node)682 json_node_dup_array (JsonNode *node)
683 {
684   g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
685   g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY, NULL);
686 
687   if (node->data.array)
688     return json_array_ref (node->data.array);
689 
690   return NULL;
691 }
692 
693 /**
694  * json_node_get_value:
695  * @node: a #JsonNode
696  * @value: (out caller-allocates): return location for an uninitialized value
697  *
698  * Retrieves a value from a #JsonNode and copies into @value. When done
699  * using it, call g_value_unset() on the #GValue. It is a programmer error
700  * to call this on a node which doesn’t hold a scalar value. Use
701  * %JSON_NODE_HOLDS_VALUE first.
702  */
703 void
json_node_get_value(JsonNode * node,GValue * value)704 json_node_get_value (JsonNode *node,
705                      GValue   *value)
706 {
707   g_return_if_fail (JSON_NODE_IS_VALID (node));
708   g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
709 
710   if (node->data.value)
711     {
712       g_value_init (value, JSON_VALUE_TYPE (node->data.value));
713       switch (JSON_VALUE_TYPE (node->data.value))
714         {
715         case G_TYPE_INT64:
716           g_value_set_int64 (value, json_value_get_int (node->data.value));
717           break;
718 
719         case G_TYPE_DOUBLE:
720           g_value_set_double (value, json_value_get_double (node->data.value));
721           break;
722 
723         case G_TYPE_BOOLEAN:
724           g_value_set_boolean (value, json_value_get_boolean (node->data.value));
725           break;
726 
727         case G_TYPE_STRING:
728           g_value_set_string (value, json_value_get_string (node->data.value));
729           break;
730 
731         default:
732           break;
733         }
734     }
735 }
736 
737 /**
738  * json_node_set_value:
739  * @node: a #JsonNode initialized to %JSON_NODE_VALUE
740  * @value: the #GValue to set
741  *
742  * Sets @value inside @node. The passed #GValue is copied into the #JsonNode.
743  *
744  * It is an error to call this on an immutable node, or on a node which is not
745  * a value node.
746  */
747 void
json_node_set_value(JsonNode * node,const GValue * value)748 json_node_set_value (JsonNode     *node,
749                      const GValue *value)
750 {
751   g_return_if_fail (JSON_NODE_IS_VALID (node));
752   g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
753   g_return_if_fail (G_VALUE_TYPE (value) != G_TYPE_INVALID);
754   g_return_if_fail (!node->immutable);
755 
756   if (node->data.value == NULL)
757     node->data.value = json_value_alloc ();
758 
759   switch (G_VALUE_TYPE (value))
760     {
761     /* auto-promote machine integers to 64 bit integers */
762     case G_TYPE_INT64:
763     case G_TYPE_INT:
764       json_value_init (node->data.value, JSON_VALUE_INT);
765       if (G_VALUE_TYPE (value) == G_TYPE_INT64)
766         json_value_set_int (node->data.value, g_value_get_int64 (value));
767       else
768         json_value_set_int (node->data.value, g_value_get_int (value));
769       break;
770 
771     case G_TYPE_BOOLEAN:
772       json_value_init (node->data.value, JSON_VALUE_BOOLEAN);
773       json_value_set_boolean (node->data.value, g_value_get_boolean (value));
774       break;
775 
776     /* auto-promote single-precision floats to double precision floats */
777     case G_TYPE_DOUBLE:
778     case G_TYPE_FLOAT:
779       json_value_init (node->data.value, JSON_VALUE_DOUBLE);
780       if (G_VALUE_TYPE (value) == G_TYPE_DOUBLE)
781         json_value_set_double (node->data.value, g_value_get_double (value));
782       else
783         json_value_set_double (node->data.value, g_value_get_float (value));
784       break;
785 
786     case G_TYPE_STRING:
787       json_value_init (node->data.value, JSON_VALUE_STRING);
788       json_value_set_string (node->data.value, g_value_get_string (value));
789       break;
790 
791     default:
792       g_message ("Invalid value of type '%s'",
793                  g_type_name (G_VALUE_TYPE (value)));
794       return;
795     }
796 
797 }
798 
799 /**
800  * json_node_free:
801  * @node: a #JsonNode
802  *
803  * Frees the resources allocated by @node.
804  */
805 void
json_node_free(JsonNode * node)806 json_node_free (JsonNode *node)
807 {
808   g_return_if_fail (node == NULL || JSON_NODE_IS_VALID (node));
809   g_return_if_fail (node == NULL || node->allocated);
810 
811   if (G_LIKELY (node))
812     {
813       if (node->ref_count > 1)
814         g_warning ("Freeing a JsonNode %p owned by other code.", node);
815 
816       json_node_unset (node);
817       g_slice_free (JsonNode, node);
818     }
819 }
820 
821 /**
822  * json_node_seal:
823  * @node: a #JsonNode
824  *
825  * Seals the #JsonNode, making it immutable to further changes. In order to be
826  * sealed, the @node must have a type and value set. The value will be
827  * recursively sealed — if the node holds an object, that #JsonObject will be
828  * sealed, etc.
829  *
830  * If the @node is already immutable, this is a no-op.
831  *
832  * Since: 1.2
833  */
834 void
json_node_seal(JsonNode * node)835 json_node_seal (JsonNode *node)
836 {
837   g_return_if_fail (JSON_NODE_IS_VALID (node));
838 
839   if (node->immutable)
840     return;
841 
842   switch (node->type)
843     {
844     case JSON_NODE_OBJECT:
845       g_return_if_fail (node->data.object != NULL);
846       json_object_seal (node->data.object);
847       break;
848     case JSON_NODE_ARRAY:
849       g_return_if_fail (node->data.array != NULL);
850       json_array_seal (node->data.array);
851       break;
852     case JSON_NODE_NULL:
853       break;
854     case JSON_NODE_VALUE:
855       g_return_if_fail (node->data.value != NULL);
856       json_value_seal (node->data.value);
857       break;
858     default:
859       g_assert_not_reached ();
860     }
861 
862   node->immutable = TRUE;
863 }
864 
865 /**
866  * json_node_is_immutable:
867  * @node: a #JsonNode
868  *
869  * Check whether the given @node has been marked as immutable by calling
870  * json_node_seal() on it.
871  *
872  * Since: 1.2
873  * Returns: %TRUE if the @node is immutable
874  */
875 gboolean
json_node_is_immutable(JsonNode * node)876 json_node_is_immutable (JsonNode *node)
877 {
878   g_return_val_if_fail (JSON_NODE_IS_VALID (node), FALSE);
879 
880   return node->immutable;
881 }
882 
883 /**
884  * json_node_type_name:
885  * @node: a #JsonNode
886  *
887  * Retrieves the user readable name of the data type contained by @node.
888  *
889  * Return value: a string containing the name of the type. The returned string
890  *   is owned by the node and should never be modified or freed
891  */
892 const gchar *
json_node_type_name(JsonNode * node)893 json_node_type_name (JsonNode *node)
894 {
895   g_return_val_if_fail (node != NULL, "(null)");
896 
897   switch (node->type)
898     {
899     case JSON_NODE_OBJECT:
900     case JSON_NODE_ARRAY:
901     case JSON_NODE_NULL:
902       return json_node_type_get_name (node->type);
903 
904     case JSON_NODE_VALUE:
905       if (node->data.value)
906         return json_value_type_get_name (node->data.value->type);
907     }
908 
909   return "unknown";
910 }
911 
912 const gchar *
json_node_type_get_name(JsonNodeType node_type)913 json_node_type_get_name (JsonNodeType node_type)
914 {
915   switch (node_type)
916     {
917     case JSON_NODE_OBJECT:
918       return "JsonObject";
919 
920     case JSON_NODE_ARRAY:
921       return "JsonArray";
922 
923     case JSON_NODE_NULL:
924       return "NULL";
925 
926     case JSON_NODE_VALUE:
927       return "Value";
928 
929     default:
930       g_assert_not_reached ();
931       break;
932     }
933 
934   return "unknown";
935 }
936 
937 /**
938  * json_node_set_parent:
939  * @node: a #JsonNode
940  * @parent: (transfer none): the parent #JsonNode of @node
941  *
942  * Sets the parent #JsonNode of @node.
943  *
944  * It is an error to call this with an immutable @parent. @node may be
945  * immutable.
946  *
947  * Since: 0.8
948  */
949 void
json_node_set_parent(JsonNode * node,JsonNode * parent)950 json_node_set_parent (JsonNode *node,
951                       JsonNode *parent)
952 {
953   g_return_if_fail (JSON_NODE_IS_VALID (node));
954   g_return_if_fail (parent == NULL ||
955                     !json_node_is_immutable (parent));
956 
957   node->parent = parent;
958 }
959 
960 /**
961  * json_node_get_parent:
962  * @node: a #JsonNode
963  *
964  * Retrieves the parent #JsonNode of @node.
965  *
966  * Return value: (transfer none) (nullable): the parent node, or %NULL if @node
967  *   is the root node
968  */
969 JsonNode *
json_node_get_parent(JsonNode * node)970 json_node_get_parent (JsonNode *node)
971 {
972   g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
973 
974   return node->parent;
975 }
976 
977 /**
978  * json_node_set_string:
979  * @node: a #JsonNode initialized to %JSON_NODE_VALUE
980  * @value: a string value
981  *
982  * Sets @value as the string content of the @node, replacing any existing
983  * content.
984  *
985  * It is an error to call this on an immutable node, or on a node which is not
986  * a value node.
987  */
988 void
json_node_set_string(JsonNode * node,const gchar * value)989 json_node_set_string (JsonNode    *node,
990                       const gchar *value)
991 {
992   g_return_if_fail (JSON_NODE_IS_VALID (node));
993   g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
994   g_return_if_fail (!node->immutable);
995 
996   if (node->data.value == NULL)
997     node->data.value = json_value_init (json_value_alloc (), JSON_VALUE_STRING);
998   else
999     json_value_init (node->data.value, JSON_VALUE_STRING);
1000 
1001   json_value_set_string (node->data.value, value);
1002 }
1003 
1004 /**
1005  * json_node_get_string:
1006  * @node: a #JsonNode of type %JSON_NODE_VALUE
1007  *
1008  * Gets the string value stored inside a #JsonNode. If the node does not hold a
1009  * string value, %NULL is returned.
1010  *
1011  * Return value: (nullable): a string value.
1012  */
1013 const gchar *
json_node_get_string(JsonNode * node)1014 json_node_get_string (JsonNode *node)
1015 {
1016   g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
1017 
1018   if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
1019     return NULL;
1020 
1021   if (JSON_VALUE_HOLDS_STRING (node->data.value))
1022     return json_value_get_string (node->data.value);
1023 
1024   return NULL;
1025 }
1026 
1027 /**
1028  * json_node_dup_string:
1029  * @node: a #JsonNode of type %JSON_NODE_VALUE
1030  *
1031  * Gets a copy of the string value stored inside a #JsonNode. If the node does
1032  * not hold a string value, %NULL is returned.
1033  *
1034  * Return value: (transfer full) (nullable): a newly allocated string
1035  *   containing a copy of the #JsonNode contents. Use g_free() to free the
1036  *   allocated resources
1037  */
1038 gchar *
json_node_dup_string(JsonNode * node)1039 json_node_dup_string (JsonNode *node)
1040 {
1041   g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
1042 
1043   return g_strdup (json_node_get_string (node));
1044 }
1045 
1046 /**
1047  * json_node_set_int:
1048  * @node: a #JsonNode of type %JSON_NODE_VALUE
1049  * @value: an integer value
1050  *
1051  * Sets @value as the integer content of the @node, replacing any existing
1052  * content.
1053  *
1054  * It is an error to call this on an immutable node, or on a node which is not
1055  * a value node.
1056  */
1057 void
json_node_set_int(JsonNode * node,gint64 value)1058 json_node_set_int (JsonNode *node,
1059                    gint64    value)
1060 {
1061   g_return_if_fail (JSON_NODE_IS_VALID (node));
1062   g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
1063   g_return_if_fail (!node->immutable);
1064 
1065   if (node->data.value == NULL)
1066     node->data.value = json_value_init (json_value_alloc (), JSON_VALUE_INT);
1067   else
1068     json_value_init (node->data.value, JSON_VALUE_INT);
1069 
1070   json_value_set_int (node->data.value, value);
1071 }
1072 
1073 /**
1074  * json_node_get_int:
1075  * @node: a #JsonNode of type %JSON_NODE_VALUE
1076  *
1077  * Gets the integer value stored inside a #JsonNode. If the node holds a double
1078  * value, its integer component is returned. If the node holds a %FALSE boolean
1079  * value, `0` is returned; otherwise a non-zero integer is returned. If the
1080  * node holds a %JSON_NODE_NULL value or a value of another non-integer type,
1081  * `0` is returned.
1082  *
1083  * Return value: an integer value.
1084  */
1085 gint64
json_node_get_int(JsonNode * node)1086 json_node_get_int (JsonNode *node)
1087 {
1088   g_return_val_if_fail (JSON_NODE_IS_VALID (node), 0);
1089 
1090   if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
1091     return 0;
1092 
1093   if (JSON_VALUE_HOLDS_INT (node->data.value))
1094     return json_value_get_int (node->data.value);
1095 
1096   if (JSON_VALUE_HOLDS_DOUBLE (node->data.value))
1097     return json_value_get_double (node->data.value);
1098 
1099   if (JSON_VALUE_HOLDS_BOOLEAN (node->data.value))
1100     return json_value_get_boolean (node->data.value);
1101 
1102   return 0;
1103 }
1104 
1105 /**
1106  * json_node_set_double:
1107  * @node: a #JsonNode of type %JSON_NODE_VALUE
1108  * @value: a double value
1109  *
1110  * Sets @value as the double content of the @node, replacing any existing
1111  * content.
1112  *
1113  * It is an error to call this on an immutable node, or on a node which is not
1114  * a value node.
1115  */
1116 void
json_node_set_double(JsonNode * node,gdouble value)1117 json_node_set_double (JsonNode *node,
1118                       gdouble   value)
1119 {
1120   g_return_if_fail (JSON_NODE_IS_VALID (node));
1121   g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
1122   g_return_if_fail (!node->immutable);
1123 
1124   if (node->data.value == NULL)
1125     node->data.value = json_value_init (json_value_alloc (), JSON_VALUE_DOUBLE);
1126   else
1127     json_value_init (node->data.value, JSON_VALUE_DOUBLE);
1128 
1129   json_value_set_double (node->data.value, value);
1130 }
1131 
1132 /**
1133  * json_node_get_double:
1134  * @node: a #JsonNode of type %JSON_NODE_VALUE
1135  *
1136  * Gets the double value stored inside a #JsonNode. If the node holds an integer
1137  * value, it is returned as a double. If the node holds a %FALSE boolean value,
1138  * `0.0` is returned; otherwise a non-zero double is returned. If the node holds
1139  * a %JSON_NODE_NULL value or a value of another non-double type, `0.0` is
1140  * returned.
1141  *
1142  * Return value: a double value.
1143  */
1144 gdouble
json_node_get_double(JsonNode * node)1145 json_node_get_double (JsonNode *node)
1146 {
1147   g_return_val_if_fail (JSON_NODE_IS_VALID (node), 0.0);
1148 
1149   if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
1150     return 0;
1151 
1152   if (JSON_VALUE_HOLDS_DOUBLE (node->data.value))
1153     return json_value_get_double (node->data.value);
1154 
1155   if (JSON_VALUE_HOLDS_INT (node->data.value))
1156     return (gdouble) json_value_get_int (node->data.value);
1157 
1158   if (JSON_VALUE_HOLDS_BOOLEAN (node->data.value))
1159     return (gdouble) json_value_get_boolean (node->data.value);
1160 
1161   return 0.0;
1162 }
1163 
1164 /**
1165  * json_node_set_boolean:
1166  * @node: a #JsonNode of type %JSON_NODE_VALUE
1167  * @value: a boolean value
1168  *
1169  * Sets @value as the boolean content of the @node, replacing any existing
1170  * content.
1171  *
1172  * It is an error to call this on an immutable node, or on a node which is not
1173  * a value node.
1174  */
1175 void
json_node_set_boolean(JsonNode * node,gboolean value)1176 json_node_set_boolean (JsonNode *node,
1177                        gboolean  value)
1178 {
1179   g_return_if_fail (JSON_NODE_IS_VALID (node));
1180   g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
1181   g_return_if_fail (!node->immutable);
1182 
1183   if (node->data.value == NULL)
1184     node->data.value = json_value_init (json_value_alloc (), JSON_VALUE_BOOLEAN);
1185   else
1186     json_value_init (node->data.value, JSON_VALUE_BOOLEAN);
1187 
1188   json_value_set_boolean (node->data.value, value);
1189 }
1190 
1191 /**
1192  * json_node_get_boolean:
1193  * @node: a #JsonNode of type %JSON_NODE_VALUE
1194  *
1195  * Gets the boolean value stored inside a #JsonNode. If the node holds an
1196  * integer or double value which is zero, %FALSE is returned; otherwise %TRUE
1197  * is returned. If the node holds a %JSON_NODE_NULL value or a value of another
1198  * non-boolean type, %FALSE is returned.
1199  *
1200  * Return value: a boolean value.
1201  */
1202 gboolean
json_node_get_boolean(JsonNode * node)1203 json_node_get_boolean (JsonNode *node)
1204 {
1205   g_return_val_if_fail (JSON_NODE_IS_VALID (node), FALSE);
1206 
1207   if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
1208     return FALSE;
1209 
1210   if (JSON_VALUE_HOLDS_BOOLEAN (node->data.value))
1211     return json_value_get_boolean (node->data.value);
1212 
1213   if (JSON_VALUE_HOLDS_INT (node->data.value))
1214     return json_value_get_int (node->data.value) != 0;
1215 
1216   if (JSON_VALUE_HOLDS_DOUBLE (node->data.value))
1217     return json_value_get_double (node->data.value) != 0.0;
1218 
1219   return FALSE;
1220 }
1221 
1222 /**
1223  * json_node_get_node_type:
1224  * @node: a #JsonNode
1225  *
1226  * Retrieves the #JsonNodeType of @node
1227  *
1228  * Return value: the type of the node
1229  *
1230  * Since: 0.8
1231  */
1232 JsonNodeType
json_node_get_node_type(JsonNode * node)1233 json_node_get_node_type (JsonNode *node)
1234 {
1235   g_return_val_if_fail (JSON_NODE_IS_VALID (node), JSON_NODE_NULL);
1236 
1237   return node->type;
1238 }
1239 
1240 /**
1241  * json_node_is_null:
1242  * @node: a #JsonNode
1243  *
1244  * Checks whether @node is a %JSON_NODE_NULL.
1245  *
1246  * A %JSON_NODE_NULL node is not the same as a %NULL #JsonNode; a
1247  * %JSON_NODE_NULL represents a 'null' value in the JSON tree.
1248  *
1249  * Return value: %TRUE if the node is null
1250  *
1251  * Since: 0.8
1252  */
1253 gboolean
json_node_is_null(JsonNode * node)1254 json_node_is_null (JsonNode *node)
1255 {
1256   g_return_val_if_fail (JSON_NODE_IS_VALID (node), TRUE);
1257 
1258   return node->type == JSON_NODE_NULL;
1259 }
1260 
1261 /**
1262  * json_type_is_a:
1263  * @sub: sub-type
1264  * @super: super-type
1265  *
1266  * Check whether @sub is a sub-type of, or equal to, @super. The only sub-type
1267  * relationship in the JSON Schema type system is that
1268  * %WBL_PRIMITIVE_TYPE_INTEGER is a sub-type of %WBL_PRIMITIVE_TYPE_NUMBER.
1269  *
1270  * Formally, this function calculates: `@sub <: @super`.
1271  *
1272  * Reference: http://json-schema.org/latest/json-schema-core.html#rfc.section.3.5
1273  *
1274  * Returns: %TRUE if @sub is a sub-type of, or equal to, @super; %FALSE
1275  *    otherwise
1276  * Since: 1.2
1277  */
1278 static gboolean
json_type_is_a(JsonNode * sub,JsonNode * super)1279 json_type_is_a (JsonNode  *sub,
1280                 JsonNode  *super)
1281 {
1282   if (super->type == JSON_NODE_VALUE && sub->type == JSON_NODE_VALUE)
1283     {
1284       JsonValueType super_value_type, sub_value_type;
1285 
1286       if (super->data.value == NULL || sub->data.value == NULL)
1287         return FALSE;
1288 
1289       super_value_type = super->data.value->type;
1290       sub_value_type = sub->data.value->type;
1291 
1292       return (super_value_type == sub_value_type ||
1293               (super_value_type == JSON_VALUE_DOUBLE &&
1294 	       sub_value_type == JSON_VALUE_INT));
1295     }
1296 
1297   return (super->type == sub->type);
1298 }
1299 
1300 /**
1301  * json_string_hash:
1302  * @key: (type utf8): a JSON string to hash
1303  *
1304  * Calculate a hash value for the given @key (a UTF-8 JSON string).
1305  *
1306  * Note: Member names are compared byte-wise, without applying any Unicode
1307  * decomposition or normalisation. This is not explicitly mentioned in the JSON
1308  * standard (ECMA-404), but is assumed.
1309  *
1310  * Returns: hash value for @key
1311  * Since: 1.2
1312  */
1313 guint
json_string_hash(gconstpointer key)1314 json_string_hash (gconstpointer key)
1315 {
1316   return g_str_hash (key);
1317 }
1318 
1319 /**
1320  * json_string_equal:
1321  * @a: (type utf8): a JSON string
1322  * @b: (type utf8): another JSON string
1323  *
1324  * Check whether @a and @b are equal UTF-8 JSON strings.
1325  *
1326  * Returns: %TRUE if @a and @b are equal; %FALSE otherwise
1327  * Since: 1.2
1328  */
1329 gboolean
json_string_equal(gconstpointer a,gconstpointer b)1330 json_string_equal (gconstpointer  a,
1331                    gconstpointer  b)
1332 {
1333   return g_str_equal (a, b);
1334 }
1335 
1336 /**
1337  * json_string_compare:
1338  * @a: (type utf8): a JSON string
1339  * @b: (type utf8): another JSON string
1340  *
1341  * Check whether @a and @b are equal UTF-8 JSON strings and return an ordering
1342  * over them in strcmp() style.
1343  *
1344  * Returns: an integer less than zero if @a < @b, equal to zero if @a == @b, and
1345  *    greater than zero if @a > @b
1346  * Since: 1.2
1347  */
1348 gint
json_string_compare(gconstpointer a,gconstpointer b)1349 json_string_compare (gconstpointer  a,
1350                      gconstpointer  b)
1351 {
1352   return g_strcmp0 (a, b);
1353 }
1354 
1355 /**
1356  * json_node_hash:
1357  * @key: (type JsonNode): a JSON node to hash
1358  *
1359  * Calculate a hash value for the given @key (a #JsonNode).
1360  *
1361  * The hash is calculated over the node and its value, recursively. If the node
1362  * is immutable, this is a fast operation; otherwise, it scales proportionally
1363  * with the size of the node’s value (for example, with the number of members
1364  * in the #JsonObject if this node contains an object).
1365  *
1366  * Returns: hash value for @key
1367  * Since: 1.2
1368  */
1369 guint
json_node_hash(gconstpointer key)1370 json_node_hash (gconstpointer key)
1371 {
1372   JsonNode *node;  /* unowned */
1373 
1374   /* These are all randomly generated and arbitrary. */
1375   const guint value_hash = 0xc19e75ad;
1376   const guint array_hash = 0x865acfc2;
1377   const guint object_hash = 0x3c8f3135;
1378 
1379   node = (JsonNode *) key;
1380 
1381   /* XOR the hash values with a (constant) random number depending on the node’s
1382    * type so that empty values, arrays and objects do not all collide at the
1383    * hash value 0. */
1384   switch (node->type)
1385     {
1386     case JSON_NODE_NULL:
1387       return 0;
1388     case JSON_NODE_VALUE:
1389       return value_hash ^ json_value_hash (node->data.value);
1390     case JSON_NODE_ARRAY:
1391       return array_hash ^ json_array_hash (json_node_get_array (node));
1392     case JSON_NODE_OBJECT:
1393       return object_hash ^ json_object_hash (json_node_get_object (node));
1394     default:
1395       g_assert_not_reached ();
1396     }
1397 }
1398 
1399 /**
1400  * json_node_equal:
1401  * @a: (type JsonNode): a JSON node
1402  * @b: (type JsonNode): another JSON node
1403  *
1404  * Check whether @a and @b are equal #JsonNodes, meaning they have the same
1405  * type and same values (checked recursively). Note that integer values are
1406  * compared numerically, ignoring type, so a double value 4.0 is equal to the
1407  * integer value 4.
1408  *
1409  * Returns: %TRUE if @a and @b are equal; %FALSE otherwise
1410  * Since: 1.2
1411  */
1412 gboolean
json_node_equal(gconstpointer a,gconstpointer b)1413 json_node_equal (gconstpointer  a,
1414                  gconstpointer  b)
1415 {
1416   JsonNode *node_a, *node_b;  /* unowned */
1417 
1418   node_a = (JsonNode *) a;
1419   node_b = (JsonNode *) b;
1420 
1421   /* Identity comparison. */
1422   if (node_a == node_b)
1423     return TRUE;
1424 
1425   /* Eliminate mismatched types rapidly. */
1426   if (!json_type_is_a (node_a, node_b) &&
1427       !json_type_is_a (node_b, node_a))
1428     {
1429       return FALSE;
1430     }
1431 
1432   switch (node_a->type)
1433     {
1434     case JSON_NODE_NULL:
1435       /* Types match already. */
1436       return TRUE;
1437     case JSON_NODE_ARRAY:
1438       return json_array_equal (json_node_get_array (node_a),
1439                                json_node_get_array (node_b));
1440     case JSON_NODE_OBJECT:
1441       return json_object_equal (json_node_get_object (node_a),
1442                                 json_node_get_object (node_b));
1443     case JSON_NODE_VALUE:
1444       /* Handled below. */
1445       break;
1446     default:
1447       g_assert_not_reached ();
1448     }
1449 
1450   /* Handle values. */
1451   switch (node_a->data.value->type)
1452     {
1453     case JSON_VALUE_NULL:
1454       /* Types already match. */
1455       return TRUE;
1456     case JSON_VALUE_BOOLEAN:
1457       return (json_node_get_boolean (node_a) == json_node_get_boolean (node_b));
1458     case JSON_VALUE_STRING:
1459       return json_string_equal (json_node_get_string (node_a),
1460                                 json_node_get_string (node_b));
1461     case JSON_VALUE_DOUBLE:
1462     case JSON_VALUE_INT: {
1463       gdouble val_a, val_b;
1464       JsonValueType value_type_a, value_type_b;
1465 
1466       value_type_a = node_a->data.value->type;
1467       value_type_b = node_b->data.value->type;
1468 
1469       /* Integer comparison doesn’t need to involve doubles… */
1470       if (value_type_a == JSON_VALUE_INT &&
1471           value_type_b == JSON_VALUE_INT)
1472         {
1473           return (json_node_get_int (node_a) ==
1474                   json_node_get_int (node_b));
1475         }
1476 
1477       /* …but everything else does. We can use bitwise double equality here,
1478        * since we’re not doing any calculations which could introduce floating
1479        * point error. We expect that the doubles in the JSON nodes come directly
1480        * from strtod() or similar, so should be bitwise equal for equal string
1481        * representations.
1482        *
1483        * Interesting background reading:
1484        * http://randomascii.wordpress.com/2012/06/26/\
1485        *   doubles-are-not-floats-so-dont-compare-them/
1486        */
1487       if (value_type_a == JSON_VALUE_INT)
1488         val_a = json_node_get_int (node_a);
1489       else
1490         val_a = json_node_get_double (node_a);
1491 
1492       if (value_type_b == JSON_VALUE_INT)
1493         val_b = json_node_get_int (node_b);
1494       else
1495         val_b = json_node_get_double (node_b);
1496 
1497       return (val_a == val_b);
1498     }
1499     case JSON_VALUE_INVALID:
1500     default:
1501       g_assert_not_reached ();
1502     }
1503 }
1504