mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-22 06:58:38 +00:00
ifcparse: dispatch the inverse containment check for every storage backend
Review: the wrapper helpers visited the storage variant themselves and threw for anything but in-memory storage. Move the dispatch into file::all_referencing_instances(instance_id, pred), implemented for both backends the way instances_by_reference is: the in-memory index through inverse_index::all_sources, RocksDB through the same "v|<id>|" prefix seek, stopping at the first source pred rejects. The SWIG helpers only build the id set and call it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HNrXDmR88wKPCYwGE21SyH
This commit is contained in:
@@ -373,6 +373,10 @@ public:
|
|||||||
/// Returns all entities in the file that reference the id
|
/// Returns all entities in the file that reference the id
|
||||||
std::vector<express::base> instances_by_reference(int reference_id);
|
std::vector<express::base> instances_by_reference(int reference_id);
|
||||||
|
|
||||||
|
/// Returns whether pred accepts the id of every instance that references
|
||||||
|
/// instance_id, stopping at the first one it rejects.
|
||||||
|
bool all_referencing_instances(int instance_id, const std::function<bool(uint32_t)>& pred);
|
||||||
|
|
||||||
/// Returns the entity with the specified id
|
/// Returns the entity with the specified id
|
||||||
express::base instance_by_id(int instance_id);
|
express::base instance_by_id(int instance_id);
|
||||||
|
|
||||||
|
|||||||
@@ -3805,6 +3805,36 @@ std::vector<express::base> file::instances_by_reference(int t) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool file::all_referencing_instances(int instance_id, const std::function<bool(uint32_t)>& pred) {
|
||||||
|
return std::visit([instance_id, &pred](auto& x) -> bool {
|
||||||
|
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, impl::in_memory_file_storage>) {
|
||||||
|
return x.byref_excl_.all_sources((uint32_t)instance_id, pred);
|
||||||
|
}
|
||||||
|
#ifdef IFOPSH_WITH_ROCKSDB
|
||||||
|
else if constexpr (std::is_same_v<std::decay_t<decltype(x)>, impl::rocks_db_file_storage>) {
|
||||||
|
// @todo no lower/upper_bounds() implemented yet
|
||||||
|
auto prefix = "v|" + std::to_string(instance_id) + "|";
|
||||||
|
auto it = std::unique_ptr<rocksdb::Iterator>(x.db->NewIterator(rocksdb::ReadOptions()));
|
||||||
|
it->Seek(prefix);
|
||||||
|
while (it->Valid() && it->key().starts_with(prefix)) {
|
||||||
|
std::vector<uint32_t> vals(it->value().size() / sizeof(uint32_t));
|
||||||
|
memcpy(vals.data(), it->value().data(), it->value().size());
|
||||||
|
for (auto& v : vals) {
|
||||||
|
if (!pred(v)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
it->Next();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("Storage not initialized");
|
||||||
|
}
|
||||||
|
}, storage_);
|
||||||
|
}
|
||||||
|
|
||||||
express::base file::instance_by_id(int id) {
|
express::base file::instance_by_id(int id) {
|
||||||
return std::visit([id](auto& x) {
|
return std::visit([id](auto& x) {
|
||||||
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, std::monostate>) {
|
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, std::monostate>) {
|
||||||
|
|||||||
@@ -325,35 +325,22 @@ private:
|
|||||||
throw ifcopenshell::exception("Only entities with ids are supported for _all_inverses_within. Provided entity: '" + e.declaration().name() + "'.");
|
throw ifcopenshell::exception("Only entities with ids are supported for _all_inverses_within. Provided entity: '" + e.declaration().name() + "'.");
|
||||||
}
|
}
|
||||||
const std::unordered_set<uint32_t> allowed(ids.begin(), ids.end());
|
const std::unordered_set<uint32_t> allowed(ids.begin(), ids.end());
|
||||||
const auto referenced_id = (uint32_t)e_.id();
|
return $self->all_referencing_instances(e_.id(), [&allowed](uint32_t source_id) {
|
||||||
return std::visit([referenced_id, &allowed](auto& x) -> bool {
|
return allowed.count(source_id) != 0;
|
||||||
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, ifcopenshell::impl::in_memory_file_storage>) {
|
});
|
||||||
return x.byref_excl_.all_sources(referenced_id, [&allowed](uint32_t source_id) {
|
|
||||||
return allowed.count(source_id) != 0;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
throw ifcopenshell::exception("_all_inverses_within is only implemented for in-memory storage");
|
|
||||||
}
|
|
||||||
}, $self->storage_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The subset of ids whose every referencing instance is itself in ids:
|
// The subset of ids whose every referencing instance is itself in ids:
|
||||||
// one crossing in, one crossing out, early exit per id in C++.
|
// one crossing in, one crossing out, early exit per id.
|
||||||
std::vector<int> _ids_referenced_only_within(const std::vector<int>& ids) {
|
std::vector<int> _ids_referenced_only_within(const std::vector<int>& ids) {
|
||||||
const std::unordered_set<uint32_t> allowed(ids.begin(), ids.end());
|
const std::unordered_set<uint32_t> allowed(ids.begin(), ids.end());
|
||||||
const auto within = [&allowed](uint32_t source_id) { return allowed.count(source_id) != 0; };
|
const auto within = [&allowed](uint32_t source_id) { return allowed.count(source_id) != 0; };
|
||||||
std::vector<int> contained;
|
std::vector<int> contained;
|
||||||
std::visit([&](auto& x) {
|
for (int id : ids) {
|
||||||
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, ifcopenshell::impl::in_memory_file_storage>) {
|
if ($self->all_referencing_instances(id, within)) {
|
||||||
for (int id : ids) {
|
contained.push_back(id);
|
||||||
if (x.byref_excl_.all_sources((uint32_t)id, within)) {
|
|
||||||
contained.push_back(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw ifcopenshell::exception("_ids_referenced_only_within is only implemented for in-memory storage");
|
|
||||||
}
|
}
|
||||||
}, $self->storage_);
|
}
|
||||||
return contained;
|
return contained;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user