diff options
Diffstat (limited to 'json-glib/json-object.c')
-rw-r--r-- | json-glib/json-object.c | 113 |
1 files changed, 111 insertions, 2 deletions
diff --git a/json-glib/json-object.c b/json-glib/json-object.c index 8e6b293..c67b687 100644 --- a/json-glib/json-object.c +++ b/json-glib/json-object.c @@ -62,7 +62,8 @@ json_object_new (void) JsonObject *object; object = g_slice_new0 (JsonObject); - + + object->age = 0; object->ref_count = 1; object->members = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, @@ -176,7 +177,10 @@ object_set_member_internal (JsonObject *object, gchar *name = g_strdup (member_name); if (g_hash_table_lookup (object->members, name) == NULL) - g_queue_push_tail (&object->members_ordered, name); + { + g_queue_push_tail (&object->members_ordered, name); + object->age += 1; + } else { GList *l; @@ -1120,6 +1124,12 @@ json_object_iter_init (JsonObjectIter *iter, * The order in which members are returned by the iterator is undefined. The * iterator is invalidated if its #JsonObject is modified during iteration. * + * You must use this function with a #JsonObjectIter initialized with + * json_object_iter_init(); using this function with an iterator initialized + * with json_object_iter_init_ordered() yields undefined behavior. + * + * See also: json_object_iter_next_ordered() + * * Returns: %TRUE if @member_name and @member_node are valid; %FALSE if the end * of the object has been reached * @@ -1140,3 +1150,102 @@ json_object_iter_next (JsonObjectIter *iter, (gpointer *) member_name, (gpointer *) member_node); } + +/** + * json_object_iter_init_ordered: + * @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_ordered (&iter, some_object); + * while (json_object_iter_next_ordered (&iter, &member_name, &member_node)) + * { + * // Do something with @member_name and @member_node. + * } + * ]| + * + * See also: json_object_iter_init() + * + * Since: 1.6 + */ +void +json_object_iter_init_ordered (JsonObjectIter *iter, + JsonObject *object) +{ + JsonObjectOrderedIterReal *iter_real = (JsonObjectOrderedIterReal *) 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; + iter_real->cur_member = NULL; + iter_real->next_member = NULL; + iter_real->age = iter_real->object->age; +} + +/** + * json_object_iter_next_ordered: + * @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 the same order in + * which the members were added to the #JsonObject. The iterator is invalidated + * if its #JsonObject is modified during iteration. + * + * You must use this function with a #JsonObjectIter initialized with + * json_object_iter_init_ordered(); using this function with an iterator initialized + * with json_object_iter_init() yields undefined behavior. + * + * See also: json_object_iter_next() + * + * Returns: %TRUE if @member_name and @member_node are valid; %FALSE if the end + * of the object has been reached + * + * Since: 1.6 + */ +gboolean +json_object_iter_next_ordered (JsonObjectIter *iter, + const gchar **member_name, + JsonNode **member_node) +{ + JsonObjectOrderedIterReal *iter_real = (JsonObjectOrderedIterReal *) iter; + const char *name = NULL; + + 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); + g_return_val_if_fail (iter_real->age == iter_real->object->age, FALSE); + + if (iter_real->cur_member == NULL) + iter_real->cur_member = iter_real->object->members_ordered.head; + else + iter_real->cur_member = iter_real->cur_member->next; + + name = iter_real->cur_member != NULL ? iter_real->cur_member->data : NULL; + + if (member_name != NULL) + *member_name = name; + if (member_node != NULL) + { + if (name != NULL) + *member_node = g_hash_table_lookup (iter_real->object->members, name); + else + *member_name = NULL; + } + + return iter_real->cur_member != NULL; +} |