| 1133 | } |
| 1134 | |
| 1135 | void destroy(value_t t) |
| 1136 | { |
| 1137 | if (t == value_t::array || t == value_t::object) |
| 1138 | { |
| 1139 | // flatten the current json_value to a heap-allocated stack |
| 1140 | std::vector<basic_json> stack; |
| 1141 | |
| 1142 | // move the top-level items to stack |
| 1143 | if (t == value_t::array) |
| 1144 | { |
| 1145 | stack.reserve(array->size()); |
| 1146 | std::move(array->begin(), array->end(), std::back_inserter(stack)); |
| 1147 | } |
| 1148 | else |
| 1149 | { |
| 1150 | stack.reserve(object->size()); |
| 1151 | for (auto&& it : *object) |
| 1152 | { |
| 1153 | stack.push_back(std::move(it.second)); |
| 1154 | } |
| 1155 | } |
| 1156 | |
| 1157 | while (!stack.empty()) |
| 1158 | { |
| 1159 | // move the last item to local variable to be processed |
| 1160 | basic_json current_item(std::move(stack.back())); |
| 1161 | stack.pop_back(); |
| 1162 | |
| 1163 | // if current_item is array/object, move |
| 1164 | // its children to the stack to be processed later |
| 1165 | if (current_item.is_array()) |
| 1166 | { |
| 1167 | std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack)); |
| 1168 | |
| 1169 | current_item.m_value.array->clear(); |
| 1170 | } |
| 1171 | else if (current_item.is_object()) |
| 1172 | { |
| 1173 | for (auto&& it : *current_item.m_value.object) |
| 1174 | { |
| 1175 | stack.push_back(std::move(it.second)); |
| 1176 | } |
| 1177 | |
| 1178 | current_item.m_value.object->clear(); |
| 1179 | } |
| 1180 | |
| 1181 | // it's now safe that current_item get destructed |
| 1182 | // since it doesn't have any children |
| 1183 | } |
| 1184 | } |
| 1185 | |
| 1186 | switch (t) |
| 1187 | { |
| 1188 | case value_t::object: |
| 1189 | { |
| 1190 | AllocatorType<object_t> alloc; |
| 1191 | std::allocator_traits<decltype(alloc)>::destroy(alloc, object); |
| 1192 | std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1); |