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