| 558 | json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {} |
| 559 | |
| 560 | void destroy(value_t t) |
| 561 | { |
| 562 | if (t == value_t::array || t == value_t::object) |
| 563 | { |
| 564 | // flatten the current json_value to a heap-allocated stack |
| 565 | std::vector<basic_json> stack; |
| 566 | |
| 567 | // move the top-level items to stack |
| 568 | if (t == value_t::array) |
| 569 | { |
| 570 | stack.reserve(array->size()); |
| 571 | std::move(array->begin(), array->end(), std::back_inserter(stack)); |
| 572 | } |
| 573 | else |
| 574 | { |
| 575 | stack.reserve(object->size()); |
| 576 | for (auto&& it : *object) |
| 577 | { |
| 578 | stack.push_back(std::move(it.second)); |
| 579 | } |
| 580 | } |
| 581 | |
| 582 | while (!stack.empty()) |
| 583 | { |
| 584 | // move the last item to local variable to be processed |
| 585 | basic_json current_item(std::move(stack.back())); |
| 586 | stack.pop_back(); |
| 587 | |
| 588 | // if current_item is array/object, move |
| 589 | // its children to the stack to be processed later |
| 590 | if (current_item.is_array()) |
| 591 | { |
| 592 | std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack)); |
| 593 | |
| 594 | current_item.m_value.array->clear(); |
| 595 | } |
| 596 | else if (current_item.is_object()) |
| 597 | { |
| 598 | for (auto&& it : *current_item.m_value.object) |
| 599 | { |
| 600 | stack.push_back(std::move(it.second)); |
| 601 | } |
| 602 | |
| 603 | current_item.m_value.object->clear(); |
| 604 | } |
| 605 | |
| 606 | // it's now safe that current_item get destructed |
| 607 | // since it doesn't have any children |
| 608 | } |
| 609 | } |
| 610 | |
| 611 | switch (t) |
| 612 | { |
| 613 | case value_t::object: |
| 614 | { |
| 615 | AllocatorType<object_t> alloc; |
| 616 | std::allocator_traits<decltype(alloc)>::destroy(alloc, object); |
| 617 | std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1); |