| 2522 | } |
| 2523 | |
| 2524 | std::vector<int> IfcFile::get_inverse_indices(int instance_id) { |
| 2525 | std::vector<int> return_value; |
| 2526 | |
| 2527 | // Mapping of instance id to attribute offset. |
| 2528 | std::map<int, std::vector<int>> mapping; |
| 2529 | |
| 2530 | std::visit([&mapping, instance_id](const auto& x) { |
| 2531 | if constexpr (std::is_same_v<std::decay_t<decltype(x)>, std::monostate>) { |
| 2532 | } else if constexpr (std::is_same_v<std::decay_t<decltype(x)>, impl::in_memory_file_storage>) { |
| 2533 | auto lower = x.byref_excl_.lower_bound({ instance_id, -1, -1 }); |
| 2534 | auto upper = x.byref_excl_.upper_bound({ instance_id, std::numeric_limits<short>::max(), std::numeric_limits<short>::max() }); |
| 2535 | for (auto it = lower; it != upper; ++it) { |
| 2536 | for (auto& i : it->second) { |
| 2537 | mapping[i].push_back(std::get<2>(it->first)); |
| 2538 | } |
| 2539 | } |
| 2540 | } else if constexpr (std::is_same_v<std::decay_t<decltype(x)>, impl::rocks_db_file_storage>) { |
| 2541 | #ifdef IFOPSH_WITH_ROCKSDB |
| 2542 | // @todo no lower/upper_bounds() implemented yet |
| 2543 | auto prefix = "v|" + std::to_string(instance_id) + "|"; |
| 2544 | auto it = std::unique_ptr<rocksdb::Iterator>(x.db->NewIterator(rocksdb::ReadOptions())); |
| 2545 | it->Seek(prefix); |
| 2546 | while (it->Valid() && it->key().starts_with(prefix)) { |
| 2547 | std::vector<uint32_t> vals(it->value().size() / sizeof(uint32_t)); |
| 2548 | memcpy(vals.data(), it->value().data(), it->value().size()); |
| 2549 | auto tuple = key_from_string<std::tuple<int, int, int>>(it->key().ToString().substr(2)); |
| 2550 | for (auto& i : vals) { |
| 2551 | mapping[i].push_back(std::get<2>(tuple)); |
| 2552 | } |
| 2553 | it->Next(); |
| 2554 | } |
| 2555 | #endif |
| 2556 | } |
| 2557 | }, storage_); |
| 2558 | |
| 2559 | auto refs = instances_by_reference(instance_id); |
| 2560 | |
| 2561 | for (const auto& ref : *refs) { |
| 2562 | auto it = mapping.find(ref->id()); |
| 2563 | if (it == mapping.end() || it->second.empty()) { |
| 2564 | throw IfcException("Internal error"); |
| 2565 | } |
| 2566 | return_value.push_back(it->second.front()); |
| 2567 | it->second.erase(it->second.begin()); |
| 2568 | if (it->second.empty()) { |
| 2569 | mapping.erase(it); |
| 2570 | } |
| 2571 | } |
| 2572 | |
| 2573 | // Test whether all mappings where indeed used. |
| 2574 | if (!mapping.empty()) { |
| 2575 | throw IfcException("Internal error"); |
| 2576 | } |
| 2577 | |
| 2578 | return return_value; |
| 2579 | } |
| 2580 | |
| 2581 | aggregate_of_instance::ptr IfcFile::getInverse(int instance_id, const IfcParse::declaration* type, int attribute_index) { |
no test coverage detected