@@ -20567,51 +20567,65 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
2056720567 }
2056820568 if (t == value_t::array || t == value_t::object)
2056920569 {
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
20580- {
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())
20570+ #ifdef __cpp_exceptions
20571+ try
2058920572 {
20590- // move the last item to local variable to be processed
20591- basic_json current_item(std::move( stack.back()));
20592- stack.pop_back() ;
20573+ #endif
20574+ // flatten the current json_value to a heap-allocated stack
20575+ std::vector<basic_json, allocator_type> stack;
2059320576
20594- // if current_item is array/object, move
20595- // its children to the stack to be processed later
20596- if (current_item.is_array())
20577+ // move the top-level items to stack
20578+ if (t == value_t::array)
2059720579 {
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();
20580+ stack.reserve(array->size());
20581+ std::move(array->begin(), array->end(), std::back_inserter(stack));
2060120582 }
20602- else if (current_item.is_object())
20583+ else
2060320584 {
20604- for (auto&& it : *current_item.m_data.m_value.object)
20585+ stack.reserve(object->size());
20586+ for (auto&& it : *object)
2060520587 {
2060620588 stack.push_back(std::move(it.second));
2060720589 }
20608-
20609- current_item.m_data.m_value.object->clear();
2061020590 }
2061120591
20612- // it's now safe that current_item get destructed
20613- // since it doesn't have any children
20592+ while (!stack.empty())
20593+ {
20594+ // move the last item to local variable to be processed
20595+ basic_json current_item(std::move(stack.back()));
20596+ stack.pop_back();
20597+
20598+ // if current_item is array/object, move
20599+ // its children to the stack to be processed later
20600+ if (current_item.is_array())
20601+ {
20602+ std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
20603+
20604+ current_item.m_data.m_value.array->clear();
20605+ }
20606+ else if (current_item.is_object())
20607+ {
20608+ for (auto&& it : *current_item.m_data.m_value.object)
20609+ {
20610+ stack.push_back(std::move(it.second));
20611+ }
20612+
20613+ current_item.m_data.m_value.object->clear();
20614+ }
20615+
20616+ // it's now safe that current_item get destructed
20617+ // since it doesn't have any children
20618+ }
20619+ #ifdef __cpp_exceptions
2061420620 }
20621+ catch (...) // NOLINT(bugprone-empty-catch)
20622+ {
20623+ // Recursion avoidance has issue allocating temporary space. This may have been `std::bad_alloc`
20624+ // or any other exception thrown by a custom allocator.
20625+ // RAII will correctly clean up anything moved into `stack`.
20626+ // Then we continue with regular recursion based destroy, which will not heap allocate.
20627+ }
20628+ #endif
2061520629 }
2061620630
2061720631 switch (t)
0 commit comments