Coverage Report

Created: 2025-10-10 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/json-glib/json-glib/json-array.c
Line
Count
Source
1
/* json-array.c - JSON array implementation
2
 * 
3
 * This file is part of JSON-GLib
4
 * Copyright (C) 2007  OpenedHand Ltd.
5
 * Copyright (C) 2009  Intel Corp.
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19
 *
20
 * Author:
21
 *   Emmanuele Bassi  <ebassi@linux.intel.com>
22
 */
23
24
#include "config.h"
25
26
#include "json-types-private.h"
27
28
/**
29
 * JsonArray:
30
 *
31
 * `JsonArray` is the representation of the array type inside JSON.
32
 *
33
 * A `JsonArray` contains [struct@Json.Node] elements, which may contain
34
 * fundamental types, other arrays or objects.
35
 *
36
 * Since arrays can be arbitrarily big, copying them can be expensive; for
37
 * this reason, they are reference counted. You can control the lifetime of
38
 * a `JsonArray` using [method@Json.Array.ref] and [method@Json.Array.unref].
39
 *
40
 * To append an element, use [method@Json.Array.add_element].
41
 *
42
 * To extract an element at a given index, use [method@Json.Array.get_element].
43
 *
44
 * To retrieve the entire array in list form, use [method@Json.Array.get_elements].
45
 *
46
 * To retrieve the length of the array, use [method@Json.Array.get_length].
47
 */
48
49
0
G_DEFINE_BOXED_TYPE (JsonArray, json_array, json_array_ref, json_array_unref);
50
0
51
0
/**
52
0
 * json_array_new: (constructor)
53
0
 *
54
0
 * Creates a new array.
55
0
 *
56
0
 * Return value: (transfer full): the newly created array
57
0
 */
58
0
JsonArray *
59
0
json_array_new (void)
60
0
{
61
0
  JsonArray *array;
62
63
0
  array = g_slice_new0 (JsonArray);
64
65
0
  array->ref_count = 1;
66
0
  array->elements = g_ptr_array_new ();
67
68
0
  return array;
69
0
}
70
71
/**
72
 * json_array_sized_new: (constructor)
73
 * @n_elements: number of slots to pre-allocate
74
 *
75
 * Creates a new array with `n_elements` slots already allocated.
76
 *
77
 * Return value: (transfer full): the newly created array
78
 */
79
JsonArray *
80
json_array_sized_new (guint n_elements)
81
0
{
82
0
  JsonArray *array;
83
84
0
  array = g_slice_new0 (JsonArray);
85
  
86
0
  array->ref_count = 1;
87
0
  array->elements = g_ptr_array_sized_new (n_elements);
88
89
0
  return array;
90
0
}
91
92
/**
93
 * json_array_ref:
94
 * @array: the array to reference
95
 *
96
 * Acquires a reference on the given array.
97
 *
98
 * Return value: (transfer none): the passed array, with the reference count
99
 *   increased by one
100
 */
101
JsonArray *
102
json_array_ref (JsonArray *array)
103
0
{
104
0
  g_return_val_if_fail (array != NULL, NULL);
105
0
  g_return_val_if_fail (array->ref_count > 0, NULL);
106
107
0
  array->ref_count++;
108
109
0
  return array;
110
0
}
111
112
/**
113
 * json_array_unref:
114
 * @array: the array to unreference
115
 *
116
 * Releases a reference on the given array.
117
 *
118
 * If the reference count reaches zero, the array is destroyed and all
119
 * its allocated resources are freed.
120
 */
121
void
122
json_array_unref (JsonArray *array)
123
0
{
124
0
  g_return_if_fail (array != NULL);
125
0
  g_return_if_fail (array->ref_count > 0);
126
127
0
  if (--array->ref_count == 0)
128
0
    {
129
0
      guint i;
130
131
0
      for (i = 0; i < array->elements->len; i++)
132
0
        json_node_unref (g_ptr_array_index (array->elements, i));
133
134
0
      g_ptr_array_free (array->elements, TRUE);
135
0
      array->elements = NULL;
136
137
0
      g_slice_free (JsonArray, array);
138
0
    }
139
0
}
140
141
/**
142
 * json_array_seal:
143
 * @array: the array to seal
144
 *
145
 * Seals the given array, making it immutable to further changes.
146
 *
147
 * This function will recursively seal all elements in the array too.
148
 *
149
 * If the `array` is already immutable, this is a no-op.
150
 *
151
 * Since: 1.2
152
 */
153
void
154
json_array_seal (JsonArray *array)
155
0
{
156
0
  guint i;
157
158
0
  g_return_if_fail (array != NULL);
159
0
  g_return_if_fail (array->ref_count > 0);
160
161
0
  if (array->immutable)
162
0
    return;
163
164
  /* Propagate to all members. */
165
0
  for (i = 0; i < array->elements->len; i++)
166
0
    json_node_seal (g_ptr_array_index (array->elements, i));
167
168
0
  array->immutable_hash = json_array_hash (array);
169
0
  array->immutable = TRUE;
170
0
}
171
172
/**
173
 * json_array_is_immutable:
174
 * @array: a JSON array
175
 *
176
 * Check whether the given `array` has been marked as immutable by calling
177
 * [method@Json.Array.seal] on it.
178
 *
179
 * Since: 1.2
180
 * Returns: %TRUE if the array is immutable
181
 */
182
gboolean
183
json_array_is_immutable (JsonArray *array)
184
0
{
185
0
  g_return_val_if_fail (array != NULL, FALSE);
186
0
  g_return_val_if_fail (array->ref_count > 0, FALSE);
187
188
0
  return array->immutable;
189
0
}
190
191
/**
192
 * json_array_get_elements:
193
 * @array: a JSON array
194
 *
195
 * Retrieves all the elements of an array as a list of nodes.
196
 *
197
 * Return value: (element-type JsonNode) (transfer container) (nullable): the elements
198
 *   of the array
199
 */
200
GList *
201
json_array_get_elements (JsonArray *array)
202
0
{
203
0
  GList *retval;
204
0
  guint i;
205
206
0
  g_return_val_if_fail (array != NULL, NULL);
207
208
0
  retval = NULL;
209
0
  for (i = 0; i < array->elements->len; i++)
210
0
    retval = g_list_prepend (retval,
211
0
                             g_ptr_array_index (array->elements, i));
212
213
0
  return g_list_reverse (retval);
214
0
}
215
216
/**
217
 * json_array_dup_element:
218
 * @array: a JSON array
219
 * @index_: the index of the element to retrieve
220
 *
221
 * Retrieves a copy of the element at the given position in the array.
222
 *
223
 * Return value: (transfer full): a copy of the element at the given position
224
 *
225
 * Since: 0.6
226
 */
227
JsonNode *
228
json_array_dup_element (JsonArray *array,
229
                        guint      index_)
230
0
{
231
0
  JsonNode *retval;
232
233
0
  g_return_val_if_fail (array != NULL, NULL);
234
0
  g_return_val_if_fail (index_ < array->elements->len, NULL);
235
236
0
  retval = json_array_get_element (array, index_);
237
0
  if (!retval)
238
0
    return NULL;
239
240
0
  return json_node_copy (retval);
241
0
}
242
243
/**
244
 * json_array_get_element:
245
 * @array: a JSON array
246
 * @index_: the index of the element to retrieve
247
 *
248
 * Retrieves the element at the given position in the array.
249
 *
250
 * Return value: (transfer none): the element at the given position
251
 */
252
JsonNode *
253
json_array_get_element (JsonArray *array,
254
                        guint      index_)
255
0
{
256
0
  g_return_val_if_fail (array != NULL, NULL);
257
0
  g_return_val_if_fail (index_ < array->elements->len, NULL);
258
259
0
  return g_ptr_array_index (array->elements, index_);
260
0
}
261
262
/**
263
 * json_array_get_int_element:
264
 * @array: a JSON array
265
 * @index_: the index of the element to retrieve
266
 *
267
 * Conveniently retrieves the integer value of the element at the given
268
 * position inside an array.
269
 *
270
 * See also: [method@Json.Array.get_element], [method@Json.Node.get_int]
271
 *
272
 * Return value: the integer value
273
 *
274
 * Since: 0.8
275
 */
276
gint64
277
json_array_get_int_element (JsonArray *array,
278
                            guint      index_)
279
0
{
280
0
  JsonNode *node;
281
282
0
  g_return_val_if_fail (array != NULL, 0);
283
0
  g_return_val_if_fail (index_ < array->elements->len, 0);
284
285
0
  node = g_ptr_array_index (array->elements, index_);
286
0
  g_return_val_if_fail (node != NULL, 0);
287
0
  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0);
288
289
0
  return json_node_get_int (node);
290
0
}
291
292
/**
293
 * json_array_get_double_element:
294
 * @array: a JSON array
295
 * @index_: the index of the element to retrieve
296
 *
297
 * Conveniently retrieves the floating point value of the element at
298
 * the given position inside an array.
299
 *
300
 * See also: [method@Json.Array.get_element], [method@Json.Node.get_double]
301
 *
302
 * Return value: the floating point value
303
 *
304
 * Since: 0.8
305
 */
306
gdouble
307
json_array_get_double_element (JsonArray *array,
308
                               guint      index_)
309
0
{
310
0
  JsonNode *node;
311
312
0
  g_return_val_if_fail (array != NULL, 0.0);
313
0
  g_return_val_if_fail (index_ < array->elements->len, 0.0);
314
315
0
  node = g_ptr_array_index (array->elements, index_);
316
0
  g_return_val_if_fail (node != NULL, 0.0);
317
0
  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0.0);
318
319
0
  return json_node_get_double (node);
320
0
}
321
322
/**
323
 * json_array_get_boolean_element:
324
 * @array: a JSON array
325
 * @index_: the index of the element to retrieve
326
 *
327
 * Conveniently retrieves the boolean value of the element at the given
328
 * position inside an array.
329
 *
330
 * See also: [method@Json.Array.get_element], [method@Json.Node.get_boolean]
331
 *
332
 * Return value: the boolean value
333
 *
334
 * Since: 0.8
335
 */
336
gboolean
337
json_array_get_boolean_element (JsonArray *array,
338
                                guint      index_)
339
0
{
340
0
  JsonNode *node;
341
342
0
  g_return_val_if_fail (array != NULL, FALSE);
343
0
  g_return_val_if_fail (index_ < array->elements->len, FALSE);
344
345
0
  node = g_ptr_array_index (array->elements, index_);
346
0
  g_return_val_if_fail (node != NULL, FALSE);
347
0
  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, FALSE);
348
349
0
  return json_node_get_boolean (node);
350
0
}
351
352
/**
353
 * json_array_get_string_element:
354
 * @array: a JSON array
355
 * @index_: the index of the element to retrieve
356
 *
357
 * Conveniently retrieves the string value of the element at the given
358
 * position inside an array.
359
 *
360
 * See also: [method@Json.Array.get_element], [method@Json.Node.get_string]
361
 *
362
 * Return value: (transfer none): the string value
363
 *
364
 * Since: 0.8
365
 */
366
const gchar *
367
json_array_get_string_element (JsonArray *array,
368
                               guint      index_)
369
0
{
370
0
  JsonNode *node;
371
372
0
  g_return_val_if_fail (array != NULL, NULL);
373
0
  g_return_val_if_fail (index_ < array->elements->len, NULL);
374
375
0
  node = g_ptr_array_index (array->elements, index_);
376
0
  g_return_val_if_fail (node != NULL, NULL);
377
0
  g_return_val_if_fail (JSON_NODE_HOLDS_VALUE (node) || JSON_NODE_HOLDS_NULL (node), NULL);
378
379
0
  if (JSON_NODE_HOLDS_NULL (node))
380
0
    return NULL;
381
382
0
  return json_node_get_string (node);
383
0
}
384
385
/**
386
 * json_array_get_null_element:
387
 * @array: a JSON array
388
 * @index_: the index of the element to retrieve
389
 *
390
 * Conveniently checks whether the element at the given position inside the
391
 * array contains a `null` value.
392
 *
393
 * See also: [method@Json.Array.get_element], [method@Json.Node.is_null]
394
 *
395
 * Return value: `TRUE` if the element is `null`
396
 *
397
 * Since: 0.8
398
 */
399
gboolean
400
json_array_get_null_element (JsonArray *array,
401
                             guint      index_)
402
0
{
403
0
  JsonNode *node;
404
405
0
  g_return_val_if_fail (array != NULL, FALSE);
406
0
  g_return_val_if_fail (index_ < array->elements->len, FALSE);
407
408
0
  node = g_ptr_array_index (array->elements, index_);
409
0
  g_return_val_if_fail (node != NULL, FALSE);
410
411
0
  if (JSON_NODE_HOLDS_NULL (node))
412
0
    return TRUE;
413
414
0
  if (JSON_NODE_HOLDS_ARRAY (node))
415
0
    return json_node_get_array (node) == NULL;
416
417
0
  if (JSON_NODE_HOLDS_OBJECT (node))
418
0
    return json_node_get_object (node) == NULL;
419
420
0
  return FALSE;
421
0
}
422
423
/**
424
 * json_array_get_array_element:
425
 * @array: a JSON array
426
 * @index_: the index of the element to retrieve
427
 *
428
 * Conveniently retrieves the array at the given position inside an array.
429
 *
430
 * See also: [method@Json.Array.get_element], [method@Json.Node.get_array]
431
 *
432
 * Return value: (transfer none): the array
433
 *
434
 * Since: 0.8
435
 */
436
JsonArray *
437
json_array_get_array_element (JsonArray *array,
438
                              guint      index_)
439
0
{
440
0
  JsonNode *node;
441
442
0
  g_return_val_if_fail (array != NULL, NULL);
443
0
  g_return_val_if_fail (index_ < array->elements->len, NULL);
444
445
0
  node = g_ptr_array_index (array->elements, index_);
446
0
  g_return_val_if_fail (node != NULL, NULL);
447
0
  g_return_val_if_fail (JSON_NODE_HOLDS_ARRAY (node) || JSON_NODE_HOLDS_NULL (node), NULL);
448
449
0
  if (JSON_NODE_HOLDS_NULL (node))
450
0
    return NULL;
451
452
0
  return json_node_get_array (node);
453
0
}
454
455
/**
456
 * json_array_get_object_element:
457
 * @array: a JSON array
458
 * @index_: the index of the element to retrieve
459
 *
460
 * Conveniently retrieves the object at the given position inside an array.
461
 *
462
 * See also: [method@Json.Array.get_element], [method@Json.Node.get_object]
463
 *
464
 * Return value: (transfer none): the object
465
 *
466
 * Since: 0.8
467
 */
468
JsonObject *
469
json_array_get_object_element (JsonArray *array,
470
                               guint      index_)
471
0
{
472
0
  JsonNode *node;
473
474
0
  g_return_val_if_fail (array != NULL, NULL);
475
0
  g_return_val_if_fail (index_ < array->elements->len, NULL);
476
477
0
  node = g_ptr_array_index (array->elements, index_);
478
0
  g_return_val_if_fail (node != NULL, NULL);
479
0
  g_return_val_if_fail (JSON_NODE_HOLDS_OBJECT (node) || JSON_NODE_HOLDS_NULL (node), NULL);
480
481
0
  if (JSON_NODE_HOLDS_NULL (node))
482
0
    return NULL;
483
484
0
  return json_node_get_object (node);
485
0
}
486
487
/**
488
 * json_array_get_length:
489
 * @array: a JSON array
490
 *
491
 * Retrieves the length of the given array
492
 *
493
 * Return value: the length of the array
494
 */
495
guint
496
json_array_get_length (JsonArray *array)
497
0
{
498
0
  g_return_val_if_fail (array != NULL, 0);
499
500
0
  return array->elements->len;
501
0
}
502
503
/**
504
 * json_array_add_element:
505
 * @array: a JSON array
506
 * @node: (transfer full): the element to add
507
 *
508
 * Appends the given `node` inside an array.
509
 */
510
void
511
json_array_add_element (JsonArray *array,
512
                        JsonNode  *node)
513
0
{
514
0
  g_return_if_fail (array != NULL);
515
0
  g_return_if_fail (node != NULL);
516
517
0
  g_ptr_array_add (array->elements, node);
518
0
}
519
520
/**
521
 * json_array_add_int_element:
522
 * @array: a JSON array
523
 * @value: the integer value to add
524
 *
525
 * Conveniently adds the given integer value into an array.
526
 *
527
 * See also: [method@Json.Array.add_element], [method@Json.Node.set_int]
528
 *
529
 * Since: 0.8
530
 */
531
void
532
json_array_add_int_element (JsonArray *array,
533
                            gint64     value)
534
0
{
535
0
  g_return_if_fail (array != NULL);
536
537
0
  json_array_add_element (array, json_node_init_int (json_node_alloc (), value));
538
0
}
539
540
/**
541
 * json_array_add_double_element:
542
 * @array: a JSON array
543
 * @value: the floating point value to add
544
 *
545
 * Conveniently adds the given floating point value into an array.
546
 *
547
 * See also: [method@Json.Array.add_element], [method@Json.Node.set_double]
548
 *
549
 * Since: 0.8
550
 */
551
void
552
json_array_add_double_element (JsonArray *array,
553
                               gdouble    value)
554
0
{
555
0
  g_return_if_fail (array != NULL);
556
557
0
  json_array_add_element (array, json_node_init_double (json_node_alloc (), value));
558
0
}
559
560
/**
561
 * json_array_add_boolean_element:
562
 * @array: a JSON array
563
 * @value: the boolean value to add
564
 *
565
 * Conveniently adds the given boolean value into an array.
566
 *
567
 * See also: [method@Json.Array.add_element], [method@Json.Node.set_boolean]
568
 *
569
 * Since: 0.8
570
 */
571
void
572
json_array_add_boolean_element (JsonArray *array,
573
                                gboolean   value)
574
0
{
575
0
  g_return_if_fail (array != NULL);
576
577
0
  json_array_add_element (array, json_node_init_boolean (json_node_alloc (), value));
578
0
}
579
580
/**
581
 * json_array_add_string_element:
582
 * @array: a JSON array
583
 * @value: the string value to add
584
 *
585
 * Conveniently adds the given string value into an array.
586
 *
587
 * See also: [method@Json.Array.add_element], [method@Json.Node.set_string]
588
 *
589
 * Since: 0.8
590
 */
591
void
592
json_array_add_string_element (JsonArray   *array,
593
                               const gchar *value)
594
0
{
595
0
  JsonNode *node;
596
597
0
  g_return_if_fail (array != NULL);
598
599
0
  node = json_node_alloc ();
600
601
0
  if (value != NULL)
602
0
    json_node_init_string (node, value);
603
0
  else
604
0
    json_node_init_null (node);
605
606
0
  json_array_add_element (array, node);
607
0
}
608
609
/**
610
 * json_array_add_null_element:
611
 * @array: a JSON array
612
 *
613
 * Conveniently adds a `null` element into an array
614
 *
615
 * See also: [method@Json.Array.add_element], `JSON_NODE_NULL`
616
 *
617
 * Since: 0.8
618
 */
619
void
620
json_array_add_null_element (JsonArray *array)
621
0
{
622
0
  g_return_if_fail (array != NULL);
623
624
0
  json_array_add_element (array, json_node_init_null (json_node_alloc ()));
625
0
}
626
627
/**
628
 * json_array_add_array_element:
629
 * @array: a JSON array
630
 * @value: (nullable) (transfer full): the array to add
631
 *
632
 * Conveniently adds an array element into an array.
633
 *
634
 * If `value` is `NULL`, a `null` element will be added instead.
635
 *
636
 * See also: [method@Json.Array.add_element], [method@Json.Node.take_array]
637
 *
638
 * Since: 0.8
639
 */
640
void
641
json_array_add_array_element (JsonArray *array,
642
                              JsonArray *value)
643
0
{
644
0
  JsonNode *node;
645
646
0
  g_return_if_fail (array != NULL);
647
648
0
  node = json_node_alloc ();
649
650
0
  if (value != NULL)
651
0
    {
652
0
      json_node_init_array (node, value);
653
0
      json_array_unref (value);
654
0
    }
655
0
  else
656
0
    json_node_init_null (node);
657
658
0
  json_array_add_element (array, node);
659
0
}
660
661
/**
662
 * json_array_add_object_element:
663
 * @array: a JSON array
664
 * @value: (transfer full) (nullable): the object to add
665
 *
666
 * Conveniently adds an object into an array.
667
 *
668
 * If `value` is `NULL`, a `null` element will be added instead.
669
 *
670
 * See also: [method@Json.Array.add_element], [method@Json.Node.take_object]
671
 *
672
 * Since: 0.8
673
 */
674
void
675
json_array_add_object_element (JsonArray  *array,
676
                               JsonObject *value)
677
0
{
678
0
  JsonNode *node;
679
680
0
  g_return_if_fail (array != NULL);
681
682
0
  node = json_node_alloc ();
683
684
0
  if (value != NULL)
685
0
    {
686
0
      json_node_init_object (node, value);
687
0
      json_object_unref (value);
688
0
    }
689
0
  else
690
0
    json_node_init_null (node);
691
692
0
  json_array_add_element (array, node);
693
0
}
694
695
/**
696
 * json_array_remove_element:
697
 * @array: a JSON array
698
 * @index_: the position of the element to be removed
699
 *
700
 * Removes the element at the given position inside an array.
701
 *
702
 * This function will release the reference held on the element.
703
 */
704
void
705
json_array_remove_element (JsonArray *array,
706
                           guint      index_)
707
0
{
708
0
  g_return_if_fail (array != NULL);
709
0
  g_return_if_fail (index_ < array->elements->len);
710
711
0
  json_node_unref (g_ptr_array_remove_index (array->elements, index_));
712
0
}
713
714
/**
715
 * json_array_foreach_element:
716
 * @array: a JSON array
717
 * @func: (scope call): the function to be called on each element
718
 * @data: (closure): data to be passed to the function
719
 *
720
 * Iterates over all elements of an array, and calls a function on
721
 * each one of them.
722
 *
723
 * It is safe to change the value of an element of the array while
724
 * iterating over it, but it is not safe to add or remove elements
725
 * from the array.
726
 *
727
 * Since: 0.8
728
 */
729
void
730
json_array_foreach_element (JsonArray        *array,
731
                            JsonArrayForeach  func,
732
                            gpointer          data)
733
0
{
734
0
  g_return_if_fail (array != NULL);
735
0
  g_return_if_fail (func != NULL);
736
737
0
  for (guint i = 0; i < array->elements->len; i++)
738
0
    {
739
0
      JsonNode *element_node;
740
741
0
      element_node = g_ptr_array_index (array->elements, i);
742
743
0
      (* func) (array, i, element_node, data);
744
0
    }
745
0
}
746
747
/**
748
 * json_array_hash:
749
 * @key: (type JsonArray) (not nullable): a JSON array to hash
750
 *
751
 * Calculates a hash value for the given `key`.
752
 *
753
 * The hash is calculated over the array and all its elements, recursively.
754
 *
755
 * If the array is immutable, this is a fast operation; otherwise, it scales
756
 * proportionally with the length of the array.
757
 *
758
 * Returns: hash value for the key
759
 * Since: 1.2
760
 */
761
guint
762
json_array_hash (gconstpointer key)
763
0
{
764
0
  JsonArray *array;  /* unowned */
765
0
  guint hash = 0;
766
0
  guint i;
767
768
0
  g_return_val_if_fail (key != NULL, 0);
769
770
0
  array = (JsonArray *) key;
771
772
  /* If the array is immutable, we can use the calculated hash. */
773
0
  if (array->immutable)
774
0
    return array->immutable_hash;
775
776
  /* Otherwise, calculate the hash. */
777
0
  for (i = 0; i < array->elements->len; i++)
778
0
    {
779
0
      JsonNode *node = g_ptr_array_index (array->elements, i);
780
0
      hash ^= (i ^ json_node_hash (node));
781
0
    }
782
783
0
  return hash;
784
0
}
785
786
/**
787
 * json_array_equal:
788
 * @a: (type JsonArray) (not nullable): a JSON array
789
 * @b: (type JsonArray) (not nullable): another JSON array
790
 *
791
 * Check whether two arrays are equal.
792
 *
793
 * Equality is defined as:
794
 *
795
 *  - the array have the same number of elements
796
 *  - the values of elements in corresponding positions are equal
797
 *
798
 * Returns: `TRUE` if the arrays are equal, and `FALSE` otherwise
799
 * Since: 1.2
800
 */
801
gboolean
802
json_array_equal (gconstpointer a,
803
                  gconstpointer b)
804
0
{
805
0
  JsonArray *array_a, *array_b;  /* unowned */
806
0
  guint length_a, length_b, i;
807
808
0
  g_return_val_if_fail (a != NULL, FALSE);
809
0
  g_return_val_if_fail (b != NULL, FALSE);
810
811
0
  array_a = (JsonArray *) a;
812
0
  array_b = (JsonArray *) b;
813
814
  /* Identity comparison. */
815
0
  if (array_a == array_b)
816
0
    return TRUE;
817
818
  /* Check lengths. */
819
0
  length_a = json_array_get_length (array_a);
820
0
  length_b = json_array_get_length (array_b);
821
822
0
  if (length_a != length_b)
823
0
    return FALSE;
824
825
  /* Check elements. */
826
0
  for (i = 0; i < length_a; i++)
827
0
    {
828
0
      JsonNode *child_a, *child_b;  /* unowned */
829
830
0
      child_a = json_array_get_element (array_a, i);
831
0
      child_b = json_array_get_element (array_b, i);
832
833
0
      if (!json_node_equal (child_a, child_b))
834
0
        return FALSE;
835
0
    }
836
837
0
  return TRUE;
838
0
}