[json-glib] object: Add JsonObjectIter to ease iteration over JsonObject members
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [json-glib] object: Add JsonObjectIter to ease iteration over JsonObject members
- Date: Tue, 6 Oct 2015 07:31:55 +0000 (UTC)
commit d231976e240f2244c60df26a1a6600ecb325506a
Author: Philip Withnall <philip withnall collabora co uk>
Date: Thu Sep 24 11:06:34 2015 +0100
object: Add JsonObjectIter to ease iteration over JsonObject members
This is a stack-allocated iterator object similar to GHashTableIter
which allows allocation-free iteration over the members in a JsonObject.
It differs from json_object_foreach_member() in the order in which it
iterates — for JsonObjectIter the order is undefined.
https://bugzilla.gnome.org/show_bug.cgi?id=755509
doc/reference/json-glib-sections.txt | 3 +
json-glib/json-object.c | 71 ++++++++++++++++++++++++++++++++++
json-glib/json-types-private.h | 9 ++++
json-glib/json-types.h | 26 ++++++++++++
json-glib/tests/object.c | 28 +++++++++++++
5 files changed, 137 insertions(+), 0 deletions(-)
---
diff --git a/doc/reference/json-glib-sections.txt b/doc/reference/json-glib-sections.txt
index ab5e579..015a442 100644
--- a/doc/reference/json-glib-sections.txt
+++ b/doc/reference/json-glib-sections.txt
@@ -18,6 +18,9 @@ json_object_get_size
json_object_remove_member
JsonObjectForeach
json_object_foreach_member
+JsonObjectIter
+json_object_iter_init
+json_object_iter_next
<SUBSECTION>
json_object_set_array_member
diff --git a/json-glib/json-object.c b/json-glib/json-object.c
index c71d8f9..cc32148 100644
--- a/json-glib/json-object.c
+++ b/json-glib/json-object.c
@@ -851,3 +851,74 @@ json_object_foreach_member (JsonObject *object,
func (object, member_name, member_node, data);
}
}
+
+/**
+ * json_object_iter_init:
+ * @iter: an uninitialised #JsonObjectIter
+ * @object: the #JsonObject to iterate over
+ *
+ * Initialise the @iter and associate it with @object.
+ *
+ * |[<!-- language="C" -->
+ * JsonObjectIter iter;
+ * const gchar *member_name;
+ * JsonNode *member_node;
+ *
+ * json_object_iter_init (&iter, some_object);
+ * while (json_object_iter_next (&iter, &member_name, &member_node))
+ * {
+ * // Do something with @member_name and @member_node.
+ * }
+ * ]|
+ *
+ * Since: UNRELEASED
+ */
+void
+json_object_iter_init (JsonObjectIter *iter,
+ JsonObject *object)
+{
+ JsonObjectIterReal *iter_real = (JsonObjectIterReal *) iter;;
+
+ g_return_if_fail (iter != NULL);
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (object->ref_count > 0);
+
+ iter_real->object = object;
+ g_hash_table_iter_init (&iter_real->members_iter, object->members);
+}
+
+/**
+ * json_object_iter_next:
+ * @iter: a #JsonObjectIter
+ * @member_name: (out callee-allocates) (transfer none) (optional): return
+ * location for the member name, or %NULL to ignore
+ * @member_node: (out callee-allocates) (transfer none) (optional): return
+ * location for the member value, or %NULL to ignore
+ *
+ * Advance @iter and retrieve the next member in the object. If the end of the
+ * object is reached, %FALSE is returned and @member_name and @member_node are
+ * set to invalid values. After that point, the @iter is invalid.
+ *
+ * The order in which members are returned by the iterator is undefined. The
+ * iterator is invalidated if its #JsonObject is modified during iteration.
+ *
+ * Returns: %TRUE if @member_name and @member_node are valid; %FALSE if the end
+ * of the object has been reached
+ *
+ * Since: UNRELEASED
+ */
+gboolean
+json_object_iter_next (JsonObjectIter *iter,
+ const gchar **member_name,
+ JsonNode **member_node)
+{
+ JsonObjectIterReal *iter_real = (JsonObjectIterReal *) iter;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (iter_real->object != NULL, FALSE);
+ g_return_val_if_fail (iter_real->object->ref_count > 0, FALSE);
+
+ return g_hash_table_iter_next (&iter_real->members_iter,
+ (gpointer *) member_name,
+ (gpointer *) member_node);
+}
diff --git a/json-glib/json-types-private.h b/json-glib/json-types-private.h
index efce6a9..f9ac064 100644
--- a/json-glib/json-types-private.h
+++ b/json-glib/json-types-private.h
@@ -95,6 +95,15 @@ struct _JsonObject
volatile gint ref_count;
};
+typedef struct
+{
+ JsonObject *object; /* unowned */
+ GHashTableIter members_iter; /* iterator over @members */
+ gpointer padding[2]; /* for future expansion */
+} JsonObjectIterReal;
+
+G_STATIC_ASSERT (sizeof (JsonObjectIterReal) == sizeof (JsonObjectIter));
+
G_GNUC_INTERNAL
const gchar * json_node_type_get_name (JsonNodeType node_type);
G_GNUC_INTERNAL
diff --git a/json-glib/json-types.h b/json-glib/json-types.h
index 9acc23b..36519c3 100644
--- a/json-glib/json-types.h
+++ b/json-glib/json-types.h
@@ -368,6 +368,32 @@ void json_object_foreach_member (JsonObject *object,
JsonObjectForeach func,
gpointer data);
+/**
+ * JsonObjectIter:
+ *
+ * An iterator used to iterate over the members of a #JsonObject. This must
+ * be allocated on the stack and initialised using json_object_iter_init().
+ * The order in which members are returned by the iterator is undefined. The
+ * iterator is invalidated if its #JsonObject is modified during iteration.
+ *
+ * All the fields in the #JsonObjectIter structure are private and should
+ * never be accessed directly.
+ *
+ * Since: UNRELEASED
+ */
+typedef struct {
+ /*< private >*/
+ gpointer priv[8];
+} JsonObjectIter;
+
+JSON_AVAILABLE_IN_1_2
+void json_object_iter_init (JsonObjectIter *iter,
+ JsonObject *object);
+JSON_AVAILABLE_IN_1_2
+gboolean json_object_iter_next (JsonObjectIter *iter,
+ const gchar **member_name,
+ JsonNode **member_node);
+
JSON_AVAILABLE_IN_1_0
GType json_array_get_type (void) G_GNUC_CONST;
JSON_AVAILABLE_IN_1_0
diff --git a/json-glib/tests/object.c b/json-glib/tests/object.c
index f109464..54b5934 100644
--- a/json-glib/tests/object.c
+++ b/json-glib/tests/object.c
@@ -140,6 +140,33 @@ test_foreach_member (void)
}
static void
+test_iter (void)
+{
+ JsonObject *object = NULL;
+ TestForeachFixture fixture = { 0, };
+ JsonObjectIter iter;
+ const gchar *member_name;
+ JsonNode *member_node;
+
+ object = json_object_new ();
+
+ json_object_set_int_member (object, "integer", 42);
+ json_object_set_boolean_member (object, "boolean", TRUE);
+ json_object_set_string_member (object, "string", "hello");
+ json_object_set_double_member (object, "double", 3.14159);
+ json_object_set_null_member (object, "null");
+
+ json_object_iter_init (&iter, object);
+
+ while (json_object_iter_next (&iter, &member_name, &member_node))
+ verify_foreach (object, member_name, member_node, &fixture);
+
+ g_assert_cmpint (fixture.n_members, ==, json_object_get_size (object));
+
+ json_object_unref (object);
+}
+
+static void
test_empty_member (void)
{
JsonObject *object = json_object_new ();
@@ -173,6 +200,7 @@ main (int argc,
g_test_add_func ("/object/set-member", test_set_member);
g_test_add_func ("/object/remove-member", test_remove_member);
g_test_add_func ("/object/foreach-member", test_foreach_member);
+ g_test_add_func ("/object/iter", test_iter);
g_test_add_func ("/object/empty-member", test_empty_member);
return g_test_run ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]