| 288 | |
| 289 | |
| 290 | void RocksDbSerializer::write_non_streaming_() { |
| 291 | // Build a map of instances and their references/dependencies |
| 292 | std::map<uint32_t, std::set<uint32_t>> dependencies, dependencies_inv; |
| 293 | std::visit([&dependencies](const auto& m) { |
| 294 | if constexpr (std::is_same_v<std::decay_t<decltype(m)>, IfcParse::impl::in_memory_file_storage>) { |
| 295 | for (const auto& ps : m.byref_excl_) { |
| 296 | for (const auto& p : ps.second) { |
| 297 | dependencies[p].insert(std::get<0>(ps.first)); |
| 298 | } |
| 299 | } |
| 300 | } |
| 301 | }, std::get<IfcParse::IfcFile*>(file_)->storage_); |
| 302 | // Add bottom-rank nodes, inv mapping does not contain them |
| 303 | for (const auto& p : *std::get<IfcParse::IfcFile*>(file_)) { |
| 304 | dependencies[p.first]; |
| 305 | } |
| 306 | |
| 307 | for (auto& ps : dependencies) { |
| 308 | for (auto& p : ps.second) { |
| 309 | dependencies_inv[p].insert(ps.first); |
| 310 | } |
| 311 | } |
| 312 | |
| 313 | // Do a topological sort over the nodes |
| 314 | std::vector<uint32_t> deps_topo_order; |
| 315 | while (dependencies.size() > 0) { |
| 316 | std::vector<uint32_t> no_deps; |
| 317 | for (auto& ps : dependencies) { |
| 318 | if (ps.second.size() == 0) { |
| 319 | no_deps.push_back(ps.first); |
| 320 | } |
| 321 | } |
| 322 | |
| 323 | if (no_deps.size() == 0) { |
| 324 | throw std::runtime_error("cyclic dependencies in model, unable to serialize"); |
| 325 | } |
| 326 | |
| 327 | for (auto& i : no_deps) { |
| 328 | deps_topo_order.push_back(i); |
| 329 | } |
| 330 | |
| 331 | // mutate mapping |
| 332 | for (auto& i : no_deps) { |
| 333 | dependencies.erase(i); |
| 334 | } |
| 335 | for (auto& i : no_deps) { |
| 336 | for (auto& j : dependencies_inv[i]) { |
| 337 | auto it = dependencies.find(j); |
| 338 | if (it != dependencies.end()) { |
| 339 | it->second.erase(i); |
| 340 | } |
| 341 | } |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | // Add them in topological order, so that add() never recurses into something not previously visited |
| 346 | for (auto& i : deps_topo_order) { |
| 347 | output_file_->addEntity(std::get<IfcParse::IfcFile*>(file_)->instance_by_id(i), i); |