Coverage Report

Created: 2025-07-11 06:47

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