|
29 | 29 | #include <memory> // unique_ptr |
30 | 30 | #include <string> // string, stoi, to_string |
31 | 31 | #include <utility> // declval, forward, move, pair, swap |
| 32 | +#ifdef _MSC_VER |
| 33 | + #include <vcruntime.h> // _HAS_EXCEPTIONS |
| 34 | +#endif |
32 | 35 | #include <vector> // vector |
33 | 36 |
|
34 | 37 | // #include <nlohmann/adl_serializer.hpp> |
@@ -20567,51 +20570,65 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec |
20567 | 20570 | } |
20568 | 20571 | if (t == value_t::array || t == value_t::object) |
20569 | 20572 | { |
20570 | | - // flatten the current json_value to a heap-allocated stack |
20571 | | - std::vector<basic_json> stack; |
20572 | | - |
20573 | | - // move the top-level items to stack |
20574 | | - if (t == value_t::array) |
20575 | | - { |
20576 | | - stack.reserve(array->size()); |
20577 | | - std::move(array->begin(), array->end(), std::back_inserter(stack)); |
20578 | | - } |
20579 | | - else |
| 20573 | +#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) |
| 20574 | + try |
20580 | 20575 | { |
20581 | | - stack.reserve(object->size()); |
20582 | | - for (auto&& it : *object) |
20583 | | - { |
20584 | | - stack.push_back(std::move(it.second)); |
20585 | | - } |
20586 | | - } |
20587 | | - |
20588 | | - while (!stack.empty()) |
20589 | | - { |
20590 | | - // move the last item to local variable to be processed |
20591 | | - basic_json current_item(std::move(stack.back())); |
20592 | | - stack.pop_back(); |
| 20576 | +#endif |
| 20577 | + // flatten the current json_value to a heap-allocated stack |
| 20578 | + std::vector<basic_json, allocator_type> stack; |
20593 | 20579 |
|
20594 | | - // if current_item is array/object, move |
20595 | | - // its children to the stack to be processed later |
20596 | | - if (current_item.is_array()) |
| 20580 | + // move the top-level items to stack |
| 20581 | + if (t == value_t::array) |
20597 | 20582 | { |
20598 | | - std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack)); |
20599 | | - |
20600 | | - current_item.m_data.m_value.array->clear(); |
| 20583 | + stack.reserve(array->size()); |
| 20584 | + std::move(array->begin(), array->end(), std::back_inserter(stack)); |
20601 | 20585 | } |
20602 | | - else if (current_item.is_object()) |
| 20586 | + else |
20603 | 20587 | { |
20604 | | - for (auto&& it : *current_item.m_data.m_value.object) |
| 20588 | + stack.reserve(object->size()); |
| 20589 | + for (auto&& it : *object) |
20605 | 20590 | { |
20606 | 20591 | stack.push_back(std::move(it.second)); |
20607 | 20592 | } |
20608 | | - |
20609 | | - current_item.m_data.m_value.object->clear(); |
20610 | 20593 | } |
20611 | 20594 |
|
20612 | | - // it's now safe that current_item get destructed |
20613 | | - // since it doesn't have any children |
| 20595 | + while (!stack.empty()) |
| 20596 | + { |
| 20597 | + // move the last item to local variable to be processed |
| 20598 | + basic_json current_item(std::move(stack.back())); |
| 20599 | + stack.pop_back(); |
| 20600 | + |
| 20601 | + // if current_item is array/object, move |
| 20602 | + // its children to the stack to be processed later |
| 20603 | + if (current_item.is_array()) |
| 20604 | + { |
| 20605 | + std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack)); |
| 20606 | + |
| 20607 | + current_item.m_data.m_value.array->clear(); |
| 20608 | + } |
| 20609 | + else if (current_item.is_object()) |
| 20610 | + { |
| 20611 | + for (auto&& it : *current_item.m_data.m_value.object) |
| 20612 | + { |
| 20613 | + stack.push_back(std::move(it.second)); |
| 20614 | + } |
| 20615 | + |
| 20616 | + current_item.m_data.m_value.object->clear(); |
| 20617 | + } |
| 20618 | + |
| 20619 | + // it's now safe that current_item get destructed |
| 20620 | + // since it doesn't have any children |
| 20621 | + } |
| 20622 | +#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) |
20614 | 20623 | } |
| 20624 | + catch (...) // NOLINT(bugprone-empty-catch) |
| 20625 | + { |
| 20626 | + // Recursion avoidance has issue allocating temporary space. This may have been `std::bad_alloc` |
| 20627 | + // or any other exception thrown by a custom allocator. |
| 20628 | + // RAII will correctly clean up anything moved into `stack`. |
| 20629 | + // Then we continue with regular recursion based destroy, which will not heap allocate. |
| 20630 | + } |
| 20631 | +#endif |
20615 | 20632 | } |
20616 | 20633 |
|
20617 | 20634 | switch (t) |
|
0 commit comments