From 4c4f692bd6814e598c9aa538a3c9979cdf05d566 Mon Sep 17 00:00:00 2001 From: Petri Lehtinen Date: Wed, 26 Aug 2015 17:32:55 +0300 Subject: Add json_object_foreach_safe Fixes #230. --- doc/apiref.rst | 13 +++++++++++++ src/jansson.h | 7 +++++++ test/suites/api/test_object.c | 19 +++++++++++++++++++ 3 files changed, 39 insertions(+) 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(); } -- cgit v1.1