mirror of
https://github.com/nlohmann/json.git
synced 2026-11-02 19:05:35 +00:00
Make basic_json::insert() provide its documented strong exception guarantee (#5986)
A failed allocation while the new elements were copied left the value changed, and with JSON_DIAGNOSTICS stale parent pointers behind. The extra work now happens almost only on the failure path: - Array insert(pos, cnt, val) and insert(pos, first, last) append the copies at the end and rotate them into place. If a copy throws, the appended elements are erased again (noexcept) and the parents are set. Moving a basic_json cannot throw, so reallocation is safe. This is no slower than vector::insert (faster for numbers), needs no temporary array, and keeps the elements that libstdc++ lost on reallocation. - Array insert(pos, val) copies a non-scalar value first and inserts it by move, except at the end, where vector::insert is strong. Scalars keep the direct path. - The object range insert(first, last) into an empty object uses the container's own range insertion and clears the object on an exception. Into a non-empty object it inserts member by member and logs one bit per source member (a new member is detected by the size change; no allocation for the first 256 members); on an exception the members added are erased by walking the source range. No assumption that key_type is string_t. - The parents are set when a failed insertion is undone. The regression test fails every allocation of every insert() overload in turn, for json and ordered_json, and checks the value and its parents. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
4 files changed
+790
-37
No files matched your search
@@ -65,7 +65,9 @@ the same index, which is now a different value.
|
||||
|
||||
## Exception safety
|
||||
|
||||
Strong exception safety: if an exception occurs, the original value stays intact.
|
||||
Strong exception safety: if an exception occurs, the original value stays intact. This includes an exception thrown
|
||||
while the new elements are copied (for example, `std::bad_alloc`): elements and members that were already added
|
||||
are removed again.
|
||||
|
||||
## Exceptions
|
||||
|
||||
|
||||
Reference in new issue
Block a user