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