aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetri Lehtinen <petri@digip.org>2015-08-26 17:32:55 +0300
committerPetri Lehtinen <petri@digip.org>2015-08-26 17:32:55 +0300
commit4c4f692bd6814e598c9aa538a3c9979cdf05d566 (patch)
tree23ce6dcfa5e465d32c9af5c7edf73855320a419e
parentfef27e6d3efa755a75888db1167f34fa80695b9e (diff)
downloadjansson-4c4f692bd6814e598c9aa538a3c9979cdf05d566.zip
jansson-4c4f692bd6814e598c9aa538a3c9979cdf05d566.tar.gz
jansson-4c4f692bd6814e598c9aa538a3c9979cdf05d566.tar.bz2
Add json_object_foreach_safe
Fixes #230.
-rw-r--r--doc/apiref.rst13
-rw-r--r--src/jansson.h7
-rw-r--r--test/suites/api/test_object.c19
3 files changed, 39 insertions, 0 deletions
diff --git a/doc/apiref.rst b/doc/apiref.rst
index 7cd2483..fce1cb2 100644
--- a/doc/apiref.rst
+++ b/doc/apiref.rst
@@ -676,6 +676,10 @@ in an object.
The items are not returned in any particular order.
+ **Note:** It's not safe to call ``json_object_del(object, key)``
+ during iteration. If you need to, use
+ :func:`json_object_foreach_safe` instead.
+
This macro expands to an ordinary ``for`` statement upon
preprocessing, so its performance is equivalent to that of
hand-written iteration code using the object iteration protocol
@@ -686,6 +690,15 @@ in an object.
.. versionadded:: 2.3
+.. function:: json_object_foreach_safe(object, tmp, key, value)
+
+ Like :func:`json_object_foreach()`, but it's safe to call
+ ``json_object_del(object, key)`` during iteration. You need to pass
+ an extra ``void *`` parameter ``tmp`` that is used for temporary storage.
+
+ .. versionadded:: 2.8
+
+
The following functions implement an iteration protocol for objects,
allowing to iterate through all key-value pairs in an object. The
items are not returned in any particular order, as this would require
diff --git a/src/jansson.h b/src/jansson.h
index b980e8c..6f7fd07 100644
--- a/src/jansson.h
+++ b/src/jansson.h
@@ -152,6 +152,13 @@ int json_object_iter_set_new(json_t *object, void *iter, json_t *value);
key && (value = json_object_iter_value(json_object_key_to_iter(key))); \
key = json_object_iter_key(json_object_iter_next(object, json_object_key_to_iter(key))))
+#define json_object_foreach_safe(object, n, key, value) \
+ for(key = json_object_iter_key(json_object_iter(object)), \
+ n = json_object_iter_next(object, json_object_key_to_iter(key)); \
+ key && (value = json_object_iter_value(json_object_key_to_iter(key))); \
+ key = json_object_iter_key(n), \
+ n = json_object_iter_next(object, json_object_key_to_iter(key)))
+
#define json_array_foreach(array, index, value) \
for(index = 0; \
index < json_array_size(array) && (value = json_array_get(array, index)); \
diff --git a/test/suites/api/test_object.c b/test/suites/api/test_object.c
index c7acb40..01cc8fd 100644
--- a/test/suites/api/test_object.c
+++ b/test/suites/api/test_object.c
@@ -545,6 +545,24 @@ static void test_object_foreach()
json_decref(object2);
}
+static void test_object_foreach_safe()
+{
+ const char *key;
+ void *tmp;
+ json_t *object, *value;
+
+ object = json_pack("{sisisi}", "foo", 1, "bar", 2, "baz", 3);
+
+ json_object_foreach_safe(object, tmp, key, value) {
+ json_object_del(object, key);
+ }
+
+ if(json_object_size(object) != 0)
+ fail("json_object_foreach_safe failed to iterate all key-value pairs");
+
+ json_decref(object);
+}
+
static void run_tests()
{
test_misc();
@@ -557,4 +575,5 @@ static void run_tests()
test_iterators();
test_preserve_order();
test_object_foreach();
+ test_object_foreach_safe();
}