[json] Update the internal JSON-GLib copy

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.
This commit is contained in:
Emmanuele Bassi 2009-06-09 12:42:19 +01:00
parent 91856b1bed
commit d743aeaa21
8 changed files with 1459 additions and 133 deletions

View File

@ -702,7 +702,7 @@ json_object_end (JsonParser *parser,
val = json_node_new (JSON_NODE_VALUE); val = json_node_new (JSON_NODE_VALUE);
json_node_set_string (val, fake); json_node_set_string (val, fake);
json_object_add_member (object, "id", val); json_object_set_member (object, "id", val);
g_free (fake); g_free (fake);
} }

View File

@ -2,26 +2,30 @@
* *
* This file is part of JSON-GLib * This file is part of JSON-GLib
* Copyright (C) 2007 OpenedHand Ltd. * Copyright (C) 2007 OpenedHand Ltd.
* Copyright (C) 2009 Intel Corp.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * 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, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * 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: * Author:
* Emmanuele Bassi <ebassi@openedhand.com> * Emmanuele Bassi <ebassi@linux.intel.com>
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
#include "json-types.h" #include "json-types-private.h"
/** /**
* SECTION:json-array * SECTION:json-array
@ -40,20 +44,13 @@
* To retrieve the length of the array, use json_array_get_length(). * To retrieve the length of the array, use json_array_get_length().
*/ */
struct _JsonArray
{
GPtrArray *elements;
volatile gint ref_count;
};
GType GType
json_array_get_type (void) json_array_get_type (void)
{ {
static GType array_type = 0; static GType array_type = 0;
if (G_UNLIKELY (!array_type)) 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, (GBoxedCopyFunc) json_array_ref,
(GBoxedFreeFunc) json_array_unref); (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); g_atomic_int_compare_and_exchange (&array->ref_count, old_ref, old_ref - 1);
else else
{ {
gint i; guint i;
for (i = 0; i < array->elements->len; i++) for (i = 0; i < array->elements->len; i++)
json_node_free (g_ptr_array_index (array->elements, 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. * Gets the elements of a #JsonArray as a list of #JsonNode<!-- -->s.
* *
* Return value: (transfer container) (element-type JsonNode): a #GList containing * Return value: a #GList containing the elements of the array. The
* the elements of the array. The contents of the list are owned by the array and * contents of the list are owned by the array and should never be
* should never be modified or freed. Use g_list_free() on the returned list when * modified or freed. Use g_list_free() on the returned list when
* done using it * done using it
*/ */
GList * GList *
@ -181,6 +178,35 @@ json_array_get_elements (JsonArray *array)
return g_list_reverse (retval); return g_list_reverse (retval);
} }
/**
* 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: * json_array_get_element:
* @array: a #JsonArray * @array: a #JsonArray
@ -189,7 +215,7 @@ json_array_get_elements (JsonArray *array)
* Retrieves the #JsonNode containing the value of the element at @index_ * Retrieves the #JsonNode containing the value of the element at @index_
* inside a #JsonArray. * 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 * JsonNode *
json_array_get_element (JsonArray *array, json_array_get_element (JsonArray *array,
@ -201,6 +227,215 @@ json_array_get_element (JsonArray *array,
return g_ptr_array_index (array->elements, index_); return g_ptr_array_index (array->elements, index_);
} }
/**
* 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: * json_array_get_length:
* @array: a #JsonArray * @array: a #JsonArray
@ -235,6 +470,183 @@ json_array_add_element (JsonArray *array,
g_ptr_array_add (array->elements, node); g_ptr_array_add (array->elements, node);
} }
/**
* 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: * json_array_remove_element:
* @array: a #JsonArray * @array: a #JsonArray
@ -252,3 +664,38 @@ json_array_remove_element (JsonArray *array,
json_node_free (g_ptr_array_remove_index (array->elements, index_)); 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);
}
}

View File

@ -32,8 +32,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "json-marshal.h" #include "json-types-private.h"
#include "json-generator.h" #include "json-generator.h"
#include "json-marshal.h"
#define JSON_GENERATOR_GET_PRIVATE(obj) \ #define JSON_GENERATOR_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), JSON_TYPE_GENERATOR, JsonGeneratorPrivate)) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), JSON_TYPE_GENERATOR, JsonGeneratorPrivate))

View File

@ -2,19 +2,23 @@
* *
* This file is part of JSON-GLib * This file is part of JSON-GLib
* Copyright (C) 2007 OpenedHand Ltd. * Copyright (C) 2007 OpenedHand Ltd.
* Copyright (C) 2009 Intel Corp.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * 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, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * 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: * Author:
* Emmanuele Bassi <ebassi@openedhand.com> * Emmanuele Bassi <ebassi@linux.intel.com>
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -23,7 +27,7 @@
#include <glib.h> #include <glib.h>
#include "json-types.h" #include "json-types-private.h"
/** /**
* SECTION:json-node * SECTION:json-node
@ -36,14 +40,62 @@
* When parsing a JSON data stream you extract the root node and walk * 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 * 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 * 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 * 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 * 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 * the data; if the node contains a complex type you can retrieve the
* #JsonObject or the #JsonArray using json_node_get_object() or * #JsonObject or the #JsonArray using json_node_get_object() or
* json_node_get_array() respectively, and then retrieve the nodes * json_node_get_array() respectively, and then retrieve the nodes
* they contain. * 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: * json_node_new:
* @type: a #JsonNodeType * @type: a #JsonNodeType
@ -57,7 +109,8 @@ json_node_new (JsonNodeType type)
{ {
JsonNode *data; 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 = g_slice_new0 (JsonNode);
data->type = type; data->type = type;
@ -81,23 +134,32 @@ json_node_copy (JsonNode *node)
g_return_val_if_fail (node != NULL, NULL); g_return_val_if_fail (node != NULL, NULL);
copy = g_slice_new (JsonNode); copy = g_slice_new0 (JsonNode);
*copy = *node; copy->type = node->type;
switch (copy->type) switch (copy->type)
{ {
case JSON_NODE_OBJECT: case JSON_NODE_OBJECT:
if (node->data.object)
copy->data.object = json_object_ref (node->data.object); copy->data.object = json_object_ref (node->data.object);
break; break;
case JSON_NODE_ARRAY: case JSON_NODE_ARRAY:
if (node->data.array)
copy->data.array = json_array_ref (node->data.array); copy->data.array = json_array_ref (node->data.array);
break; break;
case JSON_NODE_VALUE: case JSON_NODE_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_init (&(copy->data.value), G_VALUE_TYPE (&(node->data.value)));
g_value_copy (&(node->data.value), &(copy->data.value)); g_value_copy (&(node->data.value), &(copy->data.value));
}
break; break;
case JSON_NODE_NULL: case JSON_NODE_NULL:
break; break;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
} }
@ -158,7 +220,7 @@ json_node_take_object (JsonNode *node,
* *
* Retrieves the #JsonObject stored inside a #JsonNode * Retrieves the #JsonObject stored inside a #JsonNode
* *
* Return value: (transfer none): the #JsonObject * Return value: the #JsonObject
*/ */
JsonObject * JsonObject *
json_node_get_object (JsonNode *node) json_node_get_object (JsonNode *node)
@ -243,7 +305,7 @@ json_node_take_array (JsonNode *node,
* *
* Retrieves the #JsonArray stored inside a #JsonNode * Retrieves the #JsonArray stored inside a #JsonNode
* *
* Return value: (transfer none): the #JsonArray * Return value: the #JsonArray
*/ */
JsonArray * JsonArray *
json_node_get_array (JsonNode *node) 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 (node != NULL);
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE); 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_init (value, G_VALUE_TYPE (&(node->data.value)));
g_value_copy (&(node->data.value), value); g_value_copy (&(node->data.value), value);
@ -391,7 +453,7 @@ json_node_type_name (JsonNode *node)
* *
* Retrieves the parent #JsonNode of @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 * JsonNode *
json_node_get_parent (JsonNode *node) json_node_get_parent (JsonNode *node)
@ -443,7 +505,9 @@ G_CONST_RETURN gchar *
json_node_get_string (JsonNode *node) json_node_get_string (JsonNode *node)
{ {
g_return_val_if_fail (node != NULL, NULL); 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) if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_STRING)
return g_value_get_string (&(node->data.value)); return g_value_get_string (&(node->data.value));
@ -451,14 +515,25 @@ json_node_get_string (JsonNode *node)
return NULL; 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 * gchar *
json_node_dup_string (JsonNode *node) json_node_dup_string (JsonNode *node)
{ {
g_return_val_if_fail (node != NULL, NULL); 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) 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; return NULL;
} }
@ -505,7 +580,9 @@ gint
json_node_get_int (JsonNode *node) json_node_get_int (JsonNode *node)
{ {
g_return_val_if_fail (node != NULL, 0); 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) if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_INT)
return g_value_get_int (&(node->data.value)); return g_value_get_int (&(node->data.value));
@ -555,7 +632,9 @@ gdouble
json_node_get_double (JsonNode *node) json_node_get_double (JsonNode *node)
{ {
g_return_val_if_fail (node != NULL, 0.0); 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) if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_DOUBLE)
return g_value_get_double (&(node->data.value)); return g_value_get_double (&(node->data.value));
@ -605,10 +684,50 @@ gboolean
json_node_get_boolean (JsonNode *node) json_node_get_boolean (JsonNode *node)
{ {
g_return_val_if_fail (node != NULL, FALSE); 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) if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_BOOLEAN)
return g_value_get_boolean (&(node->data.value)); return g_value_get_boolean (&(node->data.value));
return FALSE; 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;
}

View File

@ -2,19 +2,23 @@
* *
* This file is part of JSON-GLib * This file is part of JSON-GLib
* Copyright (C) 2007 OpenedHand Ltd. * Copyright (C) 2007 OpenedHand Ltd.
* Copyright (C) 2009 Intel Corp.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * 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, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * 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: * Author:
* Emmanuele Bassi <ebassi@openedhand.com> * Emmanuele Bassi <ebassi@linux.intel.com>
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -23,7 +27,7 @@
#include <glib.h> #include <glib.h>
#include "json-types.h" #include "json-types-private.h"
/** /**
* SECTION:json-object * SECTION:json-object
@ -31,32 +35,29 @@
* *
* #JsonArray is the representation of the object type inside JSON. It contains * #JsonArray is the representation of the object type inside JSON. It contains
* #JsonNode<!-- -->s, which may contain fundamental types, arrays or other * #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 * 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(). * 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 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 list of members, use json_object_get_members().
* To retrieve the size of the object (that is, the number of members it has), use * To retrieve the size of the object (that is, the number of members it has),
* json_object_get_size(). * use json_object_get_size().
*/ */
struct _JsonObject
{
GHashTable *members;
volatile gint ref_count;
};
GType GType
json_object_get_type (void) json_object_get_type (void)
{ {
static GType object_type = 0; static GType object_type = 0;
if (G_UNLIKELY (!object_type)) if (G_UNLIKELY (!object_type))
object_type = g_boxed_type_register_static ("JsonObject", object_type = g_boxed_type_register_static (g_intern_static_string ("JsonObject"),
(GBoxedCopyFunc) json_object_ref, (GBoxedCopyFunc) json_object_ref,
(GBoxedFreeFunc) json_object_unref); (GBoxedFreeFunc) json_object_unref);
@ -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: * json_object_add_member:
* @object: a #JsonObject * @object: a #JsonObject
@ -141,6 +153,11 @@ json_object_unref (JsonObject *object)
* *
* Adds a member named @member_name and containing @node into a #JsonObject. * Adds a member named @member_name and containing @node into a #JsonObject.
* The object will take ownership of the #JsonNode. * 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 void
json_object_add_member (JsonObject *object, json_object_add_member (JsonObject *object,
@ -155,17 +172,239 @@ json_object_add_member (JsonObject *object,
if (json_object_has_member (object, member_name)) 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, member_name,
json_node_type_name (node)); json_node_type_name (node));
return; return;
} }
name = g_strdelimit (g_strdup (member_name), G_STR_DELIMITERS, '_'); object_set_member_internal (object, member_name, node);
g_hash_table_replace (object->members, name, node);
} }
/* FIXME: yuck. we really need to depend on GLib 2.14 */ /**
* 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 */
#if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 14 #if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 14
static void static void
get_keys (gpointer key, get_keys (gpointer key,
@ -177,6 +416,16 @@ get_keys (gpointer key,
*keys = g_list_prepend (*keys, 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 * static GList *
g_hash_table_get_keys (GHashTable *hash_table) g_hash_table_get_keys (GHashTable *hash_table)
{ {
@ -188,6 +437,18 @@ g_hash_table_get_keys (GHashTable *hash_table)
return retval; 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 */ #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 * Retrieves all the names of the members of a #JsonObject. You can
* obtain the value for each member using json_object_get_member(). * obtain the value for each member using json_object_get_member().
* *
* Return value: (transfer container) (element-type utf8): a #GList of * Return value: a #GList of member names. The content of the list
* member names. The content of the list is owned by the #JsonObject * is owned by the #JsonObject and should never be modified or
* and should never be modified or freed. When you have finished using * freed. When you have finished using the returned list, use
* the returned list, use g_list_free() to free the resources it has * g_list_free() to free the resources it has allocated.
* allocated.
*/ */
GList * GList *
json_object_get_members (JsonObject *object) json_object_get_members (JsonObject *object)
@ -211,6 +471,70 @@ json_object_get_members (JsonObject *object)
return g_hash_table_get_keys (object->members); return g_hash_table_get_keys (object->members);
} }
/**
* 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 a copy of the #JsonNode containing the value of @member_name
* inside a #JsonObject
*
* 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_dup_member (JsonObject *object,
const gchar *member_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: * json_object_get_member:
* @object: a #JsonObject * @object: a #JsonObject
@ -219,24 +543,226 @@ json_object_get_members (JsonObject *object)
* Retrieves the #JsonNode containing the value of @member_name inside * Retrieves the #JsonNode containing the value of @member_name inside
* a #JsonObject. * a #JsonObject.
* *
* Return value: (transfer none): a pointer to the node for the requested object * Return value: a pointer to the node for the requested object
* member, or %NULL * member, or %NULL
*/ */
JsonNode * JsonNode *
json_object_get_member (JsonObject *object, json_object_get_member (JsonObject *object,
const gchar *member_name) const gchar *member_name)
{ {
gchar *name; g_return_val_if_fail (object != NULL, NULL);
JsonNode *retval; 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 (object != NULL, NULL);
g_return_val_if_fail (member_name != NULL, NULL); g_return_val_if_fail (member_name != NULL, NULL);
name = g_strdelimit (g_strdup (member_name), G_STR_DELIMITERS, '_'); node = object_get_member_internal (object, member_name);
retval = g_hash_table_lookup (object->members, name); g_return_val_if_fail (node != NULL, NULL);
g_free (name); g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, NULL);
return retval; 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);
} }
/** /**
@ -301,3 +827,58 @@ json_object_remove_member (JsonObject *object,
g_hash_table_remove (object->members, name); g_hash_table_remove (object->members, name);
g_free (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);
}

View File

@ -31,6 +31,8 @@
#include <string.h> #include <string.h>
#include "json-types-private.h"
#include "json-marshal.h" #include "json-marshal.h"
#include "json-parser.h" #include "json-parser.h"
@ -587,7 +589,7 @@ json_parse_object (JsonParser *parser,
return token; return token;
} }
json_object_add_member (object, name, node); json_object_set_member (object, name, node);
node->parent = priv->current_node; node->parent = priv->current_node;
g_signal_emit (parser, parser_signals[OBJECT_MEMBER], 0, g_signal_emit (parser, parser_signals[OBJECT_MEMBER], 0,
@ -623,7 +625,7 @@ json_parse_object (JsonParser *parser,
return token; return token;
} }
json_object_add_member (object, name, node); json_object_set_member (object, name, node);
node->parent = priv->current_node; node->parent = priv->current_node;
g_signal_emit (parser, parser_signals[OBJECT_MEMBER], 0, g_signal_emit (parser, parser_signals[OBJECT_MEMBER], 0,
@ -693,7 +695,7 @@ json_parse_object (JsonParser *parser,
if (node) if (node)
{ {
json_object_add_member (object, name, node); json_object_set_member (object, name, node);
node->parent = priv->current_node; node->parent = priv->current_node;
g_signal_emit (parser, parser_signals[OBJECT_MEMBER], 0, g_signal_emit (parser, parser_signals[OBJECT_MEMBER], 0,

View File

@ -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__ */

View File

@ -2,19 +2,23 @@
* *
* This file is part of JSON-GLib * This file is part of JSON-GLib
* Copyright (C) 2007 OpenedHand Ltd. * Copyright (C) 2007 OpenedHand Ltd.
* Copyright (C) 2009 Intel Corp.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * 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, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * 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: * Author:
* Emmanuele Bassi <ebassi@openedhand.com> * Emmanuele Bassi <ebassi@linux.intel.com>
*/ */
#ifndef __JSON_TYPES_H__ #ifndef __JSON_TYPES_H__
@ -30,14 +34,22 @@ G_BEGIN_DECLS
* *
* Evaluates to the #JsonNodeType contained by @node * Evaluates to the #JsonNodeType contained by @node
*/ */
#define JSON_NODE_TYPE(node) \ #define JSON_NODE_TYPE(node) (json_node_get_node_type ((node)))
(((JsonNode *) (node))->type)
#define JSON_NODE_VALUE_TYPE(node) \
(G_VALUE_TYPE ((((JsonNode *) (node))->data.value))
#define JSON_TYPE_NODE (json_node_get_type ())
#define JSON_TYPE_OBJECT (json_object_get_type ()) #define JSON_TYPE_OBJECT (json_object_get_type ())
#define JSON_TYPE_ARRAY (json_array_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: * JsonObject:
* *
@ -54,14 +66,12 @@ typedef struct _JsonObject JsonObject;
*/ */
typedef struct _JsonArray JsonArray; typedef struct _JsonArray JsonArray;
typedef struct _JsonNode JsonNode;
/** /**
* JsonNodeType: * JsonNodeType:
* @JSON_NODE_OBJECT: The node contains a #JsonObject * @JSON_NODE_OBJECT: The node contains a #JsonObject
* @JSON_NODE_ARRAY: The node contains a #JsonArray * @JSON_NODE_ARRAY: The node contains a #JsonArray
* @JSON_NODE_VALUE: The node contains a #GValue * @JSON_NODE_VALUE: The node contains a fundamental type
* @JSON_NODE_NULL: Special type, for nodes containing %NULL * @JSON_NODE_NULL: Special type, for nodes containing null
* *
* Indicates the content of a #JsonNode. * Indicates the content of a #JsonNode.
*/ */
@ -73,29 +83,52 @@ typedef enum {
} JsonNodeType; } 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 * The function to be passed to json_object_foreach_member(). You
* structure are private and should only be accessed via the provided * should not add or remove members to and from @object within
* functions and never directly. * this function. It is safe to change the value of @member_node.
*
* Since: 0.8
*/ */
struct _JsonNode typedef void (* JsonObjectForeach) (JsonObject *object,
{ const gchar *member_name,
/*< private >*/ JsonNode *member_node,
JsonNodeType type; gpointer user_data);
union { /**
JsonObject *object; * JsonArrayForeach:
JsonArray *array; * @array: the iterated #JsonArray
GValue value; * @index_: the index of the element
} data; * @element_node: a #JsonNode containing the value at @index_
* @user_data: data passed to the function
JsonNode *parent; *
}; * 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_new (JsonNodeType type);
JsonNode * json_node_copy (JsonNode *node); JsonNode * json_node_copy (JsonNode *node);
void json_node_free (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, void json_node_set_object (JsonNode *node,
JsonObject *object); JsonObject *object);
@ -126,24 +159,73 @@ gdouble json_node_get_double (JsonNode *node);
void json_node_set_boolean (JsonNode *node, void json_node_set_boolean (JsonNode *node,
gboolean value); gboolean value);
gboolean json_node_get_boolean (JsonNode *node); gboolean json_node_get_boolean (JsonNode *node);
JsonNode * json_node_get_parent (JsonNode *node); gboolean json_node_is_null (JsonNode *node);
G_CONST_RETURN gchar *json_node_type_name (JsonNode *node);
/*
* JsonObject
*/
GType json_object_get_type (void) G_GNUC_CONST; GType json_object_get_type (void) G_GNUC_CONST;
JsonObject * json_object_new (void); JsonObject * json_object_new (void);
JsonObject * json_object_ref (JsonObject *object); JsonObject * json_object_ref (JsonObject *object);
void json_object_unref (JsonObject *object); void json_object_unref (JsonObject *object);
#ifndef JSON_DISABLE_DEPRECATED
void json_object_add_member (JsonObject *object, 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, const gchar *member_name,
JsonNode *node); 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); GList * json_object_get_members (JsonObject *object);
JsonNode * json_object_get_member (JsonObject *object, JsonNode * json_object_get_member (JsonObject *object,
const gchar *member_name); 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, gboolean json_object_has_member (JsonObject *object,
const gchar *member_name); const gchar *member_name);
void json_object_remove_member (JsonObject *object, void json_object_remove_member (JsonObject *object,
const gchar *member_name); const gchar *member_name);
GList * json_object_get_values (JsonObject *object);
guint json_object_get_size (JsonObject *object); guint json_object_get_size (JsonObject *object);
void json_object_foreach_member (JsonObject *object,
JsonObjectForeach func,
gpointer data);
GType json_array_get_type (void) G_GNUC_CONST; GType json_array_get_type (void) G_GNUC_CONST;
JsonArray * json_array_new (void); JsonArray * json_array_new (void);
@ -152,12 +234,44 @@ JsonArray * json_array_ref (JsonArray *array);
void json_array_unref (JsonArray *array); void json_array_unref (JsonArray *array);
void json_array_add_element (JsonArray *array, void json_array_add_element (JsonArray *array,
JsonNode *node); 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); GList * json_array_get_elements (JsonArray *array);
JsonNode * json_array_get_element (JsonArray *array, JsonNode * json_array_get_element (JsonArray *array,
guint index_); 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, void json_array_remove_element (JsonArray *array,
guint index_); guint index_);
guint json_array_get_length (JsonArray *array); guint json_array_get_length (JsonArray *array);
void json_array_foreach_element (JsonArray *array,
JsonArrayForeach func,
gpointer data);
G_END_DECLS G_END_DECLS