mirror of
https://github.com/json-c/json-c.git
synced 2026-06-14 06:59:06 +08:00
Issue #927: update the documentation for json_object_iterator to clarify that any change of the fields present on the object being iterated invalidates the iterator.
Update the test to show what kind of changes _are_ allowed.
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
* @file json_object_iterator.h
|
* @file json_object_iterator.h
|
||||||
*
|
*
|
||||||
* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
|
* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
|
||||||
|
* Copyright (c) 2026 Eric Hawicz
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the MIT license. See COPYING for details.
|
* it under the terms of the MIT license. See COPYING for details.
|
||||||
@@ -37,6 +38,12 @@ extern "C" {
|
|||||||
struct json_object_iterator
|
struct json_object_iterator
|
||||||
{
|
{
|
||||||
const void *opaque_;
|
const void *opaque_;
|
||||||
|
// These could be used to make an interator that fails "faster"
|
||||||
|
// in the face of certain changes to the underlying object, but
|
||||||
|
// would still be vulnerable to skipping entries.
|
||||||
|
// Changing this structure size is an ABI change
|
||||||
|
// const lh_table *table;
|
||||||
|
// size_t begin_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,10 +75,20 @@ struct json_object;
|
|||||||
*/
|
*/
|
||||||
JSON_EXPORT struct json_object_iterator json_object_iter_init_default(void);
|
JSON_EXPORT struct json_object_iterator json_object_iter_init_default(void);
|
||||||
|
|
||||||
/** Retrieves an iterator to the first pair of the JSON Object.
|
/** Retrieves an iterator to the first key/value pair of the JSON Object.
|
||||||
*
|
*
|
||||||
* @warning Any modification of the underlying pair invalidates all
|
* @warning Any modification of the fields present on the object
|
||||||
* iterators to that pair.
|
* invalidates all iterators on that object, regardless of
|
||||||
|
* what key/value pair they are pointing to, other than the
|
||||||
|
* end iterator.
|
||||||
|
* Modifications include adding or removing any pair, even if
|
||||||
|
* set of keys appears unchanged after the modification.
|
||||||
|
* Modifying *values* is allowed, including replacing a value
|
||||||
|
* by calling json_object_add(), provided the key already exists.
|
||||||
|
* Attempting to use an invalidated iterator in any way, other
|
||||||
|
* than comparing it to the end iterator, is *undefined behavior*.
|
||||||
|
* Passing such an iterator to any of the the json_object_iterator
|
||||||
|
* functions is not even guaranteed to fail in any consistent way.
|
||||||
*
|
*
|
||||||
* @param obj JSON Object instance (MUST be of type json_object)
|
* @param obj JSON Object instance (MUST be of type json_object)
|
||||||
*
|
*
|
||||||
@@ -133,8 +150,9 @@ JSON_EXPORT struct json_object_iterator json_object_iter_end(const struct json_o
|
|||||||
|
|
||||||
/** Returns an iterator to the next pair, if any
|
/** Returns an iterator to the next pair, if any
|
||||||
*
|
*
|
||||||
* @warning Any modification of the underlying pair
|
* @warning Any modification of the fields of the object invalidates
|
||||||
* invalidates all iterators to that pair.
|
* the iterator, see the warning on json_object_iter_begin()
|
||||||
|
* for details.
|
||||||
*
|
*
|
||||||
* @param iter [IN/OUT] Pointer to iterator that references a
|
* @param iter [IN/OUT] Pointer to iterator that references a
|
||||||
* name/value pair; MUST be a valid, non-end iterator.
|
* name/value pair; MUST be a valid, non-end iterator.
|
||||||
@@ -154,8 +172,9 @@ JSON_EXPORT void json_object_iter_next(struct json_object_iterator *iter);
|
|||||||
* @param iter pointer to iterator that references a name/value
|
* @param iter pointer to iterator that references a name/value
|
||||||
* pair; MUST be a valid, non-end iterator.
|
* pair; MUST be a valid, non-end iterator.
|
||||||
*
|
*
|
||||||
* @warning bad things will happen if an invalid or
|
* @warning bad things will happen if an invalid or "end" iterator
|
||||||
* "end" iterator is passed.
|
* is passed. See the warning on json_object_iter_begin()
|
||||||
|
* for details.
|
||||||
*
|
*
|
||||||
* @return const char* Pointer to the name of the referenced
|
* @return const char* Pointer to the name of the referenced
|
||||||
* name/value pair. The name memory belongs to the
|
* name/value pair. The name memory belongs to the
|
||||||
@@ -172,8 +191,9 @@ JSON_EXPORT const char *json_object_iter_peek_name(const struct json_object_iter
|
|||||||
* @param iter pointer to iterator that references a name/value
|
* @param iter pointer to iterator that references a name/value
|
||||||
* pair; MUST be a valid, non-end iterator.
|
* pair; MUST be a valid, non-end iterator.
|
||||||
*
|
*
|
||||||
* @warning bad things will happen if invalid or
|
* @warning bad things will happen if an invalid or "end" iterator
|
||||||
* "end" iterator is passed.
|
* is passed. See the warning on json_object_iter_begin()
|
||||||
|
* for details.
|
||||||
*
|
*
|
||||||
* @return struct json_object* Pointer to the json-c value
|
* @return struct json_object* Pointer to the json-c value
|
||||||
* instance of the referenced name/value pair; the
|
* instance of the referenced name/value pair; the
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#undef NDEBUG
|
#undef NDEBUG
|
||||||
#endif
|
#endif
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -20,6 +21,7 @@ int main(int atgc, char **argv)
|
|||||||
\"boolean_false\": false,\n\
|
\"boolean_false\": false,\n\
|
||||||
\"big_number\": 2147483649,\n\
|
\"big_number\": 2147483649,\n\
|
||||||
\"a_null\": null,\n\
|
\"a_null\": null,\n\
|
||||||
|
\"an_object\": { \"foo\": \"bar\" },\n\
|
||||||
}";
|
}";
|
||||||
|
|
||||||
struct json_object *new_obj;
|
struct json_object *new_obj;
|
||||||
@@ -31,10 +33,41 @@ int main(int atgc, char **argv)
|
|||||||
it = json_object_iter_begin(new_obj);
|
it = json_object_iter_begin(new_obj);
|
||||||
itEnd = json_object_iter_end(new_obj);
|
itEnd = json_object_iter_end(new_obj);
|
||||||
|
|
||||||
|
// If this changes size on any platform, it'd break the ABI
|
||||||
|
printf("sizeof(struct json_object_iterator)/sizeof(void *)=%zu\n", sizeof(struct json_object_iterator) / sizeof(void *));
|
||||||
|
|
||||||
while (!json_object_iter_equal(&it, &itEnd))
|
while (!json_object_iter_equal(&it, &itEnd))
|
||||||
{
|
{
|
||||||
printf("%s\n", json_object_iter_peek_name(&it));
|
const char *key = json_object_iter_peek_name(&it);
|
||||||
printf("%s\n", json_object_to_json_string(json_object_iter_peek_value(&it)));
|
json_object *value = json_object_iter_peek_value(&it);
|
||||||
|
printf("key: %s\n", key);
|
||||||
|
printf("pre change: %s\n", json_object_to_json_string(value));
|
||||||
|
if (json_object_get_type(value) == json_type_object)
|
||||||
|
{
|
||||||
|
// Changing sub-objects is ok
|
||||||
|
assert(json_object_object_add(value, "foo", json_object_new_string("change foo")) == 0);
|
||||||
|
assert(json_object_object_add(value, "newkey", json_object_new_string("new value")) == 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Changing the value of pairs is ok
|
||||||
|
assert(json_object_object_add(new_obj, key, json_object_new_string("switched")) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0) // DO NOT DO THIS
|
||||||
|
{
|
||||||
|
// Adding new keys is NOT ok, and invalidates the iterator
|
||||||
|
json_object_object_add(value, "somenewkey", json_object_new_string("foo"));
|
||||||
|
|
||||||
|
// Deleting any keys ALSO invalidates the iterator, even if
|
||||||
|
// the key is immediately re-added.
|
||||||
|
json_object_object_del(value, key);
|
||||||
|
json_object_object_add(value, key, json_object_new_string("switched"));
|
||||||
|
}
|
||||||
|
|
||||||
|
value = json_object_iter_peek_value(&it);
|
||||||
|
printf("post change: %s\n", json_object_to_json_string(value));
|
||||||
|
|
||||||
json_object_iter_next(&it);
|
json_object_iter_next(&it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user