[json] Update the internal JSON-GLib copy
authorEmmanuele Bassi <ebassi@linux.intel.com>
Tue, 9 Jun 2009 11:42:19 +0000 (12:42 +0100)
committerEmmanuele Bassi <ebassi@linux.intel.com>
Tue, 9 Jun 2009 13:07:22 +0000 (14:07 +0100)
There have been changes in JSON-GLib upstream to clean up the
data structures, and facilitate introspection.

We still not use the updated JsonParser with the (private) JsonScanner
code, since it's a fork of GLib's GScanner.

clutter/clutter-script.c
clutter/json/json-array.c
clutter/json/json-generator.c
clutter/json/json-node.c
clutter/json/json-object.c
clutter/json/json-parser.c
clutter/json/json-types-private.h [new file with mode: 0644]
clutter/json/json-types.h

index 463a5a0..b922739 100644 (file)
@@ -702,7 +702,7 @@ json_object_end (JsonParser *parser,
 
       val = json_node_new (JSON_NODE_VALUE);
       json_node_set_string (val, fake);
-      json_object_add_member (object, "id", val);
+      json_object_set_member (object, "id", val);
 
       g_free (fake);
     }
index 61c8a4c..08e0449 100644 (file)
@@ -2,26 +2,30 @@
  * 
  * This file is part of JSON-GLib
  * Copyright (C) 2007  OpenedHand Ltd.
+ * Copyright (C) 2009  Intel Corp.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
  * Author:
- *   Emmanuele Bassi  <ebassi@openedhand.com>
+ *   Emmanuele Bassi  <ebassi@linux.intel.com>
  */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#include "json-types.h"
+#include "json-types-private.h"
 
 /**
  * SECTION:json-array
  * To retrieve the length of the array, use json_array_get_length().
  */
 
-struct _JsonArray
-{
-  GPtrArray *elements;
-
-  volatile gint ref_count;
-};
-
 GType
 json_array_get_type (void)
 {
   static GType array_type = 0;
 
   if (G_UNLIKELY (!array_type))
-    array_type = g_boxed_type_register_static ("JsonArray",
+    array_type = g_boxed_type_register_static (g_intern_static_string ("JsonArray"),
                                                (GBoxedCopyFunc) json_array_ref,
                                                (GBoxedFreeFunc) json_array_unref);
 
@@ -142,7 +139,7 @@ json_array_unref (JsonArray *array)
     g_atomic_int_compare_and_exchange (&array->ref_count, old_ref, old_ref - 1);
   else
     {
-      gint i;
+      guint i;
 
       for (i = 0; i < array->elements->len; i++)
         json_node_free (g_ptr_array_index (array->elements, i));
@@ -160,9 +157,9 @@ json_array_unref (JsonArray *array)
  *
  * Gets the elements of a #JsonArray as a list of #JsonNode<!-- -->s.
  *
- * Return value: (transfer container) (element-type JsonNode): a #GList containing
- *   the elements of the array. The contents of the list are owned by the array and
- *   should never be  modified or freed. Use g_list_free() on the returned list when
+ * Return value: a #GList containing the elements of the array. The
+ *   contents of the list are owned by the array and should never be
+ *   modified or freed. Use g_list_free() on the returned list when
  *   done using it
  */
 GList *
@@ -182,6 +179,35 @@ json_array_get_elements (JsonArray *array)
 }
 
 /**
+ * json_array_dup_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ *
+ * Retrieves a copy of the #JsonNode containing the value of the
+ * element at @index_ inside a #JsonArray
+ *
+ * Return value: a copy of the #JsonNode at the requested index.
+ *   Use json_node_free() when done.
+ *
+ * Since: 0.6
+ */
+JsonNode *
+json_array_dup_element (JsonArray *array,
+                        guint      index_)
+{
+  JsonNode *retval;
+
+  g_return_val_if_fail (array != NULL, NULL);
+  g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+  retval = json_array_get_element (array, index_);
+  if (!retval)
+    return NULL;
+
+  return json_node_copy (retval);
+}
+
+/**
  * json_array_get_element:
  * @array: a #JsonArray
  * @index_: the index of the element to retrieve
@@ -189,7 +215,7 @@ json_array_get_elements (JsonArray *array)
  * Retrieves the #JsonNode containing the value of the element at @index_
  * inside a #JsonArray.
  *
- * Return value: (transfer none): a pointer to the #JsonNode at the requested index
+ * Return value: a pointer to the #JsonNode at the requested index
  */
 JsonNode *
 json_array_get_element (JsonArray *array,
@@ -202,6 +228,215 @@ json_array_get_element (JsonArray *array,
 }
 
 /**
+ * json_array_get_int_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the integer value of the element at @index_
+ * inside @array
+ *
+ * See also: json_array_get_element(), json_node_get_int()
+ *
+ * Return value: the integer value
+ *
+ * Since: 0.8
+ */
+gint
+json_array_get_int_element (JsonArray *array,
+                            guint      index_)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (array != NULL, 0);
+  g_return_val_if_fail (index_ < array->elements->len, 0);
+
+  node = g_ptr_array_index (array->elements, index_);
+  g_return_val_if_fail (node != NULL, 0);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0);
+
+  return json_node_get_int (node);
+}
+
+/**
+ * json_array_get_double_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the floating point value of the element at
+ * @index_ inside @array
+ *
+ * See also: json_array_get_element(), json_node_get_double()
+ *
+ * Return value: the floating point value
+ *
+ * Since: 0.8
+ */
+gdouble
+json_array_get_double_element (JsonArray *array,
+                               guint      index_)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (array != NULL, 0.0);
+  g_return_val_if_fail (index_ < array->elements->len, 0.0);
+
+  node = g_ptr_array_index (array->elements, index_);
+  g_return_val_if_fail (node != NULL, 0.0);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0.0);
+
+  return json_node_get_double (node);
+}
+
+/**
+ * json_array_get_boolean_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the boolean value of the element at @index_
+ * inside @array
+ *
+ * See also: json_array_get_element(), json_node_get_boolean()
+ *
+ * Return value: the integer value
+ *
+ * Since: 0.8
+ */
+gboolean
+json_array_get_boolean_element (JsonArray *array,
+                                guint      index_)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (array != NULL, FALSE);
+  g_return_val_if_fail (index_ < array->elements->len, FALSE);
+
+  node = g_ptr_array_index (array->elements, index_);
+  g_return_val_if_fail (node != NULL, FALSE);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, FALSE);
+
+  return json_node_get_boolean (node);
+}
+
+/**
+ * json_array_get_string_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the string value of the element at @index_
+ * inside @array
+ *
+ * See also: json_array_get_element(), json_node_get_string()
+ *
+ * Return value: the string value; the returned string is owned by
+ *   the #JsonArray and should not be modified or freed
+ *
+ * Since: 0.8
+ */
+G_CONST_RETURN gchar *
+json_array_get_string_element (JsonArray *array,
+                               guint      index_)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (array != NULL, NULL);
+  g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+  node = g_ptr_array_index (array->elements, index_);
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, NULL);
+
+  return json_node_get_string (node);
+}
+
+/**
+ * json_array_get_null_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves whether the element at @index_ is set to null
+ *
+ * See also: json_array_get_element(), JSON_NODE_TYPE(), %JSON_NODE_NULL
+ *
+ * Return value: %TRUE if the element is null
+ *
+ * Since: 0.8
+ */
+gboolean
+json_array_get_null_element (JsonArray *array,
+                             guint      index_)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (array != NULL, FALSE);
+  g_return_val_if_fail (index_ < array->elements->len, FALSE);
+
+  node = g_ptr_array_index (array->elements, index_);
+  g_return_val_if_fail (node != NULL, FALSE);
+
+  return JSON_NODE_TYPE (node) == JSON_NODE_NULL;
+}
+
+/**
+ * json_array_get_array_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the array from the element at @index_
+ * inside @array
+ *
+ * See also: json_array_get_element(), json_node_get_array()
+ *
+ * Return value: the array
+ *
+ * Since: 0.8
+ */
+JsonArray *
+json_array_get_array_element (JsonArray *array,
+                              guint      index_)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (array != NULL, NULL);
+  g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+  node = g_ptr_array_index (array->elements, index_);
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY, NULL);
+
+  return json_node_get_array (node);
+}
+
+/**
+ * json_array_get_object_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the object from the element at @index_
+ * inside @array
+ *
+ * See also: json_array_get_element(), json_node_get_object()
+ *
+ * Return value: the object
+ *
+ * Since: 0.8
+ */
+JsonObject *
+json_array_get_object_element (JsonArray *array,
+                               guint      index_)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (array != NULL, NULL);
+  g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+  node = g_ptr_array_index (array->elements, index_);
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT, NULL);
+
+  return json_node_get_object (node);
+}
+
+/**
  * json_array_get_length:
  * @array: a #JsonArray
  *
@@ -236,6 +471,183 @@ json_array_add_element (JsonArray *array,
 }
 
 /**
+ * json_array_add_int_element:
+ * @array: a #JsonArray
+ * @value: an integer value
+ *
+ * Conveniently adds an integer @value into @array
+ *
+ * See also: json_array_add_element(), json_node_set_int()
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_int_element (JsonArray *array,
+                            gint       value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (array != NULL);
+
+  node = json_node_new (JSON_NODE_VALUE);
+  json_node_set_int (node, value);
+
+  g_ptr_array_add (array->elements, node);
+}
+
+/**
+ * json_array_add_double_element:
+ * @array: a #JsonArray
+ * @value: a floating point value
+ *
+ * Conveniently adds a floating point @value into @array
+ *
+ * See also: json_array_add_element(), json_node_set_double()
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_double_element (JsonArray *array,
+                               gdouble    value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (array != NULL);
+
+  node = json_node_new (JSON_NODE_VALUE);
+  json_node_set_double (node, value);
+
+  g_ptr_array_add (array->elements, node);
+}
+
+/**
+ * json_array_add_boolean_element:
+ * @array: a #JsonArray
+ * @value: a boolean value
+ *
+ * Conveniently adds a boolean @value into @array
+ *
+ * See also: json_array_add_element(), json_node_set_boolean()
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_boolean_element (JsonArray *array,
+                                gboolean   value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (array != NULL);
+
+  node = json_node_new (JSON_NODE_VALUE);
+  json_node_set_boolean (node, value);
+
+  g_ptr_array_add (array->elements, node);
+}
+
+/**
+ * json_array_add_string_element:
+ * @array: a #JsonArray
+ * @value: a string value
+ *
+ * Conveniently adds a string @value into @array
+ *
+ * See also: json_array_add_element(), json_node_set_string()
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_string_element (JsonArray   *array,
+                               const gchar *value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (array != NULL);
+  g_return_if_fail (value != NULL);
+
+  node = json_node_new (JSON_NODE_VALUE);
+  json_node_set_string (node, value);
+
+  g_ptr_array_add (array->elements, node);
+}
+
+/**
+ * json_array_add_null_element:
+ * @array: a #JsonArray
+ *
+ * Conveniently adds a null element into @array
+ *
+ * See also: json_array_add_element(), %JSON_NODE_NULL
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_null_element (JsonArray *array)
+{
+  JsonNode *node;
+
+  g_return_if_fail (array != NULL);
+
+  node = json_node_new (JSON_NODE_NULL);
+
+  g_ptr_array_add (array->elements, node);
+}
+
+/**
+ * json_array_add_array_element:
+ * @array: a #JsonArray
+ * @value: a #JsonArray
+ *
+ * Conveniently adds an array into @array. The @array takes ownership
+ * of the newly added #JsonArray
+ *
+ * See also: json_array_add_element(), json_node_take_array()
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_array_element (JsonArray *array,
+                              JsonArray *value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (array != NULL);
+  g_return_if_fail (value != NULL);
+
+  node = json_node_new (JSON_NODE_ARRAY);
+  json_node_take_array (node, value);
+
+  g_ptr_array_add (array->elements, node);
+}
+
+/**
+ * json_array_add_object_element:
+ * @array: a #JsonArray
+ * @value: a #JsonObject
+ *
+ * Conveniently adds an object into @array. The @array takes ownership
+ * of the newly added #JsonObject
+ *
+ * See also: json_array_add_element(), json_node_take_object()
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_object_element (JsonArray  *array,
+                               JsonObject *value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (array != NULL);
+  g_return_if_fail (value != NULL);
+
+  node = json_node_new (JSON_NODE_OBJECT);
+  json_node_take_object (node, value);
+
+  g_ptr_array_add (array->elements, node);
+}
+
+/**
  * json_array_remove_element:
  * @array: a #JsonArray
  * @index_: the position of the element to be removed
@@ -252,3 +664,38 @@ json_array_remove_element (JsonArray *array,
 
   json_node_free (g_ptr_array_remove_index (array->elements, index_));
 }
+
+/**
+ * json_array_foreach_element:
+ * @array: a #JsonArray
+ * @func: the function to be called on each element
+ * @data: data to be passed to the function
+ *
+ * Iterates over all elements of @array and calls @func on
+ * each one of them.
+ *
+ * It is safe to change the value of a #JsonNode of the @array
+ * from within the iterator @func, but it is not safe to add or
+ * remove elements from the @array.
+ *
+ * Since: 0.8
+ */
+void
+json_array_foreach_element (JsonArray        *array,
+                            JsonArrayForeach  func,
+                            gpointer          data)
+{
+  gint i;
+
+  g_return_if_fail (array != NULL);
+  g_return_if_fail (func != NULL);
+
+  for (i = 0; i < array->elements->len; i++)
+    {
+      JsonNode *element_node;
+
+      element_node = g_ptr_array_index (array->elements, i);
+
+      (* func) (array, i, element_node, data);
+    }
+}
index 78c251b..d1c8717 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
-#include "json-marshal.h"
+#include "json-types-private.h"
+
 #include "json-generator.h"
+#include "json-marshal.h"
 
 #define JSON_GENERATOR_GET_PRIVATE(obj) \
         (G_TYPE_INSTANCE_GET_PRIVATE ((obj), JSON_TYPE_GENERATOR, JsonGeneratorPrivate))
index f20f7ad..1a0aeee 100644 (file)
@@ -2,19 +2,23 @@
  * 
  * This file is part of JSON-GLib
  * Copyright (C) 2007  OpenedHand Ltd.
+ * Copyright (C) 2009  Intel Corp.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
  * Author:
- *   Emmanuele Bassi  <ebassi@openedhand.com>
+ *   Emmanuele Bassi  <ebassi@linux.intel.com>
  */
 
 #ifdef HAVE_CONFIG_H
@@ -23,7 +27,7 @@
 
 #include <glib.h>
 
-#include "json-types.h"
+#include "json-types-private.h"
 
 /**
  * SECTION:json-node
  * When parsing a JSON data stream you extract the root node and walk
  * the node tree by retrieving the type of data contained inside the
  * node with the %JSON_NODE_TYPE macro. If the node contains a fundamental
- * type you can retrieve a copy of the GValue holding it with the
- * json_node_get_value() function, and then use the GValue API to extract
+ * type you can retrieve a copy of the #GValue holding it with the
+ * json_node_get_value() function, and then use the #GValue API to extract
  * the data; if the node contains a complex type you can retrieve the
  * #JsonObject or the #JsonArray using json_node_get_object() or
  * json_node_get_array() respectively, and then retrieve the nodes
  * they contain.
  */
 
+GType
+json_node_get_type (void)
+{
+  static GType node_type = 0;
+
+  if (G_UNLIKELY (node_type == 0))
+    node_type = g_boxed_type_register_static (g_intern_static_string ("JsonNode"),
+                                              (GBoxedCopyFunc) json_node_copy,
+                                              (GBoxedFreeFunc) json_node_free);
+
+  return node_type;
+}
+
+/**
+ * json_node_get_value_type:
+ * @node: a #JsonNode
+ *
+ * Returns the #GType of the payload of the node.
+ *
+ * Return value: a #GType for the payload.
+ *
+ * Since: 0.4
+ */
+GType
+json_node_get_value_type (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, G_TYPE_INVALID);
+
+  switch (node->type)
+    {
+    case JSON_NODE_OBJECT:
+      return JSON_TYPE_OBJECT;
+
+    case JSON_NODE_ARRAY:
+      return JSON_TYPE_ARRAY;
+
+    case JSON_NODE_NULL:
+      return G_TYPE_INVALID;
+
+    case JSON_NODE_VALUE:
+      return G_VALUE_TYPE (&(node->data.value));
+
+    default:
+      g_assert_not_reached ();
+      return G_TYPE_INVALID;
+    }
+}
+
 /**
  * json_node_new:
  * @type: a #JsonNodeType
@@ -57,7 +109,8 @@ json_node_new (JsonNodeType type)
 {
   JsonNode *data;
 
-  g_return_val_if_fail (type >= JSON_NODE_OBJECT && type <= JSON_NODE_NULL, NULL);
+  g_return_val_if_fail (type >= JSON_NODE_OBJECT &&
+                        type <= JSON_NODE_NULL, NULL);
 
   data = g_slice_new0 (JsonNode);
   data->type = type;
@@ -81,23 +134,32 @@ json_node_copy (JsonNode *node)
 
   g_return_val_if_fail (node != NULL, NULL);
 
-  copy = g_slice_new (JsonNode);
-  *copy = *node;
+  copy = g_slice_new0 (JsonNode);
+  copy->type = node->type;
 
   switch (copy->type)
     {
     case JSON_NODE_OBJECT:
-      copy->data.object = json_object_ref (node->data.object);
+      if (node->data.object)
+        copy->data.object = json_object_ref (node->data.object);
       break;
+
     case JSON_NODE_ARRAY:
-      copy->data.array = json_array_ref (node->data.array);
+      if (node->data.array)
+        copy->data.array = json_array_ref (node->data.array);
       break;
+
     case JSON_NODE_VALUE:
-      g_value_init (&(copy->data.value), G_VALUE_TYPE (&(node->data.value)));
-      g_value_copy (&(node->data.value), &(copy->data.value));
+      if (G_VALUE_TYPE (&(node->data.value)) != G_TYPE_INVALID)
+        {
+          g_value_init (&(copy->data.value), G_VALUE_TYPE (&(node->data.value)));
+          g_value_copy (&(node->data.value), &(copy->data.value));
+        }
       break;
+
     case JSON_NODE_NULL:
       break;
+
     default:
       g_assert_not_reached ();
     }
@@ -158,7 +220,7 @@ json_node_take_object (JsonNode   *node,
  *
  * Retrieves the #JsonObject stored inside a #JsonNode
  *
- * Return value: (transfer none): the #JsonObject
+ * Return value: the #JsonObject
  */
 JsonObject *
 json_node_get_object (JsonNode *node)
@@ -243,7 +305,7 @@ json_node_take_array (JsonNode  *node,
  *
  * Retrieves the #JsonArray stored inside a #JsonNode
  *
- * Return value: (transfer none): the #JsonArray
+ * Return value: the #JsonArray
  */
 JsonArray *
 json_node_get_array (JsonNode *node)
@@ -290,7 +352,7 @@ json_node_get_value (JsonNode *node,
   g_return_if_fail (node != NULL);
   g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
 
-  if (G_VALUE_TYPE (&(node->data.value)) != 0)
+  if (G_VALUE_TYPE (&(node->data.value)) != G_TYPE_INVALID)
     {
       g_value_init (value, G_VALUE_TYPE (&(node->data.value)));
       g_value_copy (&(node->data.value), value);
@@ -391,7 +453,7 @@ json_node_type_name (JsonNode *node)
  *
  * Retrieves the parent #JsonNode of @node.
  *
- * Return value: (transfer none): the parent node, or %NULL if @node is the root node
+ * Return value: the parent node, or %NULL if @node is the root node
  */
 JsonNode *
 json_node_get_parent (JsonNode *node)
@@ -443,7 +505,9 @@ G_CONST_RETURN gchar *
 json_node_get_string (JsonNode *node)
 {
   g_return_val_if_fail (node != NULL, NULL);
-  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, NULL);
+
+  if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
+    return NULL;
 
   if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_STRING)
     return g_value_get_string (&(node->data.value));
@@ -451,14 +515,25 @@ json_node_get_string (JsonNode *node)
   return NULL;
 }
 
+/**
+ * json_node_dup_string:
+ * @node: a #JsonNode of type %JSON_NODE_VALUE
+ *
+ * Gets a copy of the string value stored inside a #JsonNode
+ *
+ * Return value: a newly allocated string containing a copy of
+ *   the #JsonNode contents
+ */
 gchar *
 json_node_dup_string (JsonNode *node)
 {
   g_return_val_if_fail (node != NULL, NULL);
-  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, NULL);
+
+  if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
+    return NULL;
 
   if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_STRING)
-    return g_strdup (g_value_get_string (&(node->data.value)));
+    return g_value_dup_string (&(node->data.value));
 
   return NULL;
 }
@@ -505,7 +580,9 @@ gint
 json_node_get_int (JsonNode *node)
 {
   g_return_val_if_fail (node != NULL, 0);
-  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0);
+
+  if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
+    return 0;
 
   if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_INT)
     return g_value_get_int (&(node->data.value));
@@ -555,7 +632,9 @@ gdouble
 json_node_get_double (JsonNode *node)
 {
   g_return_val_if_fail (node != NULL, 0.0);
-  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0.0);
+
+  if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
+    return 0;
 
   if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_DOUBLE)
     return g_value_get_double (&(node->data.value));
@@ -605,10 +684,50 @@ gboolean
 json_node_get_boolean (JsonNode *node)
 {
   g_return_val_if_fail (node != NULL, FALSE);
-  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, FALSE);
+
+  if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
+    return FALSE;
 
   if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_BOOLEAN)
     return g_value_get_boolean (&(node->data.value));
 
   return FALSE;
 }
+
+/**
+ * json_node_get_node_type:
+ * @node: a #JsonNode
+ *
+ * Retrieves the #JsonNodeType of @node
+ *
+ * Return value: the type of the node
+ *
+ * Since: 0.8
+ */
+JsonNodeType
+json_node_get_node_type (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, JSON_NODE_NULL);
+
+  return node->type;
+}
+
+/**
+ * json_node_is_null:
+ * @node: a #JsonNode
+ *
+ * Checks whether @node is a %JSON_NODE_NULL
+ *
+ * <note>A null node is not the same as a %NULL #JsonNode</note>
+ *
+ * Return value: %TRUE if the node is null
+ *
+ * Since: 0.8
+ */
+gboolean
+json_node_is_null (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, TRUE);
+
+  return node->type == JSON_NODE_NULL;
+}
index 92bf6d3..7952274 100644 (file)
@@ -2,19 +2,23 @@
  * 
  * This file is part of JSON-GLib
  * Copyright (C) 2007  OpenedHand Ltd.
+ * Copyright (C) 2009  Intel Corp.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
  * Author:
- *   Emmanuele Bassi  <ebassi@openedhand.com>
+ *   Emmanuele Bassi  <ebassi@linux.intel.com>
  */
 
 #ifdef HAVE_CONFIG_H
@@ -23,7 +27,7 @@
 
 #include <glib.h>
 
-#include "json-types.h"
+#include "json-types-private.h"
 
 /**
  * SECTION:json-object
  *
  * #JsonArray is the representation of the object type inside JSON. It contains
  * #JsonNode<!-- -->s, which may contain fundamental types, arrays or other
- * objects. Each member of an object is accessed using its name.
+ * objects. Each member of an object is accessed using its name. Please note
+ * that the member names are normalized internally before being used; every
+ * delimiter matching the %G_STR_DELIMITER macro will be transformed into an
+ * underscore, so for instance "member-name" and "member_name" are equivalent
+ * for a #JsonObject.
  *
  * Since objects can be expensive, they are reference counted. You can control
  * the lifetime of a #JsonObject using json_object_ref() and json_object_unref().
  *
- * To add a member with a given name, use json_object_add_member().
+ * To add or overwrite a member with a given name, use json_object_set_member().
  * To extract a member with a given name, use json_object_get_member().
  * To retrieve the list of members, use json_object_get_members().
- * To retrieve the size of the object (that is, the number of members it has), use
- * json_object_get_size().
+ * To retrieve the size of the object (that is, the number of members it has),
+ * use json_object_get_size().
  */
 
-struct _JsonObject
-{
-  GHashTable *members;
-
-  volatile gint ref_count;
-};
-
 GType
 json_object_get_type (void)
 {
   static GType object_type = 0;
 
   if (G_UNLIKELY (!object_type))
-    object_type = g_boxed_type_register_static ("JsonObject",
-                                               (GBoxedCopyFunc) json_object_ref,
-                                               (GBoxedFreeFunc) json_object_unref);
+    object_type = g_boxed_type_register_static (g_intern_static_string ("JsonObject"),
+                                                (GBoxedCopyFunc) json_object_ref,
+                                                (GBoxedFreeFunc) json_object_unref);
 
   return object_type;
 }
@@ -133,6 +134,17 @@ json_object_unref (JsonObject *object)
     }
 }
 
+static inline void
+object_set_member_internal (JsonObject  *object,
+                            const gchar *member_name,
+                            JsonNode    *node)
+{
+  gchar *name;
+
+  name = g_strdelimit (g_strdup (member_name), G_STR_DELIMITERS, '_');
+  g_hash_table_replace (object->members, name, node);
+}
+
 /**
  * json_object_add_member:
  * @object: a #JsonObject
@@ -141,6 +153,11 @@ json_object_unref (JsonObject *object)
  *
  * Adds a member named @member_name and containing @node into a #JsonObject.
  * The object will take ownership of the #JsonNode.
+ *
+ * This function will return if the @object already contains a member
+ * @member_name.
+ *
+ * Deprecated: 0.8: Use json_object_set_member() instead
  */
 void
 json_object_add_member (JsonObject  *object,
@@ -155,17 +172,239 @@ json_object_add_member (JsonObject  *object,
 
   if (json_object_has_member (object, member_name))
     {
-      g_warning ("JsonObject already has a '%s' member of type '%s'",
+      g_warning ("JsonObject already has a `%s' member of type `%s'",
                  member_name,
                  json_node_type_name (node));
       return;
     }
 
-  name = g_strdelimit (g_strdup (member_name), G_STR_DELIMITERS, '_');
-  g_hash_table_replace (object->members, name, node);
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_set_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ * @node: the value of the member
+ *
+ * Sets @node as the value of @member_name inside @object.
+ *
+ * If @object already contains a member called @member_name then
+ * the member's current value is overwritten. Otherwise, a new
+ * member is added to @object.
+ *
+ * Since: 0.8
+ */
+void
+json_object_set_member (JsonObject  *object,
+                        const gchar *member_name,
+                        JsonNode    *node)
+{
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+  g_return_if_fail (node != NULL);
+
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_set_int_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ * @value: the value of the member
+ *
+ * Convenience function for setting an integer @value of
+ * @member_name inside @object.
+ *
+ * See also: json_object_set_member()
+ *
+ * Since: 0.8
+ */
+void
+json_object_set_int_member (JsonObject  *object,
+                            const gchar *member_name,
+                            gint         value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+
+  node = json_node_new (JSON_NODE_VALUE);
+  json_node_set_int (node, value);
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_set_double_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ * @value: the value of the member
+ *
+ * Convenience function for setting a floating point @value
+ * of @member_name inside @object.
+ *
+ * See also: json_object_set_member()
+ *
+ * Since: 0.8
+ */
+void
+json_object_set_double_member (JsonObject  *object,
+                               const gchar *member_name,
+                               gdouble      value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+
+  node = json_node_new (JSON_NODE_VALUE);
+  json_node_set_double (node, value);
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_set_boolean_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ * @value: the value of the member
+ *
+ * Convenience function for setting a boolean @value of
+ * @member_name inside @object.
+ *
+ * See also: json_object_set_member()
+ *
+ * Since: 0.8
+ */
+void
+json_object_set_boolean_member (JsonObject  *object,
+                                const gchar *member_name,
+                                gboolean     value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+
+  node = json_node_new (JSON_NODE_VALUE);
+  json_node_set_boolean (node, value);
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_set_string_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ * @value: the value of the member
+ *
+ * Convenience function for setting a string @value of
+ * @member_name inside @object.
+ *
+ * See also: json_object_set_member()
+ *
+ * Since: 0.8
+ */
+void
+json_object_set_string_member (JsonObject  *object,
+                               const gchar *member_name,
+                               const gchar *value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+
+  node = json_node_new (JSON_NODE_VALUE);
+  json_node_set_string (node, value);
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_set_null_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function for setting a null @value of
+ * @member_name inside @object.
+ *
+ * See also: json_object_set_member()
+ *
+ * Since: 0.8
+ */
+void
+json_object_set_null_member (JsonObject  *object,
+                             const gchar *member_name)
+{
+  JsonNode *node;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+
+  node = json_node_new (JSON_NODE_NULL);
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_set_array_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ * @value: the value of the member
+ *
+ * Convenience function for setting an array @value of
+ * @member_name inside @object.
+ *
+ * The @object will take ownership of the passed #JsonArray
+ *
+ * See also: json_object_set_member()
+ *
+ * Since: 0.8
+ */
+void
+json_object_set_array_member (JsonObject  *object,
+                              const gchar *member_name,
+                              JsonArray   *value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+
+  node = json_node_new (JSON_NODE_ARRAY);
+  json_node_take_array (node, value);
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_set_object_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ * @value: the value of the member
+ *
+ * Convenience function for setting an object @value of
+ * @member_name inside @object.
+ *
+ * The @object will take ownership of the passed #JsonArray
+ *
+ * See also: json_object_set_member()
+ *
+ * Since: 0.8
+ */
+void
+json_object_set_object_member (JsonObject  *object,
+                               const gchar *member_name,
+                               JsonObject  *value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+
+  node = json_node_new (JSON_NODE_ARRAY);
+  json_node_take_object (node, value);
+  object_set_member_internal (object, member_name, node);
 }
 
-/* FIXME: yuck. we really need to depend on GLib 2.14 */
+/* FIXME: yuck */
 #if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 14
 static void
 get_keys (gpointer key,
@@ -177,6 +416,16 @@ get_keys (gpointer key,
   *keys = g_list_prepend (*keys, key);
 }
 
+static void
+get_values (gpointer key,
+            gpointer value,
+            gpointer user_data)
+{
+  GList **values = user_data;
+
+  *values = g_list_prepend (*values, value);
+}
+
 static GList *
 g_hash_table_get_keys (GHashTable *hash_table)
 {
@@ -188,6 +437,18 @@ g_hash_table_get_keys (GHashTable *hash_table)
 
   return retval;
 }
+
+static GList *
+g_hash_table_get_values (GHashTable *hash_table)
+{
+  GList *retval = NULL;
+
+  g_return_val_if_fail (hash_table != NULL, NULL);
+
+  g_hash_table_foreach (hash_table, get_values, &retval);
+
+  return retval;
+}
 #endif /* GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 14 */
 
 /**
@@ -197,11 +458,10 @@ g_hash_table_get_keys (GHashTable *hash_table)
  * Retrieves all the names of the members of a #JsonObject. You can
  * obtain the value for each member using json_object_get_member().
  *
- * Return value: (transfer container) (element-type utf8): a #GList of
- *   member names. The content of the list is owned by the #JsonObject
- *   and should never be modified or freed. When you have finished using
- *   the returned list, use g_list_free() to free the resources it has
- *   allocated.
+ * Return value: a #GList of member names. The content of the list
+ *   is owned by the #JsonObject and should never be modified or
+ *   freed. When you have finished using the returned list, use
+ *   g_list_free() to free the resources it has allocated.
  */
 GList *
 json_object_get_members (JsonObject *object)
@@ -212,34 +472,300 @@ json_object_get_members (JsonObject *object)
 }
 
 /**
- * json_object_get_member:
+ * json_object_get_values:
+ * @object: a #JsonObject
+ *
+ * Retrieves all the values of the members of a #JsonObject.
+ *
+ * Return value: a #GList of #JsonNode<!-- -->s. The content of the
+ *   list is owned by the #JsonObject and should never be modified
+ *   or freed. When you have finished using the returned list, use
+ *   g_list_free() to free the resources it has allocated.
+ */
+GList *
+json_object_get_values (JsonObject *object)
+{
+  g_return_val_if_fail (object != NULL, NULL);
+
+  return g_hash_table_get_values (object->members);
+}
+
+/**
+ * json_object_dup_member:
  * @object: a #JsonObject
  * @member_name: the name of the JSON object member to access
  *
- * Retrieves the #JsonNode containing the value of @member_name inside
- * a #JsonObject.
+ * Retrieves a copy of the #JsonNode containing the value of @member_name
+ * inside a #JsonObject
  *
- * Return value: (transfer none): a pointer to the node for the requested object
- *   member, or %NULL
+ * Return value: a copy of the node for the requested object member
+ *   or %NULL. Use json_node_free() when done.
+ *
+ * Since: 0.6
  */
 JsonNode *
-json_object_get_member (JsonObject *object,
+json_object_dup_member (JsonObject  *object,
                         const gchar *member_name)
 {
-  gchar *name;
   JsonNode *retval;
 
   g_return_val_if_fail (object != NULL, NULL);
   g_return_val_if_fail (member_name != NULL, NULL);
 
+  retval = json_object_get_member (object, member_name);
+  if (!retval)
+    return NULL;
+
+  return json_node_copy (retval);
+}
+
+static inline JsonNode *
+object_get_member_internal (JsonObject  *object,
+                            const gchar *member_name)
+{
+  JsonNode *retval;
+  gchar *name;
+
   name = g_strdelimit (g_strdup (member_name), G_STR_DELIMITERS, '_');
+
   retval = g_hash_table_lookup (object->members, name);
+
   g_free (name);
 
   return retval;
 }
 
 /**
+ * json_object_get_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the JSON object member to access
+ *
+ * Retrieves the #JsonNode containing the value of @member_name inside
+ * a #JsonObject.
+ *
+ * Return value: a pointer to the node for the requested object
+ *   member, or %NULL
+ */
+JsonNode *
+json_object_get_member (JsonObject  *object,
+                        const gchar *member_name)
+{
+  g_return_val_if_fail (object != NULL, NULL);
+  g_return_val_if_fail (member_name != NULL, NULL);
+
+  return object_get_member_internal (object, member_name);
+}
+
+/**
+ * json_object_get_int_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function that retrieves the integer value
+ * stored in @member_name of @object
+ *
+ * See also: json_object_get_member()
+ *
+ * Return value: the integer value of the object's member
+ *
+ * Since: 0.8
+ */
+gint
+json_object_get_int_member (JsonObject  *object,
+                            const gchar *member_name)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (object != NULL, 0);
+  g_return_val_if_fail (member_name != NULL, 0);
+
+  node = object_get_member_internal (object, member_name);
+  g_return_val_if_fail (node != NULL, 0);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0);
+
+  return json_node_get_int (node);
+}
+
+/**
+ * json_object_get_double_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function that retrieves the floating point value
+ * stored in @member_name of @object
+ *
+ * See also: json_object_get_member()
+ *
+ * Return value: the floating point value of the object's member
+ *
+ * Since: 0.8
+ */
+gdouble
+json_object_get_double_member (JsonObject  *object,
+                               const gchar *member_name)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (object != NULL, 0.0);
+  g_return_val_if_fail (member_name != NULL, 0.0);
+
+  node = object_get_member_internal (object, member_name);
+  g_return_val_if_fail (node != NULL, 0.0);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0.0);
+
+  return json_node_get_double (node);
+}
+
+/**
+ * json_object_get_boolean_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function that retrieves the boolean value
+ * stored in @member_name of @object
+ *
+ * See also: json_object_get_member()
+ *
+ * Return value: the boolean value of the object's member
+ *
+ * Since: 0.8
+ */
+gboolean
+json_object_get_boolean_member (JsonObject  *object,
+                                const gchar *member_name)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (object != NULL, FALSE);
+  g_return_val_if_fail (member_name != NULL, FALSE);
+
+  node = object_get_member_internal (object, member_name);
+  g_return_val_if_fail (node != NULL, FALSE);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, FALSE);
+
+  return json_node_get_boolean (node);
+}
+
+/**
+ * json_object_get_null_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function that checks whether the value
+ * stored in @member_name of @object is null
+ *
+ * See also: json_object_get_member()
+ *
+ * Return value: %TRUE if the value is null
+ *
+ * Since: 0.8
+ */
+gboolean
+json_object_get_null_member (JsonObject  *object,
+                             const gchar *member_name)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (object != NULL, FALSE);
+  g_return_val_if_fail (member_name != NULL, FALSE);
+
+  node = object_get_member_internal (object, member_name);
+  g_return_val_if_fail (node != NULL, FALSE);
+
+  return JSON_NODE_TYPE (node) == JSON_NODE_NULL;
+}
+
+/**
+ * json_object_get_string_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function that retrieves the string value
+ * stored in @member_name of @object
+ *
+ * See also: json_object_get_member()
+ *
+ * Return value: the string value of the object's member
+ *
+ * Since: 0.8
+ */
+G_CONST_RETURN gchar *
+json_object_get_string_member (JsonObject  *object,
+                               const gchar *member_name)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (object != NULL, NULL);
+  g_return_val_if_fail (member_name != NULL, NULL);
+
+  node = object_get_member_internal (object, member_name);
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, NULL);
+
+  return json_node_get_string (node);
+}
+
+/**
+ * json_object_get_array_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function that retrieves the array
+ * stored in @member_name of @object
+ *
+ * See also: json_object_get_member()
+ *
+ * Return value: the array inside the object's member
+ *
+ * Since: 0.8
+ */
+JsonArray *
+json_object_get_array_member (JsonObject  *object,
+                              const gchar *member_name)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (object != NULL, NULL);
+  g_return_val_if_fail (member_name != NULL, NULL);
+
+  node = object_get_member_internal (object, member_name);
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY, NULL);
+
+  return json_node_get_array (node);
+}
+
+/**
+ * json_object_get_object_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function that retrieves the object
+ * stored in @member_name of @object
+ *
+ * See also: json_object_get_member()
+ *
+ * Return value: the object inside the object's member
+ *
+ * Since: 0.8
+ */
+JsonObject *
+json_object_get_object_member (JsonObject  *object,
+                               const gchar *member_name)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (object != NULL, NULL);
+  g_return_val_if_fail (member_name != NULL, NULL);
+
+  node = object_get_member_internal (object, member_name);
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT, NULL);
+
+  return json_node_get_object (node);
+}
+
+/**
  * json_object_has_member:
  * @object: a #JsonObject
  * @member_name: the name of a JSON object member
@@ -301,3 +827,58 @@ json_object_remove_member (JsonObject  *object,
   g_hash_table_remove (object->members, name);
   g_free (name);
 }
+
+typedef struct _ForeachClosure  ForeachClosure;
+
+struct _ForeachClosure
+{
+  JsonObject *object;
+
+  JsonObjectForeach func;
+  gpointer data;
+};
+
+static void
+json_object_foreach_internal (gpointer key,
+                              gpointer value,
+                              gpointer data)
+{
+  ForeachClosure *clos = data;
+  const gchar *member_name = key;
+  JsonNode *member_node = value;
+
+  clos->func (clos->object, member_name, member_node, clos->data);
+}
+
+/**
+ * json_object_foreach_member:
+ * @object: a #JsonObject
+ * @func: the function to be called on each member
+ * @data: data to be passed to the function
+ *
+ * Iterates over all members of @object and calls @func on
+ * each one of them.
+ *
+ * It is safe to change the value of a #JsonNode of the @object
+ * from within the iterator @func, but it is not safe to add or
+ * remove members from the @object.
+ *
+ * Since: 0.8
+ */
+void
+json_object_foreach_member (JsonObject        *object,
+                            JsonObjectForeach  func,
+                            gpointer           data)
+{
+  ForeachClosure clos;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (func != NULL);
+
+  clos.object = object;
+  clos.func = func;
+  clos.data = data;
+  g_hash_table_foreach (object->members,
+                        json_object_foreach_internal,
+                        &clos);
+}
index 7855dd3..526ec45 100644 (file)
@@ -31,6 +31,8 @@
 
 #include <string.h>
 
+#include "json-types-private.h"
+
 #include "json-marshal.h"
 #include "json-parser.h"
 
@@ -587,7 +589,7 @@ json_parse_object (JsonParser *parser,
               return token;
             }
 
-          json_object_add_member (object, name, node);
+          json_object_set_member (object, name, node);
           node->parent = priv->current_node;
 
           g_signal_emit (parser, parser_signals[OBJECT_MEMBER], 0,
@@ -623,7 +625,7 @@ json_parse_object (JsonParser *parser,
               return token;
             }
 
-          json_object_add_member (object, name, node);
+          json_object_set_member (object, name, node);
           node->parent = priv->current_node;
           
           g_signal_emit (parser, parser_signals[OBJECT_MEMBER], 0,
@@ -693,7 +695,7 @@ json_parse_object (JsonParser *parser,
 
       if (node)
         {
-          json_object_add_member (object, name, node);
+          json_object_set_member (object, name, node);
           node->parent = priv->current_node;
           
           g_signal_emit (parser, parser_signals[OBJECT_MEMBER], 0,
diff --git a/clutter/json/json-types-private.h b/clutter/json/json-types-private.h
new file mode 100644 (file)
index 0000000..728b367
--- /dev/null
@@ -0,0 +1,61 @@
+/* json-types-private.h - JSON data types private header
+ *
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd
+ * Copyright (C) 2009  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi@linux.intel.com>
+ */
+
+#ifndef __JSON_TYPES_PRIVATE_H__
+#define __JSON_TYPES_PRIVATE_H__
+
+#include "json-types.h"
+
+G_BEGIN_DECLS
+
+struct _JsonNode
+{
+  /*< private >*/
+  JsonNodeType type;
+
+  union {
+    JsonObject *object;
+    JsonArray *array;
+    GValue value;
+  } data;
+
+  JsonNode *parent;
+};
+
+struct _JsonArray
+{
+  GPtrArray *elements;
+
+  volatile gint ref_count;
+};
+
+struct _JsonObject
+{
+  GHashTable *members;
+
+  volatile gint ref_count;
+};
+
+G_END_DECLS
+
+#endif /* __JSON_TYPES_PRIVATE_H__ */
index 8229401..1538488 100644 (file)
@@ -2,19 +2,23 @@
  * 
  * This file is part of JSON-GLib
  * Copyright (C) 2007  OpenedHand Ltd.
+ * Copyright (C) 2009  Intel Corp.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
  * Author:
- *   Emmanuele Bassi  <ebassi@openedhand.com>
+ *   Emmanuele Bassi  <ebassi@linux.intel.com>
  */
 
 #ifndef __JSON_TYPES_H__
@@ -30,15 +34,23 @@ G_BEGIN_DECLS
  *
  * Evaluates to the #JsonNodeType contained by @node
  */
-#define JSON_NODE_TYPE(node)            \
-        (((JsonNode *) (node))->type)
-#define JSON_NODE_VALUE_TYPE(node)      \
-        (G_VALUE_TYPE ((((JsonNode *) (node))->data.value))
+#define JSON_NODE_TYPE(node)    (json_node_get_node_type ((node)))
 
+#define JSON_TYPE_NODE          (json_node_get_type ())
 #define JSON_TYPE_OBJECT        (json_object_get_type ())
 #define JSON_TYPE_ARRAY         (json_array_get_type ())
 
 /**
+ * JsonNode:
+ * @type: the type of node
+ *
+ * A generic container of JSON data types. The contents of the #JsonNode
+ * structure are private and should only be accessed via the provided
+ * functions and never directly.
+ */
+typedef struct _JsonNode        JsonNode;
+
+/**
  * JsonObject:
  *
  * A JSON object type. The contents of the #JsonObject structure are private
@@ -54,14 +66,12 @@ typedef struct _JsonObject      JsonObject;
  */
 typedef struct _JsonArray       JsonArray;
 
-typedef struct _JsonNode        JsonNode;
-
 /**
  * JsonNodeType:
  * @JSON_NODE_OBJECT: The node contains a #JsonObject
  * @JSON_NODE_ARRAY: The node contains a #JsonArray
- * @JSON_NODE_VALUE: The node contains a #GValue
- * @JSON_NODE_NULL: Special type, for nodes containing %NULL
+ * @JSON_NODE_VALUE: The node contains a fundamental type
+ * @JSON_NODE_NULL: Special type, for nodes containing null
  *
  * Indicates the content of a #JsonNode.
  */
@@ -73,29 +83,52 @@ typedef enum {
 } JsonNodeType;
 
 /**
- * JsonNode:
+ * JsonObjectForeach:
+ * @object: the iterated #JsonObject
+ * @member_name: the name of the member
+ * @member_node: a #JsonNode containing the @member_name value
+ * @user_data: data passed to the function
  *
- * A generic container of JSON data types. The contents of the #JsonNode
- * structure are private and should only be accessed via the provided
- * functions and never directly.
+ * The function to be passed to json_object_foreach_member(). You
+ * should not add or remove members to and from @object within
+ * this function. It is safe to change the value of @member_node.
+ *
+ * Since: 0.8
  */
-struct _JsonNode
-{
-  /*< private >*/
-  JsonNodeType type;
-
-  union {
-    JsonObject *object;
-    JsonArray *array;
-    GValue value;
-  } data;
+typedef void (* JsonObjectForeach) (JsonObject  *object,
+                                    const gchar *member_name,
+                                    JsonNode    *member_node,
+                                    gpointer     user_data);
 
-  JsonNode *parent;
-};
+/**
+ * JsonArrayForeach:
+ * @array: the iterated #JsonArray
+ * @index_: the index of the element
+ * @element_node: a #JsonNode containing the value at @index_
+ * @user_data: data passed to the function
+ *
+ * The function to be passed to json_array_foreach_element(). You
+ * should not add or remove elements to and from @array within
+ * this function. It is safe to change the value of @element_node.
+ *
+ * Since: 0.8
+ */
+typedef void (* JsonArrayForeach) (JsonArray  *array,
+                                   guint       index_,
+                                   JsonNode   *element_node,
+                                   gpointer    user_data);
 
+/*
+ * JsonNode
+ */
+GType                 json_node_get_type        (void) G_GNUC_CONST;
 JsonNode *            json_node_new             (JsonNodeType  type);
 JsonNode *            json_node_copy            (JsonNode     *node);
 void                  json_node_free            (JsonNode     *node);
+JsonNodeType          json_node_get_node_type   (JsonNode     *node);
+GType                 json_node_get_value_type  (JsonNode     *node);
+JsonNode *            json_node_get_parent      (JsonNode     *node);
+G_CONST_RETURN gchar *json_node_type_name       (JsonNode     *node);
 
 void                  json_node_set_object      (JsonNode     *node,
                                                  JsonObject   *object);
@@ -126,38 +159,119 @@ gdouble               json_node_get_double      (JsonNode     *node);
 void                  json_node_set_boolean     (JsonNode     *node,
                                                  gboolean      value);
 gboolean              json_node_get_boolean     (JsonNode     *node);
-JsonNode *            json_node_get_parent      (JsonNode     *node);
-G_CONST_RETURN gchar *json_node_type_name       (JsonNode     *node);
+gboolean              json_node_is_null         (JsonNode     *node);
+
+/*
+ * JsonObject
+ */
+GType                 json_object_get_type           (void) G_GNUC_CONST;
+JsonObject *          json_object_new                (void);
+JsonObject *          json_object_ref                (JsonObject  *object);
+void                  json_object_unref              (JsonObject  *object);
+
+#ifndef JSON_DISABLE_DEPRECATED
+void                  json_object_add_member         (JsonObject  *object,
+                                                      const gchar *member_name,
+                                                      JsonNode    *node) G_GNUC_DEPRECATED;
+#endif /* JSON_DISABLE_DEPRECATED */
+
+void                  json_object_set_member         (JsonObject  *object,
+                                                      const gchar *member_name,
+                                                      JsonNode    *node);
+void                  json_object_set_int_member     (JsonObject  *object,
+                                                      const gchar *member_name,
+                                                      gint         value);
+void                  json_object_set_double_member  (JsonObject  *object,
+                                                      const gchar *member_name,
+                                                      gdouble      value);
+void                  json_object_set_boolean_member (JsonObject  *object,
+                                                      const gchar *member_name,
+                                                      gboolean     value);
+void                  json_object_set_string_member  (JsonObject  *object,
+                                                      const gchar *member_name,
+                                                      const gchar *value);
+void                  json_object_set_null_member    (JsonObject  *object,
+                                                      const gchar *member_name);
+void                  json_object_set_array_member   (JsonObject  *object,
+                                                      const gchar *member_name,
+                                                      JsonArray   *value);
+void                  json_object_set_object_member  (JsonObject  *object,
+                                                      const gchar *member_name,
+                                                      JsonObject  *value);
+GList *               json_object_get_members        (JsonObject  *object);
+JsonNode *            json_object_get_member         (JsonObject  *object,
+                                                      const gchar *member_name);
+JsonNode *            json_object_dup_member         (JsonObject  *object,
+                                                      const gchar *member_name);
+gint                  json_object_get_int_member     (JsonObject  *object,
+                                                      const gchar *member_name);
+gdouble               json_object_get_double_member  (JsonObject  *object,
+                                                      const gchar *member_name);
+gboolean              json_object_get_boolean_member (JsonObject  *object,
+                                                      const gchar *member_name);
+G_CONST_RETURN gchar *json_object_get_string_member  (JsonObject  *object,
+                                                      const gchar *member_name);
+gboolean              json_object_get_null_member    (JsonObject  *object,
+                                                      const gchar *member_name);
+JsonArray *           json_object_get_array_member   (JsonObject  *object,
+                                                      const gchar *member_name);
+JsonObject *          json_object_get_object_member  (JsonObject  *object,
+                                                      const gchar *member_name);
+gboolean              json_object_has_member         (JsonObject  *object,
+                                                      const gchar *member_name);
+void                  json_object_remove_member      (JsonObject  *object,
+                                                      const gchar *member_name);
+GList *               json_object_get_values         (JsonObject  *object);
+guint                 json_object_get_size           (JsonObject  *object);
+void                  json_object_foreach_member     (JsonObject  *object,
+                                                      JsonObjectForeach func,
+                                                      gpointer     data);
 
-GType                 json_object_get_type      (void) G_GNUC_CONST;
-JsonObject *          json_object_new           (void);
-JsonObject *          json_object_ref           (JsonObject  *object);
-void                  json_object_unref         (JsonObject  *object);
-void                  json_object_add_member    (JsonObject  *object,
-                                                 const gchar *member_name,
-                                                 JsonNode    *node);
-GList *               json_object_get_members   (JsonObject  *object);
-JsonNode *            json_object_get_member    (JsonObject  *object,
-                                                 const gchar *member_name);
-gboolean              json_object_has_member    (JsonObject  *object,
-                                                 const gchar *member_name);
-void                  json_object_remove_member (JsonObject  *object,
-                                                 const gchar *member_name);
-guint                 json_object_get_size      (JsonObject  *object);
-
-GType                 json_array_get_type       (void) G_GNUC_CONST;
-JsonArray *           json_array_new            (void);
-JsonArray *           json_array_sized_new      (guint        n_elements);
-JsonArray *           json_array_ref            (JsonArray   *array);
-void                  json_array_unref          (JsonArray   *array);
-void                  json_array_add_element    (JsonArray   *array,
-                                                 JsonNode    *node);
-GList *               json_array_get_elements   (JsonArray   *array);
-JsonNode *            json_array_get_element    (JsonArray   *array,
-                                                 guint        index_);
-void                  json_array_remove_element (JsonArray   *array,
-                                                 guint        index_);
-guint                 json_array_get_length     (JsonArray   *array);
+GType                 json_array_get_type            (void) G_GNUC_CONST;
+JsonArray *           json_array_new                 (void);
+JsonArray *           json_array_sized_new           (guint        n_elements);
+JsonArray *           json_array_ref                 (JsonArray   *array);
+void                  json_array_unref               (JsonArray   *array);
+void                  json_array_add_element         (JsonArray   *array,
+                                                      JsonNode    *node);
+void                  json_array_add_int_element     (JsonArray   *array,
+                                                      gint         value);
+void                  json_array_add_double_element  (JsonArray   *array,
+                                                      gdouble      value);
+void                  json_array_add_boolean_element (JsonArray   *array,
+                                                      gboolean     value);
+void                  json_array_add_string_element  (JsonArray   *array,
+                                                      const gchar *value);
+void                  json_array_add_null_element    (JsonArray   *array);
+void                  json_array_add_array_element   (JsonArray   *array,
+                                                      JsonArray   *value);
+void                  json_array_add_object_element  (JsonArray   *array,
+                                                      JsonObject  *value);
+GList *               json_array_get_elements        (JsonArray   *array);
+JsonNode *            json_array_get_element         (JsonArray   *array,
+                                                      guint        index_);
+gint                  json_array_get_int_element     (JsonArray   *array,
+                                                      guint        index_);
+gdouble               json_array_get_double_element  (JsonArray   *array,
+                                                      guint        index_);
+gboolean              json_array_get_boolean_element (JsonArray   *array,
+                                                      guint        index_);
+G_CONST_RETURN gchar *json_array_get_string_element  (JsonArray   *array,
+                                                      guint        index_);
+gboolean              json_array_get_null_element    (JsonArray   *array,
+                                                      guint        index_);
+JsonArray *           json_array_get_array_element   (JsonArray   *array,
+                                                      guint        index_);
+JsonObject *          json_array_get_object_element  (JsonArray   *array,
+                                                      guint        index_);
+JsonNode *            json_array_dup_element         (JsonArray   *array,
+                                                      guint        index_);
+void                  json_array_remove_element      (JsonArray   *array,
+                                                      guint        index_);
+guint                 json_array_get_length          (JsonArray   *array);
+void                  json_array_foreach_element     (JsonArray   *array,
+                                                      JsonArrayForeach func,
+                                                      gpointer     data);
 
 G_END_DECLS