/src/tinysparql/subprojects/json-glib-1.10.6/json-glib/json-object.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* json-object.c - JSON object implementation |
2 | | * |
3 | | * This file is part of JSON-GLib |
4 | | * |
5 | | * SPDX-FileCopyrightText: 2007 OpenedHand Ltd. |
6 | | * SPDX-FileCopyrightText: 2009 Intel Corp. |
7 | | * SPDX-License-Identifier: LGPL-2.1-or-later |
8 | | * |
9 | | * This library is free software; you can redistribute it and/or |
10 | | * modify it under the terms of the GNU Lesser General Public |
11 | | * License as published by the Free Software Foundation; either |
12 | | * version 2.1 of the License, or (at your option) any later version. |
13 | | * |
14 | | * This library is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 | | * Lesser General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU Lesser General Public |
20 | | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
21 | | * |
22 | | * Author: |
23 | | * Emmanuele Bassi <ebassi@linux.intel.com> |
24 | | */ |
25 | | |
26 | | #include "config.h" |
27 | | |
28 | | #include <string.h> |
29 | | #include <glib.h> |
30 | | |
31 | | #include "json-types-private.h" |
32 | | |
33 | | /** |
34 | | * JsonObject: |
35 | | * |
36 | | * `JsonObject` is the representation of the object type inside JSON. |
37 | | * |
38 | | * A `JsonObject` contains [struct@Json.Node] "members", which may contain |
39 | | * fundamental types, arrays or other objects; each member of an object is |
40 | | * accessed using a unique string, or "name". |
41 | | * |
42 | | * Since objects can be arbitrarily big, copying them can be expensive; for |
43 | | * this reason they are reference counted. You can control the lifetime of |
44 | | * a `JsonObject` using [method@Json.Object.ref] and [method@Json.Object.unref]. |
45 | | * |
46 | | * To add or overwrite a member with a given name, use [method@Json.Object.set_member]. |
47 | | * |
48 | | * To extract a member with a given name, use [method@Json.Object.get_member]. |
49 | | * |
50 | | * To retrieve the list of members, use [method@Json.Object.get_members]. |
51 | | * |
52 | | * To retrieve the size of the object (that is, the number of members it has), |
53 | | * use [method@Json.Object.get_size]. |
54 | | */ |
55 | | |
56 | | G_DEFINE_BOXED_TYPE (JsonObject, json_object, json_object_ref, json_object_unref); |
57 | | |
58 | | /** |
59 | | * json_object_new: (constructor) |
60 | | * |
61 | | * Creates a new object. |
62 | | * |
63 | | * Returns: (transfer full): the newly created object |
64 | | */ |
65 | | JsonObject * |
66 | | json_object_new (void) |
67 | 0 | { |
68 | 0 | JsonObject *object; |
69 | |
|
70 | 0 | object = g_new0 (JsonObject, 1); |
71 | |
|
72 | 0 | g_ref_count_init (&object->ref_count); |
73 | |
|
74 | 0 | object->age = 0; |
75 | 0 | object->members = g_hash_table_new_full (g_str_hash, g_str_equal, |
76 | 0 | g_free, |
77 | 0 | (GDestroyNotify) json_node_unref); |
78 | 0 | g_queue_init (&object->members_ordered); |
79 | |
|
80 | 0 | return object; |
81 | 0 | } |
82 | | |
83 | | /** |
84 | | * json_object_ref: |
85 | | * @object: a JSON object |
86 | | * |
87 | | * Acquires a reference on the given object. |
88 | | * |
89 | | * Returns: (transfer none): the given object, with the reference count |
90 | | * increased by one. |
91 | | */ |
92 | | JsonObject * |
93 | | json_object_ref (JsonObject *object) |
94 | 0 | { |
95 | 0 | g_return_val_if_fail (object != NULL, NULL); |
96 | | |
97 | 0 | g_ref_count_inc (&object->ref_count); |
98 | |
|
99 | 0 | return object; |
100 | 0 | } |
101 | | |
102 | | /** |
103 | | * json_object_unref: |
104 | | * @object: a JSON object |
105 | | * |
106 | | * Releases a reference on the given object. |
107 | | * |
108 | | * If the reference count reaches zero, the object is destroyed and |
109 | | * all its resources are freed. |
110 | | */ |
111 | | void |
112 | | json_object_unref (JsonObject *object) |
113 | 0 | { |
114 | 0 | g_return_if_fail (object != NULL); |
115 | | |
116 | 0 | if (g_ref_count_dec (&object->ref_count)) |
117 | 0 | { |
118 | 0 | g_queue_clear (&object->members_ordered); |
119 | 0 | g_hash_table_destroy (object->members); |
120 | 0 | object->members = NULL; |
121 | |
|
122 | 0 | g_free (object); |
123 | 0 | } |
124 | 0 | } |
125 | | |
126 | | /** |
127 | | * json_object_seal: |
128 | | * @object: a JSON object |
129 | | * |
130 | | * Seals the object, making it immutable to further changes. |
131 | | * |
132 | | * This function will recursively seal all members of the object too. |
133 | | * |
134 | | * If the object is already immutable, this is a no-op. |
135 | | * |
136 | | * Since: 1.2 |
137 | | */ |
138 | | void |
139 | | json_object_seal (JsonObject *object) |
140 | 0 | { |
141 | 0 | JsonObjectIter iter; |
142 | 0 | JsonNode *node; |
143 | |
|
144 | 0 | g_return_if_fail (object != NULL); |
145 | | |
146 | 0 | if (object->immutable) |
147 | 0 | return; |
148 | | |
149 | | /* Propagate to all members. */ |
150 | 0 | json_object_iter_init (&iter, object); |
151 | |
|
152 | 0 | while (json_object_iter_next (&iter, NULL, &node)) |
153 | 0 | json_node_seal (node); |
154 | |
|
155 | 0 | object->immutable_hash = json_object_hash (object); |
156 | 0 | object->immutable = TRUE; |
157 | 0 | } |
158 | | |
159 | | /** |
160 | | * json_object_is_immutable: |
161 | | * @object: a JSON object |
162 | | * |
163 | | * Checks whether the given object has been marked as immutable by calling |
164 | | * [method@Json.Object.seal] on it. |
165 | | * |
166 | | * Since: 1.2 |
167 | | * Returns: `TRUE` if the object is immutable |
168 | | */ |
169 | | gboolean |
170 | | json_object_is_immutable (JsonObject *object) |
171 | 0 | { |
172 | 0 | g_return_val_if_fail (object != NULL, FALSE); |
173 | | |
174 | 0 | return object->immutable; |
175 | 0 | } |
176 | | |
177 | | static inline void |
178 | | object_set_member_internal (JsonObject *object, |
179 | | const gchar *member_name, |
180 | | JsonNode *node) |
181 | 0 | { |
182 | 0 | gchar *name = g_strdup (member_name); |
183 | |
|
184 | 0 | if (g_hash_table_lookup (object->members, name) == NULL) |
185 | 0 | { |
186 | 0 | g_queue_push_tail (&object->members_ordered, name); |
187 | 0 | object->age += 1; |
188 | 0 | } |
189 | 0 | else |
190 | 0 | { |
191 | 0 | GList *l; |
192 | | |
193 | | /* if the member already exists then we need to replace the |
194 | | * pointer to its name, to avoid keeping invalid pointers |
195 | | * once we replace the key in the hash table |
196 | | */ |
197 | 0 | l = g_queue_find_custom (&object->members_ordered, name, (GCompareFunc) strcmp); |
198 | 0 | if (l != NULL) |
199 | 0 | l->data = name; |
200 | 0 | } |
201 | |
|
202 | 0 | g_hash_table_replace (object->members, name, node); |
203 | 0 | } |
204 | | |
205 | | /** |
206 | | * json_object_add_member: |
207 | | * @object: a JSON object |
208 | | * @member_name: the name of the member |
209 | | * @node: (transfer full): the value of the member |
210 | | * |
211 | | * Adds a new member for the given name and value into an object. |
212 | | * |
213 | | * This function will return if the object already contains a member |
214 | | * with the same name. |
215 | | * |
216 | | * Deprecated: 0.8: Use [method@Json.Object.set_member] instead |
217 | | */ |
218 | | void |
219 | | json_object_add_member (JsonObject *object, |
220 | | const gchar *member_name, |
221 | | JsonNode *node) |
222 | 0 | { |
223 | 0 | g_return_if_fail (object != NULL); |
224 | 0 | g_return_if_fail (member_name != NULL); |
225 | 0 | g_return_if_fail (node != NULL); |
226 | | |
227 | 0 | if (json_object_has_member (object, member_name)) |
228 | 0 | { |
229 | 0 | g_warning ("JsonObject already has a `%s' member of type `%s'", |
230 | 0 | member_name, |
231 | 0 | json_node_type_name (node)); |
232 | 0 | return; |
233 | 0 | } |
234 | | |
235 | 0 | object_set_member_internal (object, member_name, node); |
236 | 0 | } |
237 | | |
238 | | /** |
239 | | * json_object_set_member: |
240 | | * @object: a JSON object |
241 | | * @member_name: the name of the member |
242 | | * @node: (transfer full): the value of the member |
243 | | * |
244 | | * Sets the value of a member inside an object. |
245 | | * |
246 | | * If the object does not have a member with the given name, a new member |
247 | | * is created. |
248 | | * |
249 | | * If the object already has a member with the given name, the current |
250 | | * value is overwritten with the new. |
251 | | * |
252 | | * Since: 0.8 |
253 | | */ |
254 | | void |
255 | | json_object_set_member (JsonObject *object, |
256 | | const gchar *member_name, |
257 | | JsonNode *node) |
258 | 0 | { |
259 | 0 | JsonNode *old_node; |
260 | |
|
261 | 0 | g_return_if_fail (object != NULL); |
262 | 0 | g_return_if_fail (member_name != NULL); |
263 | 0 | g_return_if_fail (node != NULL); |
264 | | |
265 | 0 | old_node = g_hash_table_lookup (object->members, member_name); |
266 | 0 | if (old_node == NULL) |
267 | 0 | goto set_member; |
268 | | |
269 | 0 | if (old_node == node) |
270 | 0 | return; |
271 | | |
272 | 0 | set_member: |
273 | 0 | object_set_member_internal (object, member_name, node); |
274 | 0 | } |
275 | | |
276 | | /** |
277 | | * json_object_set_int_member: |
278 | | * @object: a JSON object |
279 | | * @member_name: the name of the member |
280 | | * @value: the value of the member |
281 | | * |
282 | | * Convenience function for setting an object member with an integer value. |
283 | | * |
284 | | * See also: [method@Json.Object.set_member], [method@Json.Node.init_int] |
285 | | * |
286 | | * Since: 0.8 |
287 | | */ |
288 | | void |
289 | | json_object_set_int_member (JsonObject *object, |
290 | | const gchar *member_name, |
291 | | gint64 value) |
292 | 0 | { |
293 | 0 | g_return_if_fail (object != NULL); |
294 | 0 | g_return_if_fail (member_name != NULL); |
295 | | |
296 | 0 | object_set_member_internal (object, member_name, json_node_init_int (json_node_alloc (), value)); |
297 | 0 | } |
298 | | |
299 | | /** |
300 | | * json_object_set_double_member: |
301 | | * @object: a JSON object |
302 | | * @member_name: the name of the member |
303 | | * @value: the value of the member |
304 | | * |
305 | | * Convenience function for setting an object member with a floating point value. |
306 | | * |
307 | | * See also: [method@Json.Object.set_member], [method@Json.Node.init_double] |
308 | | * |
309 | | * Since: 0.8 |
310 | | */ |
311 | | void |
312 | | json_object_set_double_member (JsonObject *object, |
313 | | const gchar *member_name, |
314 | | gdouble value) |
315 | 0 | { |
316 | 0 | g_return_if_fail (object != NULL); |
317 | 0 | g_return_if_fail (member_name != NULL); |
318 | | |
319 | 0 | object_set_member_internal (object, member_name, json_node_init_double (json_node_alloc (), value)); |
320 | 0 | } |
321 | | |
322 | | /** |
323 | | * json_object_set_boolean_member: |
324 | | * @object: a JSON object |
325 | | * @member_name: the name of the member |
326 | | * @value: the value of the member |
327 | | * |
328 | | * Convenience function for setting an object member with a boolean value. |
329 | | * |
330 | | * See also: [method@Json.Object.set_member], [method@Json.Node.init_boolean] |
331 | | * |
332 | | * Since: 0.8 |
333 | | */ |
334 | | void |
335 | | json_object_set_boolean_member (JsonObject *object, |
336 | | const gchar *member_name, |
337 | | gboolean value) |
338 | 0 | { |
339 | 0 | g_return_if_fail (object != NULL); |
340 | 0 | g_return_if_fail (member_name != NULL); |
341 | | |
342 | 0 | object_set_member_internal (object, member_name, json_node_init_boolean (json_node_alloc (), value)); |
343 | 0 | } |
344 | | |
345 | | /** |
346 | | * json_object_set_string_member: |
347 | | * @object: a JSON object |
348 | | * @member_name: the name of the member |
349 | | * @value: the value of the member |
350 | | * |
351 | | * Convenience function for setting an object member with a string value. |
352 | | * |
353 | | * See also: [method@Json.Object.set_member], [method@Json.Node.init_string] |
354 | | * |
355 | | * Since: 0.8 |
356 | | */ |
357 | | void |
358 | | json_object_set_string_member (JsonObject *object, |
359 | | const gchar *member_name, |
360 | | const gchar *value) |
361 | 0 | { |
362 | 0 | JsonNode *node; |
363 | |
|
364 | 0 | g_return_if_fail (object != NULL); |
365 | 0 | g_return_if_fail (member_name != NULL); |
366 | | |
367 | 0 | node = json_node_alloc (); |
368 | |
|
369 | 0 | if (value != NULL) |
370 | 0 | json_node_init_string (node, value); |
371 | 0 | else |
372 | 0 | json_node_init_null (node); |
373 | |
|
374 | 0 | object_set_member_internal (object, member_name, node); |
375 | 0 | } |
376 | | |
377 | | /** |
378 | | * json_object_set_null_member: |
379 | | * @object: a JSON object |
380 | | * @member_name: the name of the member |
381 | | * |
382 | | * Convenience function for setting an object member with a `null` value. |
383 | | * |
384 | | * See also: [method@Json.Object.set_member], [method@Json.Node.init_null] |
385 | | * |
386 | | * Since: 0.8 |
387 | | */ |
388 | | void |
389 | | json_object_set_null_member (JsonObject *object, |
390 | | const gchar *member_name) |
391 | 0 | { |
392 | 0 | g_return_if_fail (object != NULL); |
393 | 0 | g_return_if_fail (member_name != NULL); |
394 | | |
395 | 0 | object_set_member_internal (object, member_name, json_node_init_null (json_node_alloc ())); |
396 | 0 | } |
397 | | |
398 | | /** |
399 | | * json_object_set_array_member: |
400 | | * @object: a JSON object |
401 | | * @member_name: the name of the member |
402 | | * @value: (transfer full): the value of the member |
403 | | * |
404 | | * Convenience function for setting an object member with an array value. |
405 | | * |
406 | | * See also: [method@Json.Object.set_member], [method@Json.Node.take_array] |
407 | | * |
408 | | * Since: 0.8 |
409 | | */ |
410 | | void |
411 | | json_object_set_array_member (JsonObject *object, |
412 | | const gchar *member_name, |
413 | | JsonArray *value) |
414 | 0 | { |
415 | 0 | JsonNode *node; |
416 | |
|
417 | 0 | g_return_if_fail (object != NULL); |
418 | 0 | g_return_if_fail (member_name != NULL); |
419 | | |
420 | 0 | node = json_node_alloc (); |
421 | |
|
422 | 0 | if (value != NULL) |
423 | 0 | { |
424 | 0 | json_node_init_array (node, value); |
425 | 0 | json_array_unref (value); |
426 | 0 | } |
427 | 0 | else |
428 | 0 | json_node_init_null (node); |
429 | |
|
430 | 0 | object_set_member_internal (object, member_name, node); |
431 | 0 | } |
432 | | |
433 | | /** |
434 | | * json_object_set_object_member: |
435 | | * @object: a JSON object |
436 | | * @member_name: the name of the member |
437 | | * @value: (transfer full): the value of the member |
438 | | * |
439 | | * Convenience function for setting an object member with an object value. |
440 | | * |
441 | | * See also: [method@Json.Object.set_member], [method@Json.Node.take_object] |
442 | | * |
443 | | * Since: 0.8 |
444 | | */ |
445 | | void |
446 | | json_object_set_object_member (JsonObject *object, |
447 | | const gchar *member_name, |
448 | | JsonObject *value) |
449 | 0 | { |
450 | 0 | JsonNode *node; |
451 | |
|
452 | 0 | g_return_if_fail (object != NULL); |
453 | 0 | g_return_if_fail (member_name != NULL); |
454 | | |
455 | 0 | node = json_node_alloc (); |
456 | |
|
457 | 0 | if (value != NULL) |
458 | 0 | { |
459 | 0 | json_node_init_object (node, value); |
460 | 0 | json_object_unref (value); |
461 | 0 | } |
462 | 0 | else |
463 | 0 | json_node_init_null (node); |
464 | |
|
465 | 0 | object_set_member_internal (object, member_name, node); |
466 | 0 | } |
467 | | |
468 | | /** |
469 | | * json_object_get_members: |
470 | | * @object: a JSON object |
471 | | * |
472 | | * Retrieves all the names of the members of an object. |
473 | | * |
474 | | * You can obtain the value for each member by iterating the returned list |
475 | | * and calling [method@Json.Object.get_member]. |
476 | | * |
477 | | * Returns: (element-type utf8) (transfer container) (nullable): the |
478 | | * member names of the object |
479 | | */ |
480 | | GList * |
481 | | json_object_get_members (JsonObject *object) |
482 | 0 | { |
483 | 0 | g_return_val_if_fail (object != NULL, NULL); |
484 | | |
485 | 0 | return g_list_copy (object->members_ordered.head); |
486 | 0 | } |
487 | | |
488 | | |
489 | | GQueue * |
490 | | json_object_get_members_internal (JsonObject *object) |
491 | 0 | { |
492 | 0 | g_return_val_if_fail (object != NULL, NULL); |
493 | | |
494 | 0 | return &object->members_ordered; |
495 | 0 | } |
496 | | |
497 | | /** |
498 | | * json_object_get_values: |
499 | | * @object: a JSON object |
500 | | * |
501 | | * Retrieves all the values of the members of an object. |
502 | | * |
503 | | * Returns: (element-type JsonNode) (transfer container) (nullable): the |
504 | | * member values of the object |
505 | | */ |
506 | | GList * |
507 | | json_object_get_values (JsonObject *object) |
508 | 0 | { |
509 | 0 | GList *values, *l; |
510 | |
|
511 | 0 | g_return_val_if_fail (object != NULL, NULL); |
512 | | |
513 | 0 | values = NULL; |
514 | 0 | for (l = object->members_ordered.tail; l != NULL; l = l->prev) |
515 | 0 | values = g_list_prepend (values, g_hash_table_lookup (object->members, l->data)); |
516 | |
|
517 | 0 | return values; |
518 | 0 | } |
519 | | |
520 | | /** |
521 | | * json_object_dup_member: |
522 | | * @object: a JSON object |
523 | | * @member_name: the name of the JSON object member to access |
524 | | * |
525 | | * Retrieves a copy of the value of the given member inside an object. |
526 | | * |
527 | | * Returns: (transfer full) (nullable): a copy of the value for the |
528 | | * requested object member |
529 | | * |
530 | | * Since: 0.6 |
531 | | */ |
532 | | JsonNode * |
533 | | json_object_dup_member (JsonObject *object, |
534 | | const gchar *member_name) |
535 | 0 | { |
536 | 0 | JsonNode *retval; |
537 | |
|
538 | 0 | g_return_val_if_fail (object != NULL, NULL); |
539 | 0 | g_return_val_if_fail (member_name != NULL, NULL); |
540 | | |
541 | 0 | retval = json_object_get_member (object, member_name); |
542 | 0 | if (!retval) |
543 | 0 | return NULL; |
544 | | |
545 | 0 | return json_node_copy (retval); |
546 | 0 | } |
547 | | |
548 | | static inline JsonNode * |
549 | | object_get_member_internal (JsonObject *object, |
550 | | const gchar *member_name) |
551 | 0 | { |
552 | 0 | return g_hash_table_lookup (object->members, member_name); |
553 | 0 | } |
554 | | |
555 | | /** |
556 | | * json_object_get_member: |
557 | | * @object: a JSON object |
558 | | * @member_name: the name of the JSON object member to access |
559 | | * |
560 | | * Retrieves the value of the given member inside an object. |
561 | | * |
562 | | * Returns: (transfer none) (nullable): the value for the |
563 | | * requested object member |
564 | | */ |
565 | | JsonNode * |
566 | | json_object_get_member (JsonObject *object, |
567 | | const gchar *member_name) |
568 | 0 | { |
569 | 0 | g_return_val_if_fail (object != NULL, NULL); |
570 | 0 | g_return_val_if_fail (member_name != NULL, NULL); |
571 | | |
572 | 0 | return object_get_member_internal (object, member_name); |
573 | 0 | } |
574 | | |
575 | | #define JSON_OBJECT_GET(ret_type,type_name) \ |
576 | | ret_type \ |
577 | | json_object_get_ ##type_name## _member (JsonObject *object, \ |
578 | 0 | const char *member_name) \ |
579 | 0 | { \ |
580 | 0 | g_return_val_if_fail (object != NULL, (ret_type) 0); \ |
581 | 0 | g_return_val_if_fail (member_name != NULL, (ret_type) 0); \ |
582 | 0 | \ |
583 | 0 | JsonNode *node = object_get_member_internal (object, member_name); \ |
584 | 0 | g_return_val_if_fail (node != NULL, (ret_type) 0); \ |
585 | 0 | \ |
586 | 0 | if (JSON_NODE_HOLDS_NULL (node)) \ |
587 | 0 | return (ret_type) 0; \ |
588 | 0 | \ |
589 | 0 | g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, (ret_type) 0); \ |
590 | 0 | \ |
591 | 0 | return json_node_get_ ##type_name (node); \ |
592 | 0 | } Unexecuted instantiation: json_object_get_int_member Unexecuted instantiation: json_object_get_double_member Unexecuted instantiation: json_object_get_boolean_member Unexecuted instantiation: json_object_get_string_member |
593 | | |
594 | | #define JSON_OBJECT_GET_DEFAULT(ret_type,type_name) \ |
595 | | ret_type \ |
596 | | json_object_get_ ##type_name## _member_with_default (JsonObject *object, \ |
597 | | const char *member_name, \ |
598 | 0 | ret_type default_value) \ |
599 | 0 | { \ |
600 | 0 | g_return_val_if_fail (object != NULL, default_value); \ |
601 | 0 | g_return_val_if_fail (member_name != NULL, default_value); \ |
602 | 0 | \ |
603 | 0 | JsonNode *node = object_get_member_internal (object, member_name); \ |
604 | 0 | if (node == NULL) \ |
605 | 0 | return default_value; \ |
606 | 0 | \ |
607 | 0 | if (JSON_NODE_HOLDS_NULL (node)) \ |
608 | 0 | return default_value; \ |
609 | 0 | \ |
610 | 0 | if (JSON_NODE_TYPE (node) != JSON_NODE_VALUE) \ |
611 | 0 | return default_value; \ |
612 | 0 | \ |
613 | 0 | return json_node_get_ ##type_name (node); \ |
614 | 0 | } Unexecuted instantiation: json_object_get_int_member_with_default Unexecuted instantiation: json_object_get_double_member_with_default Unexecuted instantiation: json_object_get_boolean_member_with_default Unexecuted instantiation: json_object_get_string_member_with_default |
615 | | |
616 | | /** |
617 | | * json_object_get_int_member: |
618 | | * @object: a JSON object |
619 | | * @member_name: the name of the object member |
620 | | * |
621 | | * Convenience function that retrieves the integer value |
622 | | * stored in @member_name of @object. It is an error to specify a |
623 | | * @member_name which does not exist or which holds a non-scalar, |
624 | | * non-`null` value. |
625 | | * |
626 | | * See also: [method@Json.Object.get_int_member_with_default], |
627 | | * [method@Json.Object.get_member], [method@Json.Object.has_member] |
628 | | * |
629 | | * Returns: the integer value of the object's member |
630 | | * |
631 | | * Since: 0.8 |
632 | | */ |
633 | | JSON_OBJECT_GET (gint64, int) |
634 | | |
635 | | /** |
636 | | * json_object_get_int_member_with_default: |
637 | | * @object: a JSON object |
638 | | * @member_name: the name of the object member |
639 | | * @default_value: the value to return if @member_name is not valid |
640 | | * |
641 | | * Convenience function that retrieves the integer value |
642 | | * stored in @member_name of @object. |
643 | | * |
644 | | * If @member_name does not exist, does not contain a scalar value, |
645 | | * or contains `null`, then @default_value is returned instead. If |
646 | | * @member_name contains a non-integer, non-`null` scalar value, then whatever |
647 | | * json_node_get_int() would return is returned. |
648 | | * |
649 | | * Returns: the integer value of the object's member, or the |
650 | | * given default |
651 | | * |
652 | | * Since: 1.6 |
653 | | */ |
654 | | JSON_OBJECT_GET_DEFAULT (gint64, int) |
655 | | |
656 | | /** |
657 | | * json_object_get_double_member: |
658 | | * @object: a JSON object |
659 | | * @member_name: the name of the member |
660 | | * |
661 | | * Convenience function that retrieves the floating point value |
662 | | * stored in @member_name of @object. It is an error to specify a |
663 | | * @member_name which does not exist or which holds a non-scalar, |
664 | | * non-`null` value. |
665 | | * |
666 | | * See also: [method@Json.Object.get_double_member_with_default], |
667 | | * [method@Json.Object.get_member], [method@Json.Object.has_member] |
668 | | * |
669 | | * Returns: the floating point value of the object's member |
670 | | * |
671 | | * Since: 0.8 |
672 | | */ |
673 | | JSON_OBJECT_GET (gdouble, double) |
674 | | |
675 | | /** |
676 | | * json_object_get_double_member_with_default: |
677 | | * @object: a JSON object |
678 | | * @member_name: the name of the @object member |
679 | | * @default_value: the value to return if @member_name is not valid |
680 | | * |
681 | | * Convenience function that retrieves the floating point value |
682 | | * stored in @member_name of @object. |
683 | | * |
684 | | * If @member_name does not exist, does not contain a scalar value, |
685 | | * or contains `null`, then @default_value is returned instead. If |
686 | | * @member_name contains a non-double, non-`null` scalar value, then |
687 | | * whatever json_node_get_double() would return is returned. |
688 | | * |
689 | | * Returns: the floating point value of the object's member, or the |
690 | | * given default |
691 | | * |
692 | | * Since: 1.6 |
693 | | */ |
694 | | JSON_OBJECT_GET_DEFAULT (double, double) |
695 | | |
696 | | /** |
697 | | * json_object_get_boolean_member: |
698 | | * @object: a JSON object |
699 | | * @member_name: the name of the member |
700 | | * |
701 | | * Convenience function that retrieves the boolean value |
702 | | * stored in @member_name of @object. It is an error to specify a |
703 | | * @member_name which does not exist or which holds a non-scalar, |
704 | | * non-`null` value. |
705 | | * |
706 | | * See also: [method@Json.Object.get_boolean_member_with_default], |
707 | | * [method@Json.Object.get_member], [method@Json.Object.has_member] |
708 | | * |
709 | | * Returns: the boolean value of the object's member |
710 | | * |
711 | | * Since: 0.8 |
712 | | */ |
713 | | JSON_OBJECT_GET (gboolean, boolean) |
714 | | |
715 | | /** |
716 | | * json_object_get_boolean_member_with_default: |
717 | | * @object: a JSON object |
718 | | * @member_name: the name of the @object member |
719 | | * @default_value: the value to return if @member_name is not valid |
720 | | * |
721 | | * Convenience function that retrieves the boolean value |
722 | | * stored in @member_name of @object. |
723 | | * |
724 | | * If @member_name does not exist, does not contain a scalar value, |
725 | | * or contains `null`, then @default_value is returned instead. If |
726 | | * @member_name contains a non-boolean, non-`null` scalar value, then |
727 | | * whatever json_node_get_boolean() would return is returned. |
728 | | * |
729 | | * Returns: the boolean value of the object's member, or the |
730 | | * given default |
731 | | * |
732 | | * Since: 1.6 |
733 | | */ |
734 | | JSON_OBJECT_GET_DEFAULT (gboolean, boolean) |
735 | | |
736 | | /** |
737 | | * json_object_get_string_member: |
738 | | * @object: a JSON object |
739 | | * @member_name: the name of the member |
740 | | * |
741 | | * Convenience function that retrieves the string value |
742 | | * stored in @member_name of @object. It is an error to specify a |
743 | | * @member_name that does not exist or which holds a non-scalar, |
744 | | * non-`null` value. |
745 | | * |
746 | | * See also: [method@Json.Object.get_string_member_with_default], |
747 | | * [method@Json.Object.get_member], [method@Json.Object.has_member] |
748 | | * |
749 | | * Returns: the string value of the object's member |
750 | | * |
751 | | * Since: 0.8 |
752 | | */ |
753 | | JSON_OBJECT_GET (const gchar *, string) |
754 | | |
755 | | /** |
756 | | * json_object_get_string_member_with_default: |
757 | | * @object: a JSON object |
758 | | * @member_name: the name of the @object member |
759 | | * @default_value: the value to return if @member_name is not valid |
760 | | * |
761 | | * Convenience function that retrieves the string value |
762 | | * stored in @member_name of @object. |
763 | | * |
764 | | * If @member_name does not exist, does not contain a scalar value, |
765 | | * or contains `null`, then @default_value is returned instead. If |
766 | | * @member_name contains a non-string, non-`null` scalar value, then |
767 | | * %NULL is returned. |
768 | | * |
769 | | * Returns: the string value of the object's member, or the |
770 | | * given default |
771 | | * |
772 | | * Since: 1.6 |
773 | | */ |
774 | | JSON_OBJECT_GET_DEFAULT (const char *, string) |
775 | | |
776 | | /** |
777 | | * json_object_get_null_member: |
778 | | * @object: a JSON object |
779 | | * @member_name: the name of the member |
780 | | * |
781 | | * Convenience function that checks whether the value |
782 | | * stored in @member_name of @object is null. It is an error to |
783 | | * specify a @member_name which does not exist. |
784 | | * |
785 | | * See also: [method@Json.Object.get_member], [method@Json.Object.has_member] |
786 | | * |
787 | | * Returns: `TRUE` if the value is `null` |
788 | | * |
789 | | * Since: 0.8 |
790 | | */ |
791 | | gboolean |
792 | | json_object_get_null_member (JsonObject *object, |
793 | | const gchar *member_name) |
794 | 0 | { |
795 | 0 | JsonNode *node; |
796 | |
|
797 | 0 | g_return_val_if_fail (object != NULL, FALSE); |
798 | 0 | g_return_val_if_fail (member_name != NULL, FALSE); |
799 | | |
800 | 0 | node = object_get_member_internal (object, member_name); |
801 | 0 | g_return_val_if_fail (node != NULL, FALSE); |
802 | | |
803 | 0 | if (JSON_NODE_HOLDS_NULL (node)) |
804 | 0 | return TRUE; |
805 | | |
806 | 0 | if (JSON_NODE_HOLDS_OBJECT (node)) |
807 | 0 | return json_node_get_object (node) == NULL; |
808 | | |
809 | 0 | if (JSON_NODE_HOLDS_ARRAY (node)) |
810 | 0 | return json_node_get_array (node) == NULL; |
811 | | |
812 | 0 | return FALSE; |
813 | 0 | } |
814 | | |
815 | | /** |
816 | | * json_object_get_array_member: |
817 | | * @object: a JSON object |
818 | | * @member_name: the name of the member |
819 | | * |
820 | | * Convenience function that retrieves the array |
821 | | * stored in @member_name of @object. It is an error to specify a |
822 | | * @member_name which does not exist or which holds a non-`null`, non-array |
823 | | * value. |
824 | | * |
825 | | * If @member_name contains `null`, then this function will return `NULL`. |
826 | | * |
827 | | * See also: [method@Json.Object.get_member], [method@Json.Object.has_member] |
828 | | * |
829 | | * Returns: (transfer none) (nullable): the array inside the object's member |
830 | | * |
831 | | * Since: 0.8 |
832 | | */ |
833 | | JsonArray * |
834 | | json_object_get_array_member (JsonObject *object, |
835 | | const gchar *member_name) |
836 | 0 | { |
837 | 0 | JsonNode *node; |
838 | |
|
839 | 0 | g_return_val_if_fail (object != NULL, NULL); |
840 | 0 | g_return_val_if_fail (member_name != NULL, NULL); |
841 | | |
842 | 0 | node = object_get_member_internal (object, member_name); |
843 | 0 | g_return_val_if_fail (node != NULL, NULL); |
844 | 0 | g_return_val_if_fail (JSON_NODE_HOLDS_ARRAY (node) || JSON_NODE_HOLDS_NULL (node), NULL); |
845 | | |
846 | 0 | if (JSON_NODE_HOLDS_NULL (node)) |
847 | 0 | return NULL; |
848 | | |
849 | 0 | return json_node_get_array (node); |
850 | 0 | } |
851 | | |
852 | | /** |
853 | | * json_object_get_object_member: |
854 | | * @object: a JSON object |
855 | | * @member_name: the name of the member |
856 | | * |
857 | | * Convenience function that retrieves the object |
858 | | * stored in @member_name of @object. It is an error to specify a @member_name |
859 | | * which does not exist or which holds a non-`null`, non-object value. |
860 | | * |
861 | | * If @member_name contains `null`, then this function will return `NULL`. |
862 | | * |
863 | | * See also: [method@Json.Object.get_member], [method@Json.Object.has_member] |
864 | | * |
865 | | * Returns: (transfer none) (nullable): the object inside the object's member |
866 | | * |
867 | | * Since: 0.8 |
868 | | */ |
869 | | JsonObject * |
870 | | json_object_get_object_member (JsonObject *object, |
871 | | const gchar *member_name) |
872 | 0 | { |
873 | 0 | JsonNode *node; |
874 | |
|
875 | 0 | g_return_val_if_fail (object != NULL, NULL); |
876 | 0 | g_return_val_if_fail (member_name != NULL, NULL); |
877 | | |
878 | 0 | node = object_get_member_internal (object, member_name); |
879 | 0 | g_return_val_if_fail (node != NULL, NULL); |
880 | 0 | g_return_val_if_fail (JSON_NODE_HOLDS_OBJECT (node) || JSON_NODE_HOLDS_NULL (node), NULL); |
881 | | |
882 | 0 | if (JSON_NODE_HOLDS_NULL (node)) |
883 | 0 | return NULL; |
884 | | |
885 | 0 | return json_node_get_object (node); |
886 | 0 | } |
887 | | |
888 | | /** |
889 | | * json_object_has_member: |
890 | | * @object: a JSON object |
891 | | * @member_name: the name of a JSON object member |
892 | | * |
893 | | * Checks whether @object has a member named @member_name. |
894 | | * |
895 | | * Returns: `TRUE` if the JSON object has the requested member |
896 | | */ |
897 | | gboolean |
898 | | json_object_has_member (JsonObject *object, |
899 | | const gchar *member_name) |
900 | 0 | { |
901 | 0 | g_return_val_if_fail (object != NULL, FALSE); |
902 | 0 | g_return_val_if_fail (member_name != NULL, FALSE); |
903 | | |
904 | 0 | return (g_hash_table_lookup (object->members, member_name) != NULL); |
905 | 0 | } |
906 | | |
907 | | /** |
908 | | * json_object_get_size: |
909 | | * @object: a JSON object |
910 | | * |
911 | | * Retrieves the number of members of a JSON object. |
912 | | * |
913 | | * Returns: the number of members |
914 | | */ |
915 | | guint |
916 | | json_object_get_size (JsonObject *object) |
917 | 0 | { |
918 | 0 | g_return_val_if_fail (object != NULL, 0); |
919 | | |
920 | 0 | return g_hash_table_size (object->members); |
921 | 0 | } |
922 | | |
923 | | /** |
924 | | * json_object_remove_member: |
925 | | * @object: a JSON object |
926 | | * @member_name: the name of the member to remove |
927 | | * |
928 | | * Removes @member_name from @object, freeing its allocated resources. |
929 | | */ |
930 | | void |
931 | | json_object_remove_member (JsonObject *object, |
932 | | const gchar *member_name) |
933 | 0 | { |
934 | 0 | GList *l; |
935 | |
|
936 | 0 | g_return_if_fail (object != NULL); |
937 | 0 | g_return_if_fail (member_name != NULL); |
938 | | |
939 | 0 | for (l = object->members_ordered.head; l != NULL; l = l->next) |
940 | 0 | { |
941 | 0 | const gchar *name = l->data; |
942 | |
|
943 | 0 | if (g_strcmp0 (name, member_name) == 0) |
944 | 0 | { |
945 | 0 | g_queue_delete_link (&object->members_ordered, l); |
946 | 0 | break; |
947 | 0 | } |
948 | 0 | } |
949 | |
|
950 | 0 | g_hash_table_remove (object->members, member_name); |
951 | 0 | } |
952 | | |
953 | | /** |
954 | | * json_object_foreach_member: |
955 | | * @object: a JSON object |
956 | | * @func: (scope call) (closure data): the function to be called on each member |
957 | | * @data: data to be passed to the function |
958 | | * |
959 | | * Iterates over all members of @object and calls @func on |
960 | | * each one of them. |
961 | | * |
962 | | * It is safe to change the value of a member of the oobject |
963 | | * from within the iterator function, but it is not safe to add or |
964 | | * remove members from the object. |
965 | | * |
966 | | * The order in which the object members are iterated is the |
967 | | * insertion order. |
968 | | * |
969 | | * Since: 0.8 |
970 | | */ |
971 | | void |
972 | | json_object_foreach_member (JsonObject *object, |
973 | | JsonObjectForeach func, |
974 | | gpointer data) |
975 | 0 | { |
976 | 0 | GList *l; |
977 | 0 | int age; |
978 | |
|
979 | 0 | g_return_if_fail (object != NULL); |
980 | 0 | g_return_if_fail (func != NULL); |
981 | | |
982 | 0 | age = object->age; |
983 | |
|
984 | 0 | for (l = object->members_ordered.head; l != NULL; l = l->next) |
985 | 0 | { |
986 | 0 | const gchar *member_name = l->data; |
987 | 0 | JsonNode *member_node = g_hash_table_lookup (object->members, member_name); |
988 | |
|
989 | 0 | func (object, member_name, member_node, data); |
990 | |
|
991 | 0 | g_assert (object->age == age); |
992 | 0 | } |
993 | 0 | } |
994 | | |
995 | | /** |
996 | | * json_object_hash: |
997 | | * @key: (type JsonObject): a JSON object to hash |
998 | | * |
999 | | * Calculate a hash value for the given @key (a JSON object). |
1000 | | * |
1001 | | * The hash is calculated over the object and all its members, recursively. If |
1002 | | * the object is immutable, this is a fast operation; otherwise, it scales |
1003 | | * proportionally with the number of members in the object. |
1004 | | * |
1005 | | * Returns: hash value for @key |
1006 | | * Since: 1.2 |
1007 | | */ |
1008 | | guint |
1009 | | json_object_hash (gconstpointer key) |
1010 | 0 | { |
1011 | 0 | JsonObject *object = (JsonObject *) key; |
1012 | 0 | guint hash = 0; |
1013 | 0 | JsonObjectIter iter; |
1014 | 0 | const gchar *member_name; |
1015 | 0 | JsonNode *node; |
1016 | |
|
1017 | 0 | g_return_val_if_fail (object != NULL, 0); |
1018 | | |
1019 | | /* If the object is immutable, use the cached hash. */ |
1020 | 0 | if (object->immutable) |
1021 | 0 | return object->immutable_hash; |
1022 | | |
1023 | | /* Otherwise, calculate from scratch. */ |
1024 | 0 | json_object_iter_init (&iter, object); |
1025 | |
|
1026 | 0 | while (json_object_iter_next (&iter, &member_name, &node)) |
1027 | 0 | hash ^= (json_string_hash (member_name) ^ json_node_hash (node)); |
1028 | |
|
1029 | 0 | return hash; |
1030 | 0 | } |
1031 | | |
1032 | | /** |
1033 | | * json_object_equal: |
1034 | | * @a: (type JsonObject): a JSON object |
1035 | | * @b: (type JsonObject): another JSON object |
1036 | | * |
1037 | | * Check whether @a and @b are equal objects, meaning they have the same |
1038 | | * set of members, and the values of corresponding members are equal. |
1039 | | * |
1040 | | * Returns: `TRUE` if @a and @b are equal, and `FALSE` otherwise |
1041 | | * Since: 1.2 |
1042 | | */ |
1043 | | gboolean |
1044 | | json_object_equal (gconstpointer a, |
1045 | | gconstpointer b) |
1046 | 0 | { |
1047 | 0 | JsonObject *object_a, *object_b; |
1048 | 0 | guint size_a, size_b; |
1049 | 0 | JsonObjectIter iter_a; |
1050 | 0 | JsonNode *child_a, *child_b; /* unowned */ |
1051 | 0 | const gchar *member_name; |
1052 | |
|
1053 | 0 | object_a = (JsonObject *) a; |
1054 | 0 | object_b = (JsonObject *) b; |
1055 | | |
1056 | | /* Identity comparison. */ |
1057 | 0 | if (object_a == object_b) |
1058 | 0 | return TRUE; |
1059 | | |
1060 | | /* Check sizes. */ |
1061 | 0 | size_a = json_object_get_size (object_a); |
1062 | 0 | size_b = json_object_get_size (object_b); |
1063 | |
|
1064 | 0 | if (size_a != size_b) |
1065 | 0 | return FALSE; |
1066 | | |
1067 | | /* Check member names and values. Check the member names first |
1068 | | * to avoid expensive recursive value comparisons which might |
1069 | | * be unnecessary. */ |
1070 | 0 | json_object_iter_init (&iter_a, object_a); |
1071 | |
|
1072 | 0 | while (json_object_iter_next (&iter_a, &member_name, NULL)) |
1073 | 0 | { |
1074 | 0 | if (!json_object_has_member (object_b, member_name)) |
1075 | 0 | return FALSE; |
1076 | 0 | } |
1077 | | |
1078 | 0 | json_object_iter_init (&iter_a, object_a); |
1079 | |
|
1080 | 0 | while (json_object_iter_next (&iter_a, &member_name, &child_a)) |
1081 | 0 | { |
1082 | 0 | child_b = json_object_get_member (object_b, member_name); |
1083 | |
|
1084 | 0 | if (!json_node_equal (child_a, child_b)) |
1085 | 0 | return FALSE; |
1086 | 0 | } |
1087 | | |
1088 | 0 | return TRUE; |
1089 | 0 | } |
1090 | | |
1091 | | /** |
1092 | | * json_object_iter_init: |
1093 | | * @iter: an uninitialised JSON object iterator |
1094 | | * @object: the JSON object to iterate over |
1095 | | * |
1096 | | * Initialises the @iter and associate it with @object. |
1097 | | * |
1098 | | * ```c |
1099 | | * JsonObjectIter iter; |
1100 | | * const gchar *member_name; |
1101 | | * JsonNode *member_node; |
1102 | | * |
1103 | | * json_object_iter_init (&iter, some_object); |
1104 | | * while (json_object_iter_next (&iter, &member_name, &member_node)) |
1105 | | * { |
1106 | | * // Do something with @member_name and @member_node. |
1107 | | * } |
1108 | | * ``` |
1109 | | * |
1110 | | * The iterator initialized with this function will iterate the |
1111 | | * members of the object in an undefined order. |
1112 | | * |
1113 | | * See also: [method@Json.ObjectIter.init_ordered] |
1114 | | * |
1115 | | * Since: 1.2 |
1116 | | */ |
1117 | | void |
1118 | | json_object_iter_init (JsonObjectIter *iter, |
1119 | | JsonObject *object) |
1120 | 0 | { |
1121 | 0 | JsonObjectIterReal *iter_real = (JsonObjectIterReal *) iter;; |
1122 | |
|
1123 | 0 | g_return_if_fail (iter != NULL); |
1124 | 0 | g_return_if_fail (object != NULL); |
1125 | | |
1126 | 0 | iter_real->object = object; |
1127 | 0 | g_hash_table_iter_init (&iter_real->members_iter, object->members); |
1128 | 0 | } |
1129 | | |
1130 | | /** |
1131 | | * json_object_iter_next: |
1132 | | * @iter: a JSON object iterator |
1133 | | * @member_name: (out callee-allocates) (transfer none) (optional): return |
1134 | | * location for the member name, or %NULL to ignore |
1135 | | * @member_node: (out callee-allocates) (transfer none) (optional): return |
1136 | | * location for the member value, or %NULL to ignore |
1137 | | * |
1138 | | * Advances the iterator and retrieves the next member in the object. |
1139 | | * |
1140 | | * If the end of the object is reached, `FALSE` is returned and @member_name |
1141 | | * and @member_node are set to invalid values. After that point, the @iter |
1142 | | * is invalid. |
1143 | | * |
1144 | | * The order in which members are returned by the iterator is undefined. The |
1145 | | * iterator is invalidated if the object is modified during iteration. |
1146 | | * |
1147 | | * You must use this function with an iterator initialized with |
1148 | | * [method@Json.ObjectIter.init]; using this function with an iterator |
1149 | | * initialized with [method@Json.ObjectIter.init_ordered] yields undefined |
1150 | | * behavior. |
1151 | | * |
1152 | | * See also: [method@Json.ObjectIter.next_ordered] |
1153 | | * |
1154 | | * Returns: `TRUE` if @member_name and @member_node are valid; `FALSE` if |
1155 | | * there are no more members |
1156 | | * |
1157 | | * Since: 1.2 |
1158 | | */ |
1159 | | gboolean |
1160 | | json_object_iter_next (JsonObjectIter *iter, |
1161 | | const gchar **member_name, |
1162 | | JsonNode **member_node) |
1163 | 0 | { |
1164 | 0 | JsonObjectIterReal *iter_real = (JsonObjectIterReal *) iter; |
1165 | |
|
1166 | 0 | g_return_val_if_fail (iter != NULL, FALSE); |
1167 | 0 | g_return_val_if_fail (iter_real->object != NULL, FALSE); |
1168 | | |
1169 | 0 | return g_hash_table_iter_next (&iter_real->members_iter, |
1170 | 0 | (gpointer *) member_name, |
1171 | 0 | (gpointer *) member_node); |
1172 | 0 | } |
1173 | | |
1174 | | /** |
1175 | | * json_object_iter_init_ordered: |
1176 | | * @iter: an uninitialised iterator |
1177 | | * @object: the JSON object to iterate over |
1178 | | * |
1179 | | * Initialises the @iter and associate it with @object. |
1180 | | * |
1181 | | * ```c |
1182 | | * JsonObjectIter iter; |
1183 | | * const gchar *member_name; |
1184 | | * JsonNode *member_node; |
1185 | | * |
1186 | | * json_object_iter_init_ordered (&iter, some_object); |
1187 | | * while (json_object_iter_next_ordered (&iter, &member_name, &member_node)) |
1188 | | * { |
1189 | | * // Do something with @member_name and @member_node. |
1190 | | * } |
1191 | | * ``` |
1192 | | * |
1193 | | * See also: [method@Json.ObjectIter.init] |
1194 | | * |
1195 | | * Since: 1.6 |
1196 | | */ |
1197 | | void |
1198 | | json_object_iter_init_ordered (JsonObjectIter *iter, |
1199 | | JsonObject *object) |
1200 | 0 | { |
1201 | 0 | JsonObjectOrderedIterReal *iter_real = (JsonObjectOrderedIterReal *) iter; |
1202 | |
|
1203 | 0 | g_return_if_fail (iter != NULL); |
1204 | 0 | g_return_if_fail (object != NULL); |
1205 | | |
1206 | 0 | iter_real->object = object; |
1207 | 0 | iter_real->cur_member = NULL; |
1208 | 0 | iter_real->next_member = NULL; |
1209 | 0 | iter_real->age = iter_real->object->age; |
1210 | 0 | } |
1211 | | |
1212 | | /** |
1213 | | * json_object_iter_next_ordered: |
1214 | | * @iter: an ordered JSON object iterator |
1215 | | * @member_name: (out callee-allocates) (transfer none) (optional): return |
1216 | | * location for the member name, or %NULL to ignore |
1217 | | * @member_node: (out callee-allocates) (transfer none) (optional): return |
1218 | | * location for the member value, or %NULL to ignore |
1219 | | * |
1220 | | * Advances the iterator and retrieves the next member in the object. |
1221 | | * |
1222 | | * If the end of the object is reached, `FALSE` is returned and @member_name and |
1223 | | * @member_node are set to invalid values. After that point, the @iter is invalid. |
1224 | | * |
1225 | | * The order in which members are returned by the iterator is the same order in |
1226 | | * which the members were added to the `JsonObject`. The iterator is invalidated |
1227 | | * if its `JsonObject` is modified during iteration. |
1228 | | * |
1229 | | * You must use this function with an iterator initialized with |
1230 | | * [method@Json.ObjectIter.init_ordered]; using this function with an iterator |
1231 | | * initialized with [method@Json.ObjectIter.init] yields undefined behavior. |
1232 | | * |
1233 | | * See also: [method@Json.ObjectIter.next] |
1234 | | * |
1235 | | * Returns: `TRUE `if @member_name and @member_node are valid; `FALSE` if the end |
1236 | | * of the object has been reached |
1237 | | * |
1238 | | * Since: 1.6 |
1239 | | */ |
1240 | | gboolean |
1241 | | json_object_iter_next_ordered (JsonObjectIter *iter, |
1242 | | const gchar **member_name, |
1243 | | JsonNode **member_node) |
1244 | 0 | { |
1245 | 0 | JsonObjectOrderedIterReal *iter_real = (JsonObjectOrderedIterReal *) iter; |
1246 | 0 | const char *name = NULL; |
1247 | |
|
1248 | 0 | g_return_val_if_fail (iter != NULL, FALSE); |
1249 | 0 | g_return_val_if_fail (iter_real->object != NULL, FALSE); |
1250 | 0 | g_return_val_if_fail (iter_real->age == iter_real->object->age, FALSE); |
1251 | | |
1252 | 0 | if (iter_real->cur_member == NULL) |
1253 | 0 | iter_real->cur_member = iter_real->object->members_ordered.head; |
1254 | 0 | else |
1255 | 0 | iter_real->cur_member = iter_real->cur_member->next; |
1256 | |
|
1257 | 0 | name = iter_real->cur_member != NULL ? iter_real->cur_member->data : NULL; |
1258 | |
|
1259 | 0 | if (member_name != NULL) |
1260 | 0 | *member_name = name; |
1261 | 0 | if (member_node != NULL) |
1262 | 0 | { |
1263 | 0 | if (name != NULL) |
1264 | 0 | *member_node = g_hash_table_lookup (iter_real->object->members, name); |
1265 | 0 | else |
1266 | 0 | *member_node = NULL; |
1267 | 0 | } |
1268 | |
|
1269 | 0 | return iter_real->cur_member != NULL; |
1270 | 0 | } |