|
Packit |
4c4d6b |
/* json-node.c - JSON object model node
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* This file is part of JSON-GLib
|
|
Packit |
4c4d6b |
* Copyright (C) 2007 OpenedHand Ltd.
|
|
Packit |
4c4d6b |
* Copyright (C) 2009 Intel Corp.
|
|
Packit |
4c4d6b |
* Copyright (C) 2015 Collabora Ltd.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* This library is free software; you can redistribute it and/or
|
|
Packit |
4c4d6b |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
4c4d6b |
* License as published by the Free Software Foundation; either
|
|
Packit |
4c4d6b |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
4c4d6b |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
4c4d6b |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
4c4d6b |
* Lesser General Public License for more details.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
4c4d6b |
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Author:
|
|
Packit |
4c4d6b |
* Emmanuele Bassi <ebassi@linux.intel.com>
|
|
Packit |
4c4d6b |
* Philip Withnall <philip.withnall@collabora.co.uk>
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
#include "config.h"
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
#include <glib.h>
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
#include "json-types.h"
|
|
Packit |
4c4d6b |
#include "json-types-private.h"
|
|
Packit |
4c4d6b |
#include "json-debug.h"
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* SECTION:json-node
|
|
Packit |
4c4d6b |
* @short_description: Node in a JSON object model
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* A #JsonNode is a generic container of elements inside a JSON stream.
|
|
Packit |
4c4d6b |
* It can contain fundamental types (integers, booleans, floating point
|
|
Packit |
4c4d6b |
* numbers, strings) and complex types (arrays and objects).
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* When parsing a JSON data stream you extract the root node and walk
|
|
Packit |
4c4d6b |
* the node tree by retrieving the type of data contained inside the
|
|
Packit |
4c4d6b |
* node with the %JSON_NODE_TYPE macro. If the node contains a fundamental
|
|
Packit |
4c4d6b |
* type you can retrieve a copy of the #GValue holding it with the
|
|
Packit |
4c4d6b |
* json_node_get_value() function, and then use the #GValue API to extract
|
|
Packit |
4c4d6b |
* the data; if the node contains a complex type you can retrieve the
|
|
Packit |
4c4d6b |
* #JsonObject or the #JsonArray using json_node_get_object() or
|
|
Packit |
4c4d6b |
* json_node_get_array() respectively, and then retrieve the nodes
|
|
Packit |
4c4d6b |
* they contain.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* A #JsonNode may be marked as immutable using json_node_seal(). This marks the
|
|
Packit |
4c4d6b |
* node and all its descendents as read-only, and means that subsequent calls to
|
|
Packit |
4c4d6b |
* setter functions (such as json_node_set_array()) on them will abort as a
|
|
Packit |
4c4d6b |
* programmer error. By marking a node tree as immutable, it may be referenced
|
|
Packit |
4c4d6b |
* in multiple places and its hash value cached for fast lookups, without the
|
|
Packit |
4c4d6b |
* possibility of a value deep within the tree changing and affecting hash
|
|
Packit |
4c4d6b |
* values. Immutable #JsonNodes may be passed to functions which retain a
|
|
Packit |
4c4d6b |
* reference to them without needing to take a copy.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* #JsonNode supports two types of memory management: alloc/free semantics, and
|
|
Packit |
4c4d6b |
* ref/unref semantics. The two may be mixed to a limited extent: nodes may be
|
|
Packit |
4c4d6b |
* allocated (which gives them a reference count of 1), referenced zero or more
|
|
Packit |
4c4d6b |
* times, unreferenced exactly that number of times (using json_node_unref()),
|
|
Packit |
4c4d6b |
* then either unreferenced exactly once more or freed (using json_node_free())
|
|
Packit |
4c4d6b |
* to destroy them. json_node_free() must not be used when a node might have a
|
|
Packit |
4c4d6b |
* reference count not equal to 1. To this end, json-glib uses json_node_copy()
|
|
Packit |
4c4d6b |
* and json_node_unref() internally.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
G_DEFINE_BOXED_TYPE (JsonNode, json_node, json_node_copy, json_node_unref);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_get_value_type:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Returns the #GType of the payload of the node.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: a #GType for the payload.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 0.4
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
GType
|
|
Packit |
4c4d6b |
json_node_get_value_type (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (node != NULL, G_TYPE_INVALID);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
switch (node->type)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
case JSON_NODE_OBJECT:
|
|
Packit |
4c4d6b |
return JSON_TYPE_OBJECT;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case JSON_NODE_ARRAY:
|
|
Packit |
4c4d6b |
return JSON_TYPE_ARRAY;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case JSON_NODE_NULL:
|
|
Packit |
4c4d6b |
return G_TYPE_INVALID;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case JSON_NODE_VALUE:
|
|
Packit |
4c4d6b |
if (node->data.value)
|
|
Packit |
4c4d6b |
return JSON_VALUE_TYPE (node->data.value);
|
|
Packit |
4c4d6b |
else
|
|
Packit |
4c4d6b |
return G_TYPE_INVALID;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
default:
|
|
Packit |
4c4d6b |
g_assert_not_reached ();
|
|
Packit |
4c4d6b |
return G_TYPE_INVALID;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_alloc: (constructor)
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Allocates a new #JsonNode. Use json_node_init() and its variants
|
|
Packit |
4c4d6b |
* to initialize the returned value.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer full): the newly allocated #JsonNode. Use
|
|
Packit |
4c4d6b |
* json_node_free() to free the resources allocated by this function
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 0.16
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonNode *
|
|
Packit |
4c4d6b |
json_node_alloc (void)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
JsonNode *node = NULL;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
node = g_slice_new0 (JsonNode);
|
|
Packit |
4c4d6b |
node->ref_count = 1;
|
|
Packit |
4c4d6b |
node->allocated = TRUE;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return node;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
static void
|
|
Packit |
4c4d6b |
json_node_unset (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
/* Note: Don't use JSON_NODE_IS_VALID here because this may legitimately be
|
|
Packit |
4c4d6b |
* called with (node->ref_count == 0) from json_node_unref(). */
|
|
Packit |
4c4d6b |
g_assert (node != NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
switch (node->type)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
case JSON_NODE_OBJECT:
|
|
Packit |
4c4d6b |
if (node->data.object)
|
|
Packit |
4c4d6b |
json_object_unref (node->data.object);
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case JSON_NODE_ARRAY:
|
|
Packit |
4c4d6b |
if (node->data.array)
|
|
Packit |
4c4d6b |
json_array_unref (node->data.array);
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case JSON_NODE_VALUE:
|
|
Packit |
4c4d6b |
if (node->data.value)
|
|
Packit |
4c4d6b |
json_value_unref (node->data.value);
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case JSON_NODE_NULL:
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_init:
|
|
Packit |
4c4d6b |
* @node: the #JsonNode to initialize
|
|
Packit |
4c4d6b |
* @type: the type of JSON node to initialize @node to
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Initializes a @node to a specific @type.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* If the node has already been initialized once, it will be reset to
|
|
Packit |
4c4d6b |
* the given type, and any data contained will be cleared.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer none): the initialized #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 0.16
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonNode *
|
|
Packit |
4c4d6b |
json_node_init (JsonNode *node,
|
|
Packit |
4c4d6b |
JsonNodeType type)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (type >= JSON_NODE_OBJECT &&
|
|
Packit |
4c4d6b |
type <= JSON_NODE_NULL, NULL);
|
|
Packit |
4c4d6b |
g_return_val_if_fail (node->ref_count == 1, NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
json_node_unset (node);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
node->type = type;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return node;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_init_object:
|
|
Packit |
4c4d6b |
* @node: the #JsonNode to initialize
|
|
Packit |
4c4d6b |
* @object: (allow-none): the #JsonObject to initialize @node with, or %NULL
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Initializes @node to %JSON_NODE_OBJECT and sets @object into it.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* This function will take a reference on @object.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* If the node has already been initialized once, it will be reset to
|
|
Packit |
4c4d6b |
* the given type, and any data contained will be cleared.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer none): the initialized #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 0.16
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonNode *
|
|
Packit |
4c4d6b |
json_node_init_object (JsonNode *node,
|
|
Packit |
4c4d6b |
JsonObject *object)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (node != NULL, NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
json_node_init (node, JSON_NODE_OBJECT);
|
|
Packit |
4c4d6b |
json_node_set_object (node, object);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return node;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_init_array:
|
|
Packit |
4c4d6b |
* @node: the #JsonNode to initialize
|
|
Packit |
4c4d6b |
* @array: (allow-none): the #JsonArray to initialize @node with, or %NULL
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Initializes @node to %JSON_NODE_ARRAY and sets @array into it.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* This function will take a reference on @array.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* If the node has already been initialized once, it will be reset to
|
|
Packit |
4c4d6b |
* the given type, and any data contained will be cleared.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer none): the initialized #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 0.16
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonNode *
|
|
Packit |
4c4d6b |
json_node_init_array (JsonNode *node,
|
|
Packit |
4c4d6b |
JsonArray *array)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (node != NULL, NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
json_node_init (node, JSON_NODE_ARRAY);
|
|
Packit |
4c4d6b |
json_node_set_array (node, array);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return node;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_init_int:
|
|
Packit |
4c4d6b |
* @node: the #JsonNode to initialize
|
|
Packit |
4c4d6b |
* @value: an integer
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Initializes @node to %JSON_NODE_VALUE and sets @value into it.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* If the node has already been initialized once, it will be reset to
|
|
Packit |
4c4d6b |
* the given type, and any data contained will be cleared.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer none): the initialized #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 0.16
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonNode *
|
|
Packit |
4c4d6b |
json_node_init_int (JsonNode *node,
|
|
Packit |
4c4d6b |
gint64 value)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (node != NULL, NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
json_node_init (node, JSON_NODE_VALUE);
|
|
Packit |
4c4d6b |
json_node_set_int (node, value);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return node;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_init_double:
|
|
Packit |
4c4d6b |
* @node: the #JsonNode to initialize
|
|
Packit |
4c4d6b |
* @value: a floating point value
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Initializes @node to %JSON_NODE_VALUE and sets @value into it.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* If the node has already been initialized once, it will be reset to
|
|
Packit |
4c4d6b |
* the given type, and any data contained will be cleared.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer none): the initialized #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 0.16
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonNode *
|
|
Packit |
4c4d6b |
json_node_init_double (JsonNode *node,
|
|
Packit |
4c4d6b |
gdouble value)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (node != NULL, NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
json_node_init (node, JSON_NODE_VALUE);
|
|
Packit |
4c4d6b |
json_node_set_double (node, value);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return node;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_init_boolean:
|
|
Packit |
4c4d6b |
* @node: the #JsonNode to initialize
|
|
Packit |
4c4d6b |
* @value: a boolean value
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Initializes @node to %JSON_NODE_VALUE and sets @value into it.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* If the node has already been initialized once, it will be reset to
|
|
Packit |
4c4d6b |
* the given type, and any data contained will be cleared.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer none): the initialized #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 0.16
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonNode *
|
|
Packit |
4c4d6b |
json_node_init_boolean (JsonNode *node,
|
|
Packit |
4c4d6b |
gboolean value)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (node != NULL, NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
json_node_init (node, JSON_NODE_VALUE);
|
|
Packit |
4c4d6b |
json_node_set_boolean (node, value);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return node;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_init_string:
|
|
Packit |
4c4d6b |
* @node: the #JsonNode to initialize
|
|
Packit |
4c4d6b |
* @value: (allow-none): a string value
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Initializes @node to %JSON_NODE_VALUE and sets @value into it.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* If the node has already been initialized once, it will be reset to
|
|
Packit |
4c4d6b |
* the given type, and any data contained will be cleared.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer none): the initialized #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 0.16
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonNode *
|
|
Packit |
4c4d6b |
json_node_init_string (JsonNode *node,
|
|
Packit |
4c4d6b |
const char *value)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (node != NULL, NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
json_node_init (node, JSON_NODE_VALUE);
|
|
Packit |
4c4d6b |
json_node_set_string (node, value);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return node;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_init_null:
|
|
Packit |
4c4d6b |
* @node: the #JsonNode to initialize
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Initializes @node to %JSON_NODE_NULL.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* If the node has already been initialized once, it will be reset to
|
|
Packit |
4c4d6b |
* the given type, and any data contained will be cleared.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer none): the initialized #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 0.16
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonNode *
|
|
Packit |
4c4d6b |
json_node_init_null (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (node != NULL, NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return json_node_init (node, JSON_NODE_NULL);
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_new: (constructor)
|
|
Packit |
4c4d6b |
* @type: a #JsonNodeType
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Creates a new #JsonNode of @type.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* This is a convenience function for json_node_alloc() and json_node_init(),
|
|
Packit |
4c4d6b |
* and it's the equivalent of:
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* |[
|
|
Packit |
4c4d6b |
json_node_init (json_node_alloc (), type);
|
|
Packit |
4c4d6b |
* ]|
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer full): the newly created #JsonNode
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonNode *
|
|
Packit |
4c4d6b |
json_node_new (JsonNodeType type)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (type >= JSON_NODE_OBJECT &&
|
|
Packit |
4c4d6b |
type <= JSON_NODE_NULL, NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return json_node_init (json_node_alloc (), type);
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_copy:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Copies @node. If the node contains complex data types, their reference
|
|
Packit |
4c4d6b |
* counts are increased, regardless of whether the node is mutable or
|
|
Packit |
4c4d6b |
* immutable.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* The copy will be immutable if, and only if, @node is immutable. However,
|
|
Packit |
4c4d6b |
* there should be no need to copy an immutable node.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer full): the copied #JsonNode
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonNode *
|
|
Packit |
4c4d6b |
json_node_copy (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
JsonNode *copy;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
copy = json_node_alloc ();
|
|
Packit |
4c4d6b |
copy->type = node->type;
|
|
Packit |
4c4d6b |
copy->immutable = node->immutable;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
#ifdef JSON_ENABLE_DEBUG
|
|
Packit |
4c4d6b |
if (node->immutable)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
JSON_NOTE (NODE, "Copying immutable JsonNode %p of type %s",
|
|
Packit |
4c4d6b |
node,
|
|
Packit |
4c4d6b |
json_node_type_name (node));
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
#endif
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
switch (copy->type)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
case JSON_NODE_OBJECT:
|
|
Packit |
4c4d6b |
copy->data.object = json_node_dup_object (node);
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case JSON_NODE_ARRAY:
|
|
Packit |
4c4d6b |
copy->data.array = json_node_dup_array (node);
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case JSON_NODE_VALUE:
|
|
Packit |
4c4d6b |
if (node->data.value)
|
|
Packit |
4c4d6b |
copy->data.value = json_value_ref (node->data.value);
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case JSON_NODE_NULL:
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
default:
|
|
Packit |
4c4d6b |
g_assert_not_reached ();
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return copy;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_ref:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Increment the reference count of @node.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 1.2
|
|
Packit |
4c4d6b |
* Returns: (transfer full): a pointer to @node
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonNode *
|
|
Packit |
4c4d6b |
json_node_ref (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
g_atomic_int_inc (&node->ref_count);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return node;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_unref:
|
|
Packit |
4c4d6b |
* @node: (transfer full): a #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Decrement the reference count of @node. If it reaches zero, the node is
|
|
Packit |
4c4d6b |
* freed.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 1.2
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
void
|
|
Packit |
4c4d6b |
json_node_unref (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_IS_VALID (node));
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (g_atomic_int_dec_and_test (&node->ref_count))
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
json_node_unset (node);
|
|
Packit |
4c4d6b |
if (node->allocated)
|
|
Packit |
4c4d6b |
g_slice_free (JsonNode, node);
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_set_object:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode initialized to %JSON_NODE_OBJECT
|
|
Packit |
4c4d6b |
* @object: (nullable): a #JsonObject
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Sets @objects inside @node. The reference count of @object is increased.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* If @object is %NULL, the node’s existing object is cleared.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* It is an error to call this on an immutable node, or on a node which is not
|
|
Packit |
4c4d6b |
* an object node.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
void
|
|
Packit |
4c4d6b |
json_node_set_object (JsonNode *node,
|
|
Packit |
4c4d6b |
JsonObject *object)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_IS_VALID (node));
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT);
|
|
Packit |
4c4d6b |
g_return_if_fail (!node->immutable);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (node->data.object != NULL)
|
|
Packit |
4c4d6b |
json_object_unref (node->data.object);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (object)
|
|
Packit |
4c4d6b |
node->data.object = json_object_ref (object);
|
|
Packit |
4c4d6b |
else
|
|
Packit |
4c4d6b |
node->data.object = NULL;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_take_object:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode initialized to %JSON_NODE_OBJECT
|
|
Packit |
4c4d6b |
* @object: (transfer full): a #JsonObject
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Sets @object inside @node. The reference count of @object is not increased.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* It is an error to call this on an immutable node, or on a node which is not
|
|
Packit |
4c4d6b |
* an object node.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
void
|
|
Packit |
4c4d6b |
json_node_take_object (JsonNode *node,
|
|
Packit |
4c4d6b |
JsonObject *object)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_IS_VALID (node));
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT);
|
|
Packit |
4c4d6b |
g_return_if_fail (!node->immutable);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (node->data.object)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
json_object_unref (node->data.object);
|
|
Packit |
4c4d6b |
node->data.object = NULL;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (object)
|
|
Packit |
4c4d6b |
node->data.object = object;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_get_object:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Retrieves the #JsonObject stored inside a #JsonNode. It is a programmer error
|
|
Packit |
4c4d6b |
* to call this on a node which doesn’t hold an object value. Use
|
|
Packit |
4c4d6b |
* %JSON_NODE_HOLDS_OBJECT first.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer none) (nullable): the #JsonObject
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonObject *
|
|
Packit |
4c4d6b |
json_node_get_object (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT, NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return node->data.object;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_dup_object:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Retrieves the #JsonObject inside @node. The reference count of
|
|
Packit |
4c4d6b |
* the returned object is increased. It is a programmer error
|
|
Packit |
4c4d6b |
* to call this on a node which doesn’t hold an object value. Use
|
|
Packit |
4c4d6b |
* %JSON_NODE_HOLDS_OBJECT first.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer full) (nullable): the #JsonObject
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonObject *
|
|
Packit |
4c4d6b |
json_node_dup_object (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT, NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (node->data.object)
|
|
Packit |
4c4d6b |
return json_object_ref (node->data.object);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return NULL;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_set_array:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode initialized to %JSON_NODE_ARRAY
|
|
Packit |
4c4d6b |
* @array: a #JsonArray
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Sets @array inside @node and increases the #JsonArray reference count.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* It is an error to call this on an immutable node, or on a node which is not
|
|
Packit |
4c4d6b |
* an array node.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
void
|
|
Packit |
4c4d6b |
json_node_set_array (JsonNode *node,
|
|
Packit |
4c4d6b |
JsonArray *array)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_IS_VALID (node));
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY);
|
|
Packit |
4c4d6b |
g_return_if_fail (!node->immutable);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (node->data.array)
|
|
Packit |
4c4d6b |
json_array_unref (node->data.array);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (array)
|
|
Packit |
4c4d6b |
node->data.array = json_array_ref (array);
|
|
Packit |
4c4d6b |
else
|
|
Packit |
4c4d6b |
node->data.array = NULL;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_take_array:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode initialized to %JSON_NODE_ARRAY
|
|
Packit |
4c4d6b |
* @array: (transfer full): a #JsonArray
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Sets @array into @node without increasing the #JsonArray reference count.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* It is an error to call this on an immutable node, or a node which is not
|
|
Packit |
4c4d6b |
* an array node.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
void
|
|
Packit |
4c4d6b |
json_node_take_array (JsonNode *node,
|
|
Packit |
4c4d6b |
JsonArray *array)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_IS_VALID (node));
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY);
|
|
Packit |
4c4d6b |
g_return_if_fail (!node->immutable);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (node->data.array)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
json_array_unref (node->data.array);
|
|
Packit |
4c4d6b |
node->data.array = NULL;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (array)
|
|
Packit |
4c4d6b |
node->data.array = array;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_get_array:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Retrieves the #JsonArray stored inside a #JsonNode. It is a programmer error
|
|
Packit |
4c4d6b |
* to call this on a node which doesn’t hold an array value. Use
|
|
Packit |
4c4d6b |
* %JSON_NODE_HOLDS_ARRAY first.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer none) (nullable): the #JsonArray
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonArray *
|
|
Packit |
4c4d6b |
json_node_get_array (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY, NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return node->data.array;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_dup_array:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Retrieves the #JsonArray stored inside a #JsonNode and returns it
|
|
Packit |
4c4d6b |
* with its reference count increased by one. It is a programmer error
|
|
Packit |
4c4d6b |
* to call this on a node which doesn’t hold an array value. Use
|
|
Packit |
4c4d6b |
* %JSON_NODE_HOLDS_ARRAY first.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer full) (nullable): the #JsonArray with its reference
|
|
Packit |
4c4d6b |
* count increased.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonArray *
|
|
Packit |
4c4d6b |
json_node_dup_array (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY, NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (node->data.array)
|
|
Packit |
4c4d6b |
return json_array_ref (node->data.array);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return NULL;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_get_value:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode
|
|
Packit |
4c4d6b |
* @value: (out caller-allocates): return location for an uninitialized value
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Retrieves a value from a #JsonNode and copies into @value. When done
|
|
Packit |
4c4d6b |
* using it, call g_value_unset() on the #GValue. It is a programmer error
|
|
Packit |
4c4d6b |
* to call this on a node which doesn’t hold a scalar value. Use
|
|
Packit |
4c4d6b |
* %JSON_NODE_HOLDS_VALUE first.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
void
|
|
Packit |
4c4d6b |
json_node_get_value (JsonNode *node,
|
|
Packit |
4c4d6b |
GValue *value)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_IS_VALID (node));
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (node->data.value)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_value_init (value, JSON_VALUE_TYPE (node->data.value));
|
|
Packit |
4c4d6b |
switch (JSON_VALUE_TYPE (node->data.value))
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
case G_TYPE_INT64:
|
|
Packit |
4c4d6b |
g_value_set_int64 (value, json_value_get_int (node->data.value));
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case G_TYPE_DOUBLE:
|
|
Packit |
4c4d6b |
g_value_set_double (value, json_value_get_double (node->data.value));
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case G_TYPE_BOOLEAN:
|
|
Packit |
4c4d6b |
g_value_set_boolean (value, json_value_get_boolean (node->data.value));
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case G_TYPE_STRING:
|
|
Packit |
4c4d6b |
g_value_set_string (value, json_value_get_string (node->data.value));
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
default:
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_set_value:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode initialized to %JSON_NODE_VALUE
|
|
Packit |
4c4d6b |
* @value: the #GValue to set
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Sets @value inside @node. The passed #GValue is copied into the #JsonNode.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* It is an error to call this on an immutable node, or on a node which is not
|
|
Packit |
4c4d6b |
* a value node.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
void
|
|
Packit |
4c4d6b |
json_node_set_value (JsonNode *node,
|
|
Packit |
4c4d6b |
const GValue *value)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_IS_VALID (node));
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
|
|
Packit |
4c4d6b |
g_return_if_fail (G_VALUE_TYPE (value) != G_TYPE_INVALID);
|
|
Packit |
4c4d6b |
g_return_if_fail (!node->immutable);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (node->data.value == NULL)
|
|
Packit |
4c4d6b |
node->data.value = json_value_alloc ();
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
switch (G_VALUE_TYPE (value))
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
/* auto-promote machine integers to 64 bit integers */
|
|
Packit |
4c4d6b |
case G_TYPE_INT64:
|
|
Packit |
4c4d6b |
case G_TYPE_INT:
|
|
Packit |
4c4d6b |
json_value_init (node->data.value, JSON_VALUE_INT);
|
|
Packit |
4c4d6b |
if (G_VALUE_TYPE (value) == G_TYPE_INT64)
|
|
Packit |
4c4d6b |
json_value_set_int (node->data.value, g_value_get_int64 (value));
|
|
Packit |
4c4d6b |
else
|
|
Packit |
4c4d6b |
json_value_set_int (node->data.value, g_value_get_int (value));
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case G_TYPE_BOOLEAN:
|
|
Packit |
4c4d6b |
json_value_init (node->data.value, JSON_VALUE_BOOLEAN);
|
|
Packit |
4c4d6b |
json_value_set_boolean (node->data.value, g_value_get_boolean (value));
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/* auto-promote single-precision floats to double precision floats */
|
|
Packit |
4c4d6b |
case G_TYPE_DOUBLE:
|
|
Packit |
4c4d6b |
case G_TYPE_FLOAT:
|
|
Packit |
4c4d6b |
json_value_init (node->data.value, JSON_VALUE_DOUBLE);
|
|
Packit |
4c4d6b |
if (G_VALUE_TYPE (value) == G_TYPE_DOUBLE)
|
|
Packit |
4c4d6b |
json_value_set_double (node->data.value, g_value_get_double (value));
|
|
Packit |
4c4d6b |
else
|
|
Packit |
4c4d6b |
json_value_set_double (node->data.value, g_value_get_float (value));
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case G_TYPE_STRING:
|
|
Packit |
4c4d6b |
json_value_init (node->data.value, JSON_VALUE_STRING);
|
|
Packit |
4c4d6b |
json_value_set_string (node->data.value, g_value_get_string (value));
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
default:
|
|
Packit |
4c4d6b |
g_message ("Invalid value of type '%s'",
|
|
Packit |
4c4d6b |
g_type_name (G_VALUE_TYPE (value)));
|
|
Packit |
4c4d6b |
return;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_free:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Frees the resources allocated by @node.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
void
|
|
Packit |
4c4d6b |
json_node_free (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_if_fail (node == NULL || JSON_NODE_IS_VALID (node));
|
|
Packit |
4c4d6b |
g_return_if_fail (node == NULL || node->allocated);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (G_LIKELY (node))
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
if (node->ref_count > 1)
|
|
Packit |
4c4d6b |
g_warning ("Freeing a JsonNode %p owned by other code.", node);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
json_node_unset (node);
|
|
Packit |
4c4d6b |
g_slice_free (JsonNode, node);
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_seal:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Seals the #JsonNode, making it immutable to further changes. In order to be
|
|
Packit |
4c4d6b |
* sealed, the @node must have a type and value set. The value will be
|
|
Packit |
4c4d6b |
* recursively sealed — if the node holds an object, that #JsonObject will be
|
|
Packit |
4c4d6b |
* sealed, etc.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* If the @node is already immutable, this is a no-op.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 1.2
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
void
|
|
Packit |
4c4d6b |
json_node_seal (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_IS_VALID (node));
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (node->immutable)
|
|
Packit |
4c4d6b |
return;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
switch (node->type)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
case JSON_NODE_OBJECT:
|
|
Packit |
4c4d6b |
g_return_if_fail (node->data.object != NULL);
|
|
Packit |
4c4d6b |
json_object_seal (node->data.object);
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
case JSON_NODE_ARRAY:
|
|
Packit |
4c4d6b |
g_return_if_fail (node->data.array != NULL);
|
|
Packit |
4c4d6b |
json_array_seal (node->data.array);
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
case JSON_NODE_NULL:
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
case JSON_NODE_VALUE:
|
|
Packit |
4c4d6b |
g_return_if_fail (node->data.value != NULL);
|
|
Packit |
4c4d6b |
json_value_seal (node->data.value);
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
default:
|
|
Packit |
4c4d6b |
g_assert_not_reached ();
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
node->immutable = TRUE;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_is_immutable:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Check whether the given @node has been marked as immutable by calling
|
|
Packit |
4c4d6b |
* json_node_seal() on it.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 1.2
|
|
Packit |
4c4d6b |
* Returns: %TRUE if the @node is immutable
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
gboolean
|
|
Packit |
4c4d6b |
json_node_is_immutable (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_IS_VALID (node), FALSE);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return node->immutable;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_type_name:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Retrieves the user readable name of the data type contained by @node.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: a string containing the name of the type. The returned string
|
|
Packit |
4c4d6b |
* is owned by the node and should never be modified or freed
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
const gchar *
|
|
Packit |
4c4d6b |
json_node_type_name (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (node != NULL, "(null)");
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
switch (node->type)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
case JSON_NODE_OBJECT:
|
|
Packit |
4c4d6b |
case JSON_NODE_ARRAY:
|
|
Packit |
4c4d6b |
case JSON_NODE_NULL:
|
|
Packit |
4c4d6b |
return json_node_type_get_name (node->type);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case JSON_NODE_VALUE:
|
|
Packit |
4c4d6b |
if (node->data.value)
|
|
Packit |
4c4d6b |
return json_value_type_get_name (node->data.value->type);
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return "unknown";
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
const gchar *
|
|
Packit |
4c4d6b |
json_node_type_get_name (JsonNodeType node_type)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
switch (node_type)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
case JSON_NODE_OBJECT:
|
|
Packit |
4c4d6b |
return "JsonObject";
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case JSON_NODE_ARRAY:
|
|
Packit |
4c4d6b |
return "JsonArray";
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case JSON_NODE_NULL:
|
|
Packit |
4c4d6b |
return "NULL";
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
case JSON_NODE_VALUE:
|
|
Packit |
4c4d6b |
return "Value";
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
default:
|
|
Packit |
4c4d6b |
g_assert_not_reached ();
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return "unknown";
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_set_parent:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode
|
|
Packit |
4c4d6b |
* @parent: (transfer none): the parent #JsonNode of @node
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Sets the parent #JsonNode of @node.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* It is an error to call this with an immutable @parent. @node may be
|
|
Packit |
4c4d6b |
* immutable.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 0.8
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
void
|
|
Packit |
4c4d6b |
json_node_set_parent (JsonNode *node,
|
|
Packit |
4c4d6b |
JsonNode *parent)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_IS_VALID (node));
|
|
Packit |
4c4d6b |
g_return_if_fail (parent == NULL ||
|
|
Packit |
4c4d6b |
!json_node_is_immutable (parent));
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
node->parent = parent;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_get_parent:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Retrieves the parent #JsonNode of @node.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer none) (nullable): the parent node, or %NULL if @node
|
|
Packit |
4c4d6b |
* is the root node
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonNode *
|
|
Packit |
4c4d6b |
json_node_get_parent (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return node->parent;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_set_string:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode initialized to %JSON_NODE_VALUE
|
|
Packit |
4c4d6b |
* @value: a string value
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Sets @value as the string content of the @node, replacing any existing
|
|
Packit |
4c4d6b |
* content.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* It is an error to call this on an immutable node, or on a node which is not
|
|
Packit |
4c4d6b |
* a value node.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
void
|
|
Packit |
4c4d6b |
json_node_set_string (JsonNode *node,
|
|
Packit |
4c4d6b |
const gchar *value)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_IS_VALID (node));
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
|
|
Packit |
4c4d6b |
g_return_if_fail (!node->immutable);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (node->data.value == NULL)
|
|
Packit |
4c4d6b |
node->data.value = json_value_init (json_value_alloc (), JSON_VALUE_STRING);
|
|
Packit |
4c4d6b |
else
|
|
Packit |
4c4d6b |
json_value_init (node->data.value, JSON_VALUE_STRING);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
json_value_set_string (node->data.value, value);
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_get_string:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode of type %JSON_NODE_VALUE
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Gets the string value stored inside a #JsonNode. If the node does not hold a
|
|
Packit |
4c4d6b |
* string value, %NULL is returned.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (nullable): a string value.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
const gchar *
|
|
Packit |
4c4d6b |
json_node_get_string (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
|
|
Packit |
4c4d6b |
return NULL;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (JSON_VALUE_HOLDS_STRING (node->data.value))
|
|
Packit |
4c4d6b |
return json_value_get_string (node->data.value);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return NULL;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_dup_string:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode of type %JSON_NODE_VALUE
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Gets a copy of the string value stored inside a #JsonNode. If the node does
|
|
Packit |
4c4d6b |
* not hold a string value, %NULL is returned.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: (transfer full) (nullable): a newly allocated string
|
|
Packit |
4c4d6b |
* containing a copy of the #JsonNode contents. Use g_free() to free the
|
|
Packit |
4c4d6b |
* allocated resources
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
gchar *
|
|
Packit |
4c4d6b |
json_node_dup_string (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return g_strdup (json_node_get_string (node));
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_set_int:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode of type %JSON_NODE_VALUE
|
|
Packit |
4c4d6b |
* @value: an integer value
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Sets @value as the integer content of the @node, replacing any existing
|
|
Packit |
4c4d6b |
* content.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* It is an error to call this on an immutable node, or on a node which is not
|
|
Packit |
4c4d6b |
* a value node.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
void
|
|
Packit |
4c4d6b |
json_node_set_int (JsonNode *node,
|
|
Packit |
4c4d6b |
gint64 value)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_IS_VALID (node));
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
|
|
Packit |
4c4d6b |
g_return_if_fail (!node->immutable);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (node->data.value == NULL)
|
|
Packit |
4c4d6b |
node->data.value = json_value_init (json_value_alloc (), JSON_VALUE_INT);
|
|
Packit |
4c4d6b |
else
|
|
Packit |
4c4d6b |
json_value_init (node->data.value, JSON_VALUE_INT);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
json_value_set_int (node->data.value, value);
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_get_int:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode of type %JSON_NODE_VALUE
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Gets the integer value stored inside a #JsonNode. If the node holds a double
|
|
Packit |
4c4d6b |
* value, its integer component is returned. If the node holds a %FALSE boolean
|
|
Packit |
4c4d6b |
* value, `0` is returned; otherwise a non-zero integer is returned. If the
|
|
Packit |
4c4d6b |
* node holds a %JSON_NODE_NULL value or a value of another non-integer type,
|
|
Packit |
4c4d6b |
* `0` is returned.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: an integer value.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
gint64
|
|
Packit |
4c4d6b |
json_node_get_int (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_IS_VALID (node), 0);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
|
|
Packit |
4c4d6b |
return 0;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (JSON_VALUE_HOLDS_INT (node->data.value))
|
|
Packit |
4c4d6b |
return json_value_get_int (node->data.value);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (JSON_VALUE_HOLDS_DOUBLE (node->data.value))
|
|
Packit |
4c4d6b |
return json_value_get_double (node->data.value);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (JSON_VALUE_HOLDS_BOOLEAN (node->data.value))
|
|
Packit |
4c4d6b |
return json_value_get_boolean (node->data.value);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return 0;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_set_double:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode of type %JSON_NODE_VALUE
|
|
Packit |
4c4d6b |
* @value: a double value
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Sets @value as the double content of the @node, replacing any existing
|
|
Packit |
4c4d6b |
* content.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* It is an error to call this on an immutable node, or on a node which is not
|
|
Packit |
4c4d6b |
* a value node.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
void
|
|
Packit |
4c4d6b |
json_node_set_double (JsonNode *node,
|
|
Packit |
4c4d6b |
gdouble value)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_IS_VALID (node));
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
|
|
Packit |
4c4d6b |
g_return_if_fail (!node->immutable);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (node->data.value == NULL)
|
|
Packit |
4c4d6b |
node->data.value = json_value_init (json_value_alloc (), JSON_VALUE_DOUBLE);
|
|
Packit |
4c4d6b |
else
|
|
Packit |
4c4d6b |
json_value_init (node->data.value, JSON_VALUE_DOUBLE);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
json_value_set_double (node->data.value, value);
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_get_double:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode of type %JSON_NODE_VALUE
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Gets the double value stored inside a #JsonNode. If the node holds an integer
|
|
Packit |
4c4d6b |
* value, it is returned as a double. If the node holds a %FALSE boolean value,
|
|
Packit |
4c4d6b |
* `0.0` is returned; otherwise a non-zero double is returned. If the node holds
|
|
Packit |
4c4d6b |
* a %JSON_NODE_NULL value or a value of another non-double type, `0.0` is
|
|
Packit |
4c4d6b |
* returned.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: a double value.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
gdouble
|
|
Packit |
4c4d6b |
json_node_get_double (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_IS_VALID (node), 0.0);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
|
|
Packit |
4c4d6b |
return 0;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (JSON_VALUE_HOLDS_DOUBLE (node->data.value))
|
|
Packit |
4c4d6b |
return json_value_get_double (node->data.value);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (JSON_VALUE_HOLDS_INT (node->data.value))
|
|
Packit |
4c4d6b |
return (gdouble) json_value_get_int (node->data.value);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (JSON_VALUE_HOLDS_BOOLEAN (node->data.value))
|
|
Packit |
4c4d6b |
return (gdouble) json_value_get_boolean (node->data.value);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return 0.0;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_set_boolean:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode of type %JSON_NODE_VALUE
|
|
Packit |
4c4d6b |
* @value: a boolean value
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Sets @value as the boolean content of the @node, replacing any existing
|
|
Packit |
4c4d6b |
* content.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* It is an error to call this on an immutable node, or on a node which is not
|
|
Packit |
4c4d6b |
* a value node.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
void
|
|
Packit |
4c4d6b |
json_node_set_boolean (JsonNode *node,
|
|
Packit |
4c4d6b |
gboolean value)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_IS_VALID (node));
|
|
Packit |
4c4d6b |
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
|
|
Packit |
4c4d6b |
g_return_if_fail (!node->immutable);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (node->data.value == NULL)
|
|
Packit |
4c4d6b |
node->data.value = json_value_init (json_value_alloc (), JSON_VALUE_BOOLEAN);
|
|
Packit |
4c4d6b |
else
|
|
Packit |
4c4d6b |
json_value_init (node->data.value, JSON_VALUE_BOOLEAN);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
json_value_set_boolean (node->data.value, value);
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_get_boolean:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode of type %JSON_NODE_VALUE
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Gets the boolean value stored inside a #JsonNode. If the node holds an
|
|
Packit |
4c4d6b |
* integer or double value which is zero, %FALSE is returned; otherwise %TRUE
|
|
Packit |
4c4d6b |
* is returned. If the node holds a %JSON_NODE_NULL value or a value of another
|
|
Packit |
4c4d6b |
* non-boolean type, %FALSE is returned.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: a boolean value.
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
gboolean
|
|
Packit |
4c4d6b |
json_node_get_boolean (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_IS_VALID (node), FALSE);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
|
|
Packit |
4c4d6b |
return FALSE;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (JSON_VALUE_HOLDS_BOOLEAN (node->data.value))
|
|
Packit |
4c4d6b |
return json_value_get_boolean (node->data.value);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (JSON_VALUE_HOLDS_INT (node->data.value))
|
|
Packit |
4c4d6b |
return json_value_get_int (node->data.value) != 0;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (JSON_VALUE_HOLDS_DOUBLE (node->data.value))
|
|
Packit |
4c4d6b |
return json_value_get_double (node->data.value) != 0.0;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return FALSE;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_get_node_type:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Retrieves the #JsonNodeType of @node
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: the type of the node
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 0.8
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
JsonNodeType
|
|
Packit |
4c4d6b |
json_node_get_node_type (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_IS_VALID (node), JSON_NODE_NULL);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return node->type;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_is_null:
|
|
Packit |
4c4d6b |
* @node: a #JsonNode
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Checks whether @node is a %JSON_NODE_NULL.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* A %JSON_NODE_NULL node is not the same as a %NULL #JsonNode; a
|
|
Packit |
4c4d6b |
* %JSON_NODE_NULL represents a 'null' value in the JSON tree.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Return value: %TRUE if the node is null
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Since: 0.8
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
gboolean
|
|
Packit |
4c4d6b |
json_node_is_null (JsonNode *node)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
g_return_val_if_fail (JSON_NODE_IS_VALID (node), TRUE);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return node->type == JSON_NODE_NULL;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_type_is_a:
|
|
Packit |
4c4d6b |
* @sub: sub-type
|
|
Packit |
4c4d6b |
* @super: super-type
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Check whether @sub is a sub-type of, or equal to, @super. The only sub-type
|
|
Packit |
4c4d6b |
* relationship in the JSON Schema type system is that
|
|
Packit |
4c4d6b |
* %WBL_PRIMITIVE_TYPE_INTEGER is a sub-type of %WBL_PRIMITIVE_TYPE_NUMBER.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Formally, this function calculates: `@sub <: @super`.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Reference: http://json-schema.org/latest/json-schema-core.html#rfc.section.3.5
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Returns: %TRUE if @sub is a sub-type of, or equal to, @super; %FALSE
|
|
Packit |
4c4d6b |
* otherwise
|
|
Packit |
4c4d6b |
* Since: 1.2
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
static gboolean
|
|
Packit |
4c4d6b |
json_type_is_a (JsonNode *sub,
|
|
Packit |
4c4d6b |
JsonNode *super)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
if (super->type == JSON_NODE_VALUE && sub->type == JSON_NODE_VALUE)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
JsonValueType super_value_type, sub_value_type;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (super->data.value == NULL || sub->data.value == NULL)
|
|
Packit |
4c4d6b |
return FALSE;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
super_value_type = super->data.value->type;
|
|
Packit |
4c4d6b |
sub_value_type = sub->data.value->type;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return (super_value_type == sub_value_type ||
|
|
Packit |
4c4d6b |
(super_value_type == JSON_VALUE_DOUBLE &&
|
|
Packit |
4c4d6b |
sub_value_type == JSON_VALUE_INT));
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return (super->type == sub->type);
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_string_hash:
|
|
Packit |
4c4d6b |
* @key: (type utf8): a JSON string to hash
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Calculate a hash value for the given @key (a UTF-8 JSON string).
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Note: Member names are compared byte-wise, without applying any Unicode
|
|
Packit |
4c4d6b |
* decomposition or normalisation. This is not explicitly mentioned in the JSON
|
|
Packit |
4c4d6b |
* standard (ECMA-404), but is assumed.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Returns: hash value for @key
|
|
Packit |
4c4d6b |
* Since: 1.2
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
guint
|
|
Packit |
4c4d6b |
json_string_hash (gconstpointer key)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
return g_str_hash (key);
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_string_equal:
|
|
Packit |
4c4d6b |
* @a: (type utf8): a JSON string
|
|
Packit |
4c4d6b |
* @b: (type utf8): another JSON string
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Check whether @a and @b are equal UTF-8 JSON strings.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Returns: %TRUE if @a and @b are equal; %FALSE otherwise
|
|
Packit |
4c4d6b |
* Since: 1.2
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
gboolean
|
|
Packit |
4c4d6b |
json_string_equal (gconstpointer a,
|
|
Packit |
4c4d6b |
gconstpointer b)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
return g_str_equal (a, b);
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_string_compare:
|
|
Packit |
4c4d6b |
* @a: (type utf8): a JSON string
|
|
Packit |
4c4d6b |
* @b: (type utf8): another JSON string
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Check whether @a and @b are equal UTF-8 JSON strings and return an ordering
|
|
Packit |
4c4d6b |
* over them in strcmp() style.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Returns: an integer less than zero if @a < @b, equal to zero if @a == @b, and
|
|
Packit |
4c4d6b |
* greater than zero if @a > @b
|
|
Packit |
4c4d6b |
* Since: 1.2
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
gint
|
|
Packit |
4c4d6b |
json_string_compare (gconstpointer a,
|
|
Packit |
4c4d6b |
gconstpointer b)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
return g_strcmp0 (a, b);
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_hash:
|
|
Packit |
4c4d6b |
* @key: (type JsonNode): a JSON node to hash
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Calculate a hash value for the given @key (a #JsonNode).
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* The hash is calculated over the node and its value, recursively. If the node
|
|
Packit |
4c4d6b |
* is immutable, this is a fast operation; otherwise, it scales proportionally
|
|
Packit |
4c4d6b |
* with the size of the node’s value (for example, with the number of members
|
|
Packit |
4c4d6b |
* in the #JsonObject if this node contains an object).
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Returns: hash value for @key
|
|
Packit |
4c4d6b |
* Since: 1.2
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
guint
|
|
Packit |
4c4d6b |
json_node_hash (gconstpointer key)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
JsonNode *node; /* unowned */
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/* These are all randomly generated and arbitrary. */
|
|
Packit |
4c4d6b |
const guint value_hash = 0xc19e75ad;
|
|
Packit |
4c4d6b |
const guint array_hash = 0x865acfc2;
|
|
Packit |
4c4d6b |
const guint object_hash = 0x3c8f3135;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
node = (JsonNode *) key;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/* XOR the hash values with a (constant) random number depending on the node’s
|
|
Packit |
4c4d6b |
* type so that empty values, arrays and objects do not all collide at the
|
|
Packit |
4c4d6b |
* hash value 0. */
|
|
Packit |
4c4d6b |
switch (node->type)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
case JSON_NODE_NULL:
|
|
Packit |
4c4d6b |
return 0;
|
|
Packit |
4c4d6b |
case JSON_NODE_VALUE:
|
|
Packit |
4c4d6b |
return value_hash ^ json_value_hash (node->data.value);
|
|
Packit |
4c4d6b |
case JSON_NODE_ARRAY:
|
|
Packit |
4c4d6b |
return array_hash ^ json_array_hash (json_node_get_array (node));
|
|
Packit |
4c4d6b |
case JSON_NODE_OBJECT:
|
|
Packit |
4c4d6b |
return object_hash ^ json_object_hash (json_node_get_object (node));
|
|
Packit |
4c4d6b |
default:
|
|
Packit |
4c4d6b |
g_assert_not_reached ();
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/**
|
|
Packit |
4c4d6b |
* json_node_equal:
|
|
Packit |
4c4d6b |
* @a: (type JsonNode): a JSON node
|
|
Packit |
4c4d6b |
* @b: (type JsonNode): another JSON node
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Check whether @a and @b are equal #JsonNodes, meaning they have the same
|
|
Packit |
4c4d6b |
* type and same values (checked recursively). Note that integer values are
|
|
Packit |
4c4d6b |
* compared numerically, ignoring type, so a double value 4.0 is equal to the
|
|
Packit |
4c4d6b |
* integer value 4.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Returns: %TRUE if @a and @b are equal; %FALSE otherwise
|
|
Packit |
4c4d6b |
* Since: 1.2
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
gboolean
|
|
Packit |
4c4d6b |
json_node_equal (gconstpointer a,
|
|
Packit |
4c4d6b |
gconstpointer b)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
JsonNode *node_a, *node_b; /* unowned */
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
node_a = (JsonNode *) a;
|
|
Packit |
4c4d6b |
node_b = (JsonNode *) b;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/* Identity comparison. */
|
|
Packit |
4c4d6b |
if (node_a == node_b)
|
|
Packit |
4c4d6b |
return TRUE;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/* Eliminate mismatched types rapidly. */
|
|
Packit |
4c4d6b |
if (!json_type_is_a (node_a, node_b) &&
|
|
Packit |
4c4d6b |
!json_type_is_a (node_b, node_a))
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
return FALSE;
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
switch (node_a->type)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
case JSON_NODE_NULL:
|
|
Packit |
4c4d6b |
/* Types match already. */
|
|
Packit |
4c4d6b |
return TRUE;
|
|
Packit |
4c4d6b |
case JSON_NODE_ARRAY:
|
|
Packit |
4c4d6b |
return json_array_equal (json_node_get_array (node_a),
|
|
Packit |
4c4d6b |
json_node_get_array (node_b));
|
|
Packit |
4c4d6b |
case JSON_NODE_OBJECT:
|
|
Packit |
4c4d6b |
return json_object_equal (json_node_get_object (node_a),
|
|
Packit |
4c4d6b |
json_node_get_object (node_b));
|
|
Packit |
4c4d6b |
case JSON_NODE_VALUE:
|
|
Packit |
4c4d6b |
/* Handled below. */
|
|
Packit |
4c4d6b |
break;
|
|
Packit |
4c4d6b |
default:
|
|
Packit |
4c4d6b |
g_assert_not_reached ();
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/* Handle values. */
|
|
Packit |
4c4d6b |
switch (node_a->data.value->type)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
case JSON_VALUE_NULL:
|
|
Packit |
4c4d6b |
/* Types already match. */
|
|
Packit |
4c4d6b |
return TRUE;
|
|
Packit |
4c4d6b |
case JSON_VALUE_BOOLEAN:
|
|
Packit |
4c4d6b |
return (json_node_get_boolean (node_a) == json_node_get_boolean (node_b));
|
|
Packit |
4c4d6b |
case JSON_VALUE_STRING:
|
|
Packit |
4c4d6b |
return json_string_equal (json_node_get_string (node_a),
|
|
Packit |
4c4d6b |
json_node_get_string (node_b));
|
|
Packit |
4c4d6b |
case JSON_VALUE_DOUBLE:
|
|
Packit |
4c4d6b |
case JSON_VALUE_INT: {
|
|
Packit |
4c4d6b |
gdouble val_a, val_b;
|
|
Packit |
4c4d6b |
JsonValueType value_type_a, value_type_b;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
value_type_a = node_a->data.value->type;
|
|
Packit |
4c4d6b |
value_type_b = node_b->data.value->type;
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/* Integer comparison doesn’t need to involve doubles… */
|
|
Packit |
4c4d6b |
if (value_type_a == JSON_VALUE_INT &&
|
|
Packit |
4c4d6b |
value_type_b == JSON_VALUE_INT)
|
|
Packit |
4c4d6b |
{
|
|
Packit |
4c4d6b |
return (json_node_get_int (node_a) ==
|
|
Packit |
4c4d6b |
json_node_get_int (node_b));
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
/* …but everything else does. We can use bitwise double equality here,
|
|
Packit |
4c4d6b |
* since we’re not doing any calculations which could introduce floating
|
|
Packit |
4c4d6b |
* point error. We expect that the doubles in the JSON nodes come directly
|
|
Packit |
4c4d6b |
* from strtod() or similar, so should be bitwise equal for equal string
|
|
Packit |
4c4d6b |
* representations.
|
|
Packit |
4c4d6b |
*
|
|
Packit |
4c4d6b |
* Interesting background reading:
|
|
Packit |
4c4d6b |
* http://randomascii.wordpress.com/2012/06/26/\
|
|
Packit |
4c4d6b |
* doubles-are-not-floats-so-dont-compare-them/
|
|
Packit |
4c4d6b |
*/
|
|
Packit |
4c4d6b |
if (value_type_a == JSON_VALUE_INT)
|
|
Packit |
4c4d6b |
val_a = json_node_get_int (node_a);
|
|
Packit |
4c4d6b |
else
|
|
Packit |
4c4d6b |
val_a = json_node_get_double (node_a);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
if (value_type_b == JSON_VALUE_INT)
|
|
Packit |
4c4d6b |
val_b = json_node_get_int (node_b);
|
|
Packit |
4c4d6b |
else
|
|
Packit |
4c4d6b |
val_b = json_node_get_double (node_b);
|
|
Packit |
4c4d6b |
|
|
Packit |
4c4d6b |
return (val_a == val_b);
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
case JSON_VALUE_INVALID:
|
|
Packit |
4c4d6b |
default:
|
|
Packit |
4c4d6b |
g_assert_not_reached ();
|
|
Packit |
4c4d6b |
}
|
|
Packit |
4c4d6b |
}
|