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