[json-glib] node: Add json_node_ref() and json_node_unref()
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [json-glib] node: Add json_node_ref() and json_node_unref()
- Date: Tue, 1 Mar 2016 16:06:50 +0000 (UTC)
commit 1de237a502ceee96df7091c2df4492b8bc08b2c5
Author: Philip Withnall <philip withnall collabora co uk>
Date: Sat Nov 7 17:38:22 2015 +0100
node: Add json_node_ref() and json_node_unref()
Add reference counting semantics to JsonNode, in addition to the
existing init/unset and alloc/free semantics.
json_node_free() must only be used with nodes allocated using
json_node_alloc(). json_node_unref() may be used with all nodes (if
correctly paired; it may be paired with json_node_alloc()).
It is not valid to call json_node_free() on a node whose reference count
is not 1.
https://bugzilla.gnome.org/show_bug.cgi?id=756121
doc/reference/json-glib-sections.txt | 2 +
json-glib/json-array.c | 6 +-
json-glib/json-builder.c | 4 +-
json-glib/json-generator.c | 4 +-
json-glib/json-gobject.c | 4 +-
json-glib/json-gvariant.c | 2 +-
json-glib/json-node.c | 129 +++++++++++++++++++++++++---------
json-glib/json-object.c | 4 +-
json-glib/json-parser.c | 24 +++---
json-glib/json-path.c | 4 +-
json-glib/json-reader.c | 4 +-
json-glib/json-types-private.h | 13 +++-
json-glib/json-types.h | 5 ++
13 files changed, 141 insertions(+), 64 deletions(-)
---
diff --git a/doc/reference/json-glib-sections.txt b/doc/reference/json-glib-sections.txt
index 2dccde9..21e1f0d 100644
--- a/doc/reference/json-glib-sections.txt
+++ b/doc/reference/json-glib-sections.txt
@@ -110,6 +110,8 @@ json_node_init_array
json_node_new
json_node_copy
json_node_free
+json_node_ref
+json_node_unref
json_node_is_immutable
json_node_seal
diff --git a/json-glib/json-array.c b/json-glib/json-array.c
index 05cde4a..cc9c979 100644
--- a/json-glib/json-array.c
+++ b/json-glib/json-array.c
@@ -124,7 +124,7 @@ json_array_unref (JsonArray *array)
guint i;
for (i = 0; i < array->elements->len; i++)
- json_node_free (g_ptr_array_index (array->elements, i));
+ json_node_unref (g_ptr_array_index (array->elements, i));
g_ptr_array_free (array->elements, TRUE);
array->elements = NULL;
@@ -217,7 +217,7 @@ json_array_get_elements (JsonArray *array)
* element at @index_ inside a #JsonArray
*
* Return value: (transfer full): a copy of the #JsonNode at the requested
- * index. Use json_node_free() when done.
+ * index. Use json_node_unref() when done.
*
* Since: 0.6
*/
@@ -706,7 +706,7 @@ json_array_remove_element (JsonArray *array,
g_return_if_fail (array != NULL);
g_return_if_fail (index_ < array->elements->len);
- json_node_free (g_ptr_array_remove_index (array->elements, index_));
+ json_node_unref (g_ptr_array_remove_index (array->elements, index_));
}
/**
diff --git a/json-glib/json-builder.c b/json-glib/json-builder.c
index 6531b0c..66a5796 100644
--- a/json-glib/json-builder.c
+++ b/json-glib/json-builder.c
@@ -125,7 +125,7 @@ json_builder_free_all_state (JsonBuilder *builder)
if (builder->priv->root)
{
- json_node_free (builder->priv->root);
+ json_node_unref (builder->priv->root);
builder->priv->root = NULL;
}
}
@@ -272,7 +272,7 @@ json_builder_new_immutable (void)
* (ie: all opened objects, object members and arrays are being closed).
*
* Return value: (transfer full): the #JsonNode, or %NULL if the build is not complete.
- * Free the returned value with json_node_free().
+ * Free the returned value with json_node_unref().
*/
JsonNode *
json_builder_get_root (JsonBuilder *builder)
diff --git a/json-glib/json-generator.c b/json-glib/json-generator.c
index 8eed152..c47e7fe 100644
--- a/json-glib/json-generator.c
+++ b/json-glib/json-generator.c
@@ -140,7 +140,7 @@ json_generator_finalize (GObject *gobject)
priv = json_generator_get_instance_private ((JsonGenerator *) gobject);
if (priv->root != NULL)
- json_node_free (priv->root);
+ json_node_unref (priv->root);
G_OBJECT_CLASS (json_generator_parent_class)->finalize (gobject);
}
@@ -722,7 +722,7 @@ json_generator_set_root (JsonGenerator *generator,
if (generator->priv->root != NULL)
{
- json_node_free (generator->priv->root);
+ json_node_unref (generator->priv->root);
generator->priv->root = NULL;
}
diff --git a/json-glib/json-gobject.c b/json-glib/json-gobject.c
index d39088e..34a43c8 100644
--- a/json-glib/json-gobject.c
+++ b/json-glib/json-gobject.c
@@ -839,7 +839,7 @@ json_gobject_deserialize (GType gtype,
* map to a property of the #GObject
*
* Return value: (transfer full): the newly created #JsonNode
- * of type %JSON_NODE_OBJECT. Use json_node_free() to free
+ * of type %JSON_NODE_OBJECT. Use json_node_unref() to free
* the resources allocated by this function
*
* Since: 0.10
@@ -1012,7 +1012,7 @@ json_gobject_to_data (GObject *gobject,
data = json_generator_to_data (gen, length);
g_object_unref (gen);
- json_node_free (root);
+ json_node_unref (root);
return data;
}
diff --git a/json-glib/json-gvariant.c b/json-glib/json-gvariant.c
index f8058df..6d55fb8 100644
--- a/json-glib/json-gvariant.c
+++ b/json-glib/json-gvariant.c
@@ -440,7 +440,7 @@ json_gvariant_serialize_data (GVariant *variant, gsize *length)
g_object_unref (generator);
- json_node_free (json_node);
+ json_node_unref (json_node);
return json;
}
diff --git a/json-glib/json-node.c b/json-glib/json-node.c
index 092a27f..35a7918 100644
--- a/json-glib/json-node.c
+++ b/json-glib/json-node.c
@@ -55,9 +55,18 @@
* possibility of a value deep within the tree changing and affecting hash
* values. Immutable #JsonNodes may be passed to functions which retain a
* reference to them without needing to take a copy.
+ *
+ * #JsonNode supports two types of memory management: alloc/free semantics, and
+ * ref/unref semantics. The two may be mixed to a limited extent: nodes may be
+ * allocated (which gives them a reference count of 1), referenced zero or more
+ * times, unreferenced exactly that number of times (using json_node_unref()),
+ * then either unreferenced exactly once more or freed (using json_node_free())
+ * to destroy them. json_node_free() must not be used when a node might have a
+ * reference count not equal to 1. To this end, json-glib uses json_node_copy()
+ * and json_node_unref() internally.
*/
-G_DEFINE_BOXED_TYPE (JsonNode, json_node, json_node_copy, json_node_free);
+G_DEFINE_BOXED_TYPE (JsonNode, json_node, json_node_copy, json_node_unref);
/**
* json_node_get_value_type:
@@ -111,12 +120,20 @@ json_node_get_value_type (JsonNode *node)
JsonNode *
json_node_alloc (void)
{
- return g_slice_new0 (JsonNode);
+ JsonNode *node = NULL;
+
+ node = g_slice_new0 (JsonNode);
+ node->ref_count = 1;
+ node->allocated = TRUE;
+
+ return node;
}
static void
json_node_unset (JsonNode *node)
{
+ /* Note: Don't use JSON_NODE_IS_VALID here because this may legitimately be
+ * called with (node->ref_count == 0) from json_node_unref(). */
g_assert (node != NULL);
switch (node->type)
@@ -161,6 +178,7 @@ json_node_init (JsonNode *node,
{
g_return_val_if_fail (type >= JSON_NODE_OBJECT &&
type <= JSON_NODE_NULL, NULL);
+ g_return_val_if_fail (node->ref_count == 1, NULL);
json_node_unset (node);
@@ -392,9 +410,9 @@ json_node_copy (JsonNode *node)
{
JsonNode *copy;
- g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
- copy = g_slice_new0 (JsonNode);
+ copy = json_node_alloc ();
copy->type = node->type;
copy->immutable = node->immutable;
@@ -427,6 +445,47 @@ json_node_copy (JsonNode *node)
}
/**
+ * json_node_ref:
+ * @node: a #JsonNode
+ *
+ * Increment the reference count of @node.
+ *
+ * Since: UNRELEASED
+ * Returns: (transfer full): a pointer to @node
+ */
+JsonNode *
+json_node_ref (JsonNode *node)
+{
+ g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
+
+ g_atomic_int_inc (&node->ref_count);
+
+ return node;
+}
+
+/**
+ * json_node_unref:
+ * @node: (transfer full): a #JsonNode
+ *
+ * Decrement the reference count of @node. If it reaches zero, the node is
+ * freed.
+ *
+ * Since: UNRELEASED
+ */
+void
+json_node_unref (JsonNode *node)
+{
+ g_return_if_fail (JSON_NODE_IS_VALID (node));
+
+ if (g_atomic_int_dec_and_test (&node->ref_count))
+ {
+ json_node_unset (node);
+ if (node->allocated)
+ g_slice_free (JsonNode, node);
+ }
+}
+
+/**
* json_node_set_object:
* @node: a #JsonNode initialized to %JSON_NODE_OBJECT
* @object: (nullable): a #JsonObject
@@ -441,7 +500,7 @@ void
json_node_set_object (JsonNode *node,
JsonObject *object)
{
- g_return_if_fail (node != NULL);
+ g_return_if_fail (JSON_NODE_IS_VALID (node));
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT);
g_return_if_fail (!node->immutable);
@@ -467,7 +526,7 @@ void
json_node_take_object (JsonNode *node,
JsonObject *object)
{
- g_return_if_fail (node != NULL);
+ g_return_if_fail (JSON_NODE_IS_VALID (node));
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT);
g_return_if_fail (!node->immutable);
@@ -492,7 +551,7 @@ json_node_take_object (JsonNode *node,
JsonObject *
json_node_get_object (JsonNode *node)
{
- g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT, NULL);
return node->data.object;
@@ -510,7 +569,7 @@ json_node_get_object (JsonNode *node)
JsonObject *
json_node_dup_object (JsonNode *node)
{
- g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT, NULL);
if (node->data.object)
@@ -532,7 +591,7 @@ void
json_node_set_array (JsonNode *node,
JsonArray *array)
{
- g_return_if_fail (node != NULL);
+ g_return_if_fail (JSON_NODE_IS_VALID (node));
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY);
g_return_if_fail (!node->immutable);
@@ -558,7 +617,7 @@ void
json_node_take_array (JsonNode *node,
JsonArray *array)
{
- g_return_if_fail (node != NULL);
+ g_return_if_fail (JSON_NODE_IS_VALID (node));
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY);
g_return_if_fail (!node->immutable);
@@ -583,7 +642,7 @@ json_node_take_array (JsonNode *node,
JsonArray *
json_node_get_array (JsonNode *node)
{
- g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY, NULL);
return node->data.array;
@@ -602,7 +661,7 @@ json_node_get_array (JsonNode *node)
JsonArray *
json_node_dup_array (JsonNode *node)
{
- g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY, NULL);
if (node->data.array)
@@ -623,7 +682,7 @@ void
json_node_get_value (JsonNode *node,
GValue *value)
{
- g_return_if_fail (node != NULL);
+ g_return_if_fail (JSON_NODE_IS_VALID (node));
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
if (node->data.value)
@@ -666,7 +725,7 @@ void
json_node_set_value (JsonNode *node,
const GValue *value)
{
- g_return_if_fail (node != NULL);
+ g_return_if_fail (JSON_NODE_IS_VALID (node));
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
g_return_if_fail (G_VALUE_TYPE (value) != G_TYPE_INVALID);
g_return_if_fail (!node->immutable);
@@ -707,7 +766,7 @@ json_node_set_value (JsonNode *node,
break;
default:
- g_warning ("Invalid value of type '%s'",
+ g_message ("Invalid value of type '%s'",
g_type_name (G_VALUE_TYPE (value)));
return;
}
@@ -723,8 +782,14 @@ json_node_set_value (JsonNode *node,
void
json_node_free (JsonNode *node)
{
+ g_return_if_fail (node == NULL || JSON_NODE_IS_VALID (node));
+ g_return_if_fail (node == NULL || node->allocated);
+
if (G_LIKELY (node))
{
+ if (node->ref_count > 1)
+ g_warning ("Freeing a JsonNode %p owned by other code.", node);
+
json_node_unset (node);
g_slice_free (JsonNode, node);
}
@@ -746,9 +811,7 @@ json_node_free (JsonNode *node)
void
json_node_seal (JsonNode *node)
{
- g_return_if_fail (node != NULL);
- g_return_if_fail (node->type >= JSON_NODE_OBJECT &&
- node->type <= JSON_NODE_NULL);
+ g_return_if_fail (JSON_NODE_IS_VALID (node));
if (node->immutable)
return;
@@ -789,9 +852,7 @@ json_node_seal (JsonNode *node)
gboolean
json_node_is_immutable (JsonNode *node)
{
- g_return_val_if_fail (node != NULL, FALSE);
- g_return_val_if_fail (node->type >= JSON_NODE_OBJECT &&
- node->type <= JSON_NODE_NULL, FALSE);
+ g_return_val_if_fail (JSON_NODE_IS_VALID (node), FALSE);
return node->immutable;
}
@@ -866,7 +927,7 @@ void
json_node_set_parent (JsonNode *node,
JsonNode *parent)
{
- g_return_if_fail (node != NULL);
+ g_return_if_fail (JSON_NODE_IS_VALID (node));
g_return_if_fail (parent == NULL ||
!json_node_is_immutable (parent));
@@ -885,7 +946,7 @@ json_node_set_parent (JsonNode *node,
JsonNode *
json_node_get_parent (JsonNode *node)
{
- g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
return node->parent;
}
@@ -904,7 +965,7 @@ void
json_node_set_string (JsonNode *node,
const gchar *value)
{
- g_return_if_fail (node != NULL);
+ g_return_if_fail (JSON_NODE_IS_VALID (node));
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
g_return_if_fail (!node->immutable);
@@ -927,7 +988,7 @@ json_node_set_string (JsonNode *node,
const gchar *
json_node_get_string (JsonNode *node)
{
- g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
return NULL;
@@ -950,7 +1011,7 @@ json_node_get_string (JsonNode *node)
gchar *
json_node_dup_string (JsonNode *node)
{
- g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL);
return g_strdup (json_node_get_string (node));
}
@@ -969,7 +1030,7 @@ void
json_node_set_int (JsonNode *node,
gint64 value)
{
- g_return_if_fail (node != NULL);
+ g_return_if_fail (JSON_NODE_IS_VALID (node));
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
g_return_if_fail (!node->immutable);
@@ -992,7 +1053,7 @@ json_node_set_int (JsonNode *node,
gint64
json_node_get_int (JsonNode *node)
{
- g_return_val_if_fail (node != NULL, 0);
+ g_return_val_if_fail (JSON_NODE_IS_VALID (node), 0);
if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
return 0;
@@ -1023,7 +1084,7 @@ void
json_node_set_double (JsonNode *node,
gdouble value)
{
- g_return_if_fail (node != NULL);
+ g_return_if_fail (JSON_NODE_IS_VALID (node));
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
g_return_if_fail (!node->immutable);
@@ -1046,7 +1107,7 @@ json_node_set_double (JsonNode *node,
gdouble
json_node_get_double (JsonNode *node)
{
- g_return_val_if_fail (node != NULL, 0.0);
+ g_return_val_if_fail (JSON_NODE_IS_VALID (node), 0.0);
if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
return 0;
@@ -1077,7 +1138,7 @@ void
json_node_set_boolean (JsonNode *node,
gboolean value)
{
- g_return_if_fail (node != NULL);
+ g_return_if_fail (JSON_NODE_IS_VALID (node));
g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
g_return_if_fail (!node->immutable);
@@ -1100,7 +1161,7 @@ json_node_set_boolean (JsonNode *node,
gboolean
json_node_get_boolean (JsonNode *node)
{
- g_return_val_if_fail (node != NULL, FALSE);
+ g_return_val_if_fail (JSON_NODE_IS_VALID (node), FALSE);
if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
return FALSE;
@@ -1130,7 +1191,7 @@ json_node_get_boolean (JsonNode *node)
JsonNodeType
json_node_get_node_type (JsonNode *node)
{
- g_return_val_if_fail (node != NULL, JSON_NODE_NULL);
+ g_return_val_if_fail (JSON_NODE_IS_VALID (node), JSON_NODE_NULL);
return node->type;
}
@@ -1151,7 +1212,7 @@ json_node_get_node_type (JsonNode *node)
gboolean
json_node_is_null (JsonNode *node)
{
- g_return_val_if_fail (node != NULL, TRUE);
+ g_return_val_if_fail (JSON_NODE_IS_VALID (node), TRUE);
return node->type == JSON_NODE_NULL;
}
diff --git a/json-glib/json-object.c b/json-glib/json-object.c
index 574d04d..acb72f7 100644
--- a/json-glib/json-object.c
+++ b/json-glib/json-object.c
@@ -66,7 +66,7 @@ json_object_new (void)
object->ref_count = 1;
object->members = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free,
- (GDestroyNotify) json_node_free);
+ (GDestroyNotify) json_node_unref);
object->members_ordered = NULL;
return object;
@@ -525,7 +525,7 @@ json_object_get_values (JsonObject *object)
* inside a #JsonObject
*
* Return value: (transfer full): a copy of the node for the requested
- * object member or %NULL. Use json_node_free() when done.
+ * object member or %NULL. Use json_node_unref() when done.
*
* Since: 0.6
*/
diff --git a/json-glib/json-parser.c b/json-glib/json-parser.c
index 8f1c40c..a7b1c32 100644
--- a/json-glib/json-parser.c
+++ b/json-glib/json-parser.c
@@ -134,7 +134,7 @@ json_parser_clear (JsonParser *parser)
if (priv->root)
{
- json_node_free (priv->root);
+ json_node_unref (priv->root);
priv->root = NULL;
}
}
@@ -553,7 +553,7 @@ json_parse_array (JsonParser *parser,
{
/* the json_parse_* functions will have set the error code */
json_array_unref (array);
- json_node_free (priv->current_node);
+ json_node_unref (priv->current_node);
priv->current_node = old_current;
return token;
@@ -585,8 +585,8 @@ json_parse_array (JsonParser *parser,
priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
json_array_unref (array);
- json_node_free (priv->current_node);
- json_node_free (element);
+ json_node_unref (priv->current_node);
+ json_node_unref (element);
priv->current_node = old_current;
return G_TOKEN_RIGHT_BRACE;
@@ -669,7 +669,7 @@ json_parse_object (JsonParser *parser,
priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
json_object_unref (object);
- json_node_free (priv->current_node);
+ json_node_unref (priv->current_node);
priv->current_node = old_current;
return G_TOKEN_STRING;
@@ -685,7 +685,7 @@ json_parse_object (JsonParser *parser,
priv->error_code = JSON_PARSER_ERROR_EMPTY_MEMBER_NAME;
json_object_unref (object);
- json_node_free (priv->current_node);
+ json_node_unref (priv->current_node);
priv->current_node = old_current;
return G_TOKEN_STRING;
@@ -703,7 +703,7 @@ json_parse_object (JsonParser *parser,
g_free (name);
json_object_unref (object);
- json_node_free (priv->current_node);
+ json_node_unref (priv->current_node);
priv->current_node = old_current;
return ':';
@@ -739,7 +739,7 @@ json_parse_object (JsonParser *parser,
/* the json_parse_* functions will have set the error code */
g_free (name);
json_object_unref (object);
- json_node_free (priv->current_node);
+ json_node_unref (priv->current_node);
priv->current_node = old_current;
return token;
@@ -757,8 +757,8 @@ json_parse_object (JsonParser *parser,
priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
json_object_unref (object);
- json_node_free (member);
- json_node_free (priv->current_node);
+ json_node_unref (member);
+ json_node_unref (priv->current_node);
priv->current_node = old_current;
return G_TOKEN_RIGHT_BRACE;
@@ -769,8 +769,8 @@ json_parse_object (JsonParser *parser,
priv->error_code = JSON_PARSER_ERROR_MISSING_COMMA;
json_object_unref (object);
- json_node_free (member);
- json_node_free (priv->current_node);
+ json_node_unref (member);
+ json_node_unref (priv->current_node);
priv->current_node = old_current;
return G_TOKEN_COMMA;
diff --git a/json-glib/json-path.c b/json-glib/json-path.c
index 3ccf98f..4604cd9 100644
--- a/json-glib/json-path.c
+++ b/json-glib/json-path.c
@@ -936,7 +936,7 @@ walk_path_node (GList *path,
*
* Return value: (transfer full): a newly-created #JsonNode of type
* %JSON_NODE_ARRAY containing an array of matching #JsonNodes.
- * Use json_node_free() when done
+ * Use json_node_unref() when done
*
* Since: 0.14
*/
@@ -976,7 +976,7 @@ json_path_match (JsonPath *path,
*
* Return value: (transfer full): a newly-created #JsonNode of type
* %JSON_NODE_ARRAY containing an array of matching #JsonNodes.
- * Use json_node_free() when done
+ * Use json_node_unref() when done
*
* Since: 0.14
*/
diff --git a/json-glib/json-reader.c b/json-glib/json-reader.c
index 8c552e5..afc2414 100644
--- a/json-glib/json-reader.c
+++ b/json-glib/json-reader.c
@@ -113,7 +113,7 @@ json_reader_finalize (GObject *gobject)
JsonReaderPrivate *priv = JSON_READER (gobject)->priv;
if (priv->root != NULL)
- json_node_free (priv->root);
+ json_node_unref (priv->root);
if (priv->error != NULL)
g_clear_error (&priv->error);
@@ -258,7 +258,7 @@ json_reader_set_root (JsonReader *reader,
if (priv->root != NULL)
{
- json_node_free (priv->root);
+ json_node_unref (priv->root);
priv->root = NULL;
priv->current_node = NULL;
priv->previous_node = NULL;
diff --git a/json-glib/json-types-private.h b/json-glib/json-types-private.h
index 34a3160..8934e9a 100644
--- a/json-glib/json-types-private.h
+++ b/json-glib/json-types-private.h
@@ -28,6 +28,12 @@
G_BEGIN_DECLS
+#define JSON_NODE_IS_VALID(n) \
+ ((n) != NULL && \
+ (n)->type >= JSON_NODE_OBJECT && \
+ (n)->type <= JSON_NODE_NULL && \
+ (n)->ref_count >= 1)
+
typedef struct _JsonValue JsonValue;
typedef enum {
@@ -43,7 +49,10 @@ struct _JsonNode
{
/*< private >*/
JsonNodeType type;
+
+ volatile gint ref_count;
gboolean immutable : 1;
+ gboolean allocated : 1;
union {
JsonObject *object;
@@ -54,8 +63,8 @@ struct _JsonNode
JsonNode *parent;
};
-#define JSON_VALUE_INIT { JSON_VALUE_INVALID, 1, { 0 } }
-#define JSON_VALUE_INIT_TYPE(t) { (t), 1, { 0 } }
+#define JSON_VALUE_INIT { JSON_VALUE_INVALID, 1, FALSE, { 0 }, NULL }
+#define JSON_VALUE_INIT_TYPE(t) { (t), 1, FALSE, { 0 }, NULL }
#define JSON_VALUE_IS_VALID(v) ((v) != NULL && (v)->type != JSON_VALUE_INVALID)
#define JSON_VALUE_HOLDS(v,t) ((v) != NULL && (v)->type == (t))
#define JSON_VALUE_HOLDS_INT(v) (JSON_VALUE_HOLDS((v), JSON_VALUE_INT))
diff --git a/json-glib/json-types.h b/json-glib/json-types.h
index 5f2a084..33180b4 100644
--- a/json-glib/json-types.h
+++ b/json-glib/json-types.h
@@ -213,6 +213,11 @@ JsonNode * json_node_copy (JsonNode *node);
JSON_AVAILABLE_IN_1_0
void json_node_free (JsonNode *node);
+JSON_AVAILABLE_IN_1_2
+JsonNode * json_node_ref (JsonNode *node);
+JSON_AVAILABLE_IN_1_2
+void json_node_unref (JsonNode *node);
+
JSON_AVAILABLE_IN_1_0
JsonNodeType json_node_get_node_type (JsonNode *node);
JSON_AVAILABLE_IN_1_0
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]