/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 | } |