From d743aeaa21b2c06ce9e673808e6f3ab2b05dd929 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 9 Jun 2009 12:42:19 +0100 Subject: [PATCH] [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. --- clutter/clutter-script.c | 2 +- clutter/json/json-array.c | 479 +++++++++++++++++++++- clutter/json/json-generator.c | 4 +- clutter/json/json-node.c | 163 +++++++- clutter/json/json-object.c | 649 ++++++++++++++++++++++++++++-- clutter/json/json-parser.c | 8 +- clutter/json/json-types-private.h | 61 +++ clutter/json/json-types.h | 226 ++++++++--- 8 files changed, 1459 insertions(+), 133 deletions(-) create mode 100644 clutter/json/json-types-private.h diff --git a/clutter/clutter-script.c b/clutter/clutter-script.c index 463a5a00b..b9227394d 100644 --- a/clutter/clutter-script.c +++ b/clutter/clutter-script.c @@ -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); } diff --git a/clutter/json/json-array.c b/clutter/json/json-array.c index 61c8a4c8f..08e044906 100644 --- a/clutter/json/json-array.c +++ b/clutter/json/json-array.c @@ -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 . + * * Author: - * Emmanuele Bassi + * Emmanuele Bassi */ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include "json-types.h" +#include "json-types-private.h" /** * SECTION:json-array @@ -40,20 +44,13 @@ * 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 #JsonNodes. * - * 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 * @@ -181,6 +178,35 @@ json_array_get_elements (JsonArray *array) 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: * @array: a #JsonArray @@ -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, @@ -201,6 +227,215 @@ json_array_get_element (JsonArray *array, 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: * @array: a #JsonArray @@ -235,6 +470,183 @@ json_array_add_element (JsonArray *array, 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: * @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_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); + } +} diff --git a/clutter/json/json-generator.c b/clutter/json/json-generator.c index 78c251b02..d1c8717dc 100644 --- a/clutter/json/json-generator.c +++ b/clutter/json/json-generator.c @@ -32,8 +32,10 @@ #include #include -#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)) diff --git a/clutter/json/json-node.c b/clutter/json/json-node.c index f20f7adc4..1a0aeeed0 100644 --- a/clutter/json/json-node.c +++ b/clutter/json/json-node.c @@ -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 . + * * Author: - * Emmanuele Bassi + * Emmanuele Bassi */ #ifdef HAVE_CONFIG_H @@ -23,7 +27,7 @@ #include -#include "json-types.h" +#include "json-types-private.h" /** * SECTION:json-node @@ -36,14 +40,62 @@ * 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 + * + * A null node is not the same as a %NULL #JsonNode + * + * 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; +} diff --git a/clutter/json/json-object.c b/clutter/json/json-object.c index 92bf6d3fe..795227467 100644 --- a/clutter/json/json-object.c +++ b/clutter/json/json-object.c @@ -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 . + * * Author: - * Emmanuele Bassi + * Emmanuele Bassi */ #ifdef HAVE_CONFIG_H @@ -23,7 +27,7 @@ #include -#include "json-types.h" +#include "json-types-private.h" /** * SECTION:json-object @@ -31,34 +35,31 @@ * * #JsonArray is the representation of the object type inside JSON. It contains * #JsonNodes, 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); } -/* 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 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) @@ -211,6 +471,70 @@ json_object_get_members (JsonObject *object) 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 #JsonNodes. 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: * @object: a #JsonObject @@ -219,24 +543,226 @@ json_object_get_members (JsonObject *object) * Retrieves the #JsonNode containing the value of @member_name inside * 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 */ JsonNode * -json_object_get_member (JsonObject *object, +json_object_get_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); + + 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); - name = g_strdelimit (g_strdup (member_name), G_STR_DELIMITERS, '_'); - retval = g_hash_table_lookup (object->members, name); - g_free (name); + 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 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_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); +} diff --git a/clutter/json/json-parser.c b/clutter/json/json-parser.c index 7855dd3fd..526ec45dc 100644 --- a/clutter/json/json-parser.c +++ b/clutter/json/json-parser.c @@ -31,6 +31,8 @@ #include +#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 index 000000000..728b36713 --- /dev/null +++ b/clutter/json/json-types-private.h @@ -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 . + * + * Author: + * Emmanuele Bassi + */ + +#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__ */ diff --git a/clutter/json/json-types.h b/clutter/json/json-types.h index 82294011d..153848835 100644 --- a/clutter/json/json-types.h +++ b/clutter/json/json-types.h @@ -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 . + * * Author: - * Emmanuele Bassi + * Emmanuele Bassi */ #ifndef __JSON_TYPES_H__ @@ -30,14 +34,22 @@ 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: * @@ -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; +typedef void (* JsonObjectForeach) (JsonObject *object, + const gchar *member_name, + JsonNode *member_node, + gpointer user_data); - union { - JsonObject *object; - JsonArray *array; - GValue value; - } 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); -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); +/* + * 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); -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); +#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_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