[json-glib] object: Guarantee insertion order
- From: Emmanuele Bassi <ebassi src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [json-glib] object: Guarantee insertion order
- Date: Mon, 26 Oct 2009 22:38:39 +0000 (UTC)
commit cba7db96581343e3cbd8e5eb067026efb8cac24e
Author: Emmanuele Bassi <ebassi linux intel com>
Date: Mon Oct 26 22:36:01 2009 +0000
object: Guarantee insertion order
When iterating over the members of a JsonObject, or when retrieving
the list of members, the insertion order should be preserved by the
JsonObject. This is simply implemented by keeping a mirror list of
the member names.
Apparently, though JSON does not guarantee any ordering, it is somewhat
expected by JSON (and ECMAScript) users.
json-glib/json-object.c | 67 +++++++++++++++++++++-------------------
json-glib/json-types-private.h | 3 ++
tests/test-generator.c | 3 +-
3 files changed, 40 insertions(+), 33 deletions(-)
---
diff --git a/json-glib/json-object.c b/json-glib/json-object.c
index 69f9d15..862cd0e 100644
--- a/json-glib/json-object.c
+++ b/json-glib/json-object.c
@@ -123,7 +123,9 @@ json_object_unref (JsonObject *object)
g_atomic_int_compare_and_exchange (&object->ref_count, old_ref, old_ref - 1);
else
{
+ g_list_free (object->members_ordered);
g_hash_table_destroy (object->members);
+ object->members_ordered = NULL;
object->members = NULL;
g_slice_free (JsonObject, object);
@@ -135,9 +137,12 @@ object_set_member_internal (JsonObject *object,
const gchar *member_name,
JsonNode *node)
{
- g_hash_table_replace (object->members,
- g_strdup (member_name),
- node);
+ gchar *name = g_strdup (member_name);
+
+ if (g_hash_table_lookup (object->members, name) == NULL)
+ object->members_ordered = g_list_prepend (object->members_ordered, name);
+
+ g_hash_table_replace (object->members, name, node);
}
/**
@@ -459,9 +464,13 @@ g_hash_table_get_values (GHashTable *hash_table)
GList *
json_object_get_members (JsonObject *object)
{
+ GList *copy;
+
g_return_val_if_fail (object != NULL, NULL);
- return g_hash_table_get_keys (object->members);
+ copy = g_list_copy (object->members_ordered);
+
+ return g_list_reverse (copy);
}
/**
@@ -795,32 +804,23 @@ void
json_object_remove_member (JsonObject *object,
const gchar *member_name)
{
+ GList *l;
+
g_return_if_fail (object != NULL);
g_return_if_fail (member_name != NULL);
- g_hash_table_remove (object->members, member_name);
-}
-
-typedef struct _ForeachClosure ForeachClosure;
-
-struct _ForeachClosure
-{
- JsonObject *object;
-
- JsonObjectForeach func;
- gpointer data;
-};
+ for (l = object->members_ordered; l != NULL; l = l->next)
+ {
+ const gchar *name = l->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;
+ if (g_strcmp0 (name, member_name) == 0)
+ {
+ object->members_ordered = g_list_delete_link (object->members_ordered, l);
+ break;
+ }
+ }
- clos->func (clos->object, member_name, member_node, clos->data);
+ g_hash_table_remove (object->members, member_name);
}
/**
@@ -843,15 +843,18 @@ json_object_foreach_member (JsonObject *object,
JsonObjectForeach func,
gpointer data)
{
- ForeachClosure clos;
+ GList *members, *l;
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);
+ /* the list is stored in reverse order to have constant time additions */
+ members = g_list_last (object->members_ordered);
+ for (l = members; l != NULL; l = l->prev)
+ {
+ const gchar *member_name = l->data;
+ JsonNode *member_node = g_hash_table_lookup (object->members, member_name);
+
+ func (object, member_name, member_node, data);
+ }
}
diff --git a/json-glib/json-types-private.h b/json-glib/json-types-private.h
index b59151b..ac72316 100644
--- a/json-glib/json-types-private.h
+++ b/json-glib/json-types-private.h
@@ -53,6 +53,9 @@ struct _JsonObject
{
GHashTable *members;
+ /* the members of the object, ordered in reverse */
+ GList *members_ordered;
+
volatile gint ref_count;
};
diff --git a/tests/test-generator.c b/tests/test-generator.c
index e5671c2..6aa7dc6 100644
--- a/tests/test-generator.c
+++ b/tests/test-generator.c
@@ -196,11 +196,12 @@ test_simple_object (void)
data = json_generator_to_data (generator, &len);
if (g_test_verbose ())
- g_print ("checking simple array `%s' (expected: %s)\n",
+ g_print ("checking simple object `%s' (expected: %s)\n",
data,
simple_object);
g_assert_cmpint (len, ==, strlen (simple_object));
+ g_assert_cmpstr (data, ==, simple_object);
/* we cannot compare the strings literal because JsonObject does not
* guarantee any ordering
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]