mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-11 06:18:09 +00:00
Getting closer to working SPF again
This commit is contained in:
@@ -330,6 +330,8 @@ if (WITH_ROCKSDB)
|
|||||||
|
|
||||||
add_definitions(-DWITH_ROCKSDB)
|
add_definitions(-DWITH_ROCKSDB)
|
||||||
set(SWIG_DEFINES ${SWIG_DEFINES} -DWITH_ROCKSDB)
|
set(SWIG_DEFINES ${SWIG_DEFINES} -DWITH_ROCKSDB)
|
||||||
|
|
||||||
|
set(RPCRT_LIBRARIES "rpcrt4.lib" "shlwapi.lib")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Find Boost: On win32 the (hardcoded) default is to use static libraries and
|
# Find Boost: On win32 the (hardcoded) default is to use static libraries and
|
||||||
@@ -967,7 +969,7 @@ endforeach()
|
|||||||
set(IFCPARSE_FILES ${IFCPARSE_CPP_FILES} ${IFCPARSE_H_FILES})
|
set(IFCPARSE_FILES ${IFCPARSE_CPP_FILES} ${IFCPARSE_H_FILES})
|
||||||
|
|
||||||
add_library(IfcParse ${IFCPARSE_FILES})
|
add_library(IfcParse ${IFCPARSE_FILES})
|
||||||
target_link_libraries(IfcParse ${ROCKSDB_LIBRARY})
|
target_link_libraries(IfcParse ${ROCKSDB_LIBRARY} ${RPCRT_LIBRARIES})
|
||||||
set_target_properties(IfcParse PROPERTIES COMPILE_FLAGS -DIFC_PARSE_EXPORTS VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
set_target_properties(IfcParse PROPERTIES COMPILE_FLAGS -DIFC_PARSE_EXPORTS VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
||||||
|
|
||||||
if(WASM_BUILD)
|
if(WASM_BUILD)
|
||||||
|
|||||||
@@ -391,7 +391,6 @@ namespace {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// @todo naming
|
// @todo naming
|
||||||
IfcParse::impl::rocks_db_file_storage::rocks_db_file_storage(const std::string& filepath, IfcParse::IfcFile* ffile)
|
IfcParse::impl::rocks_db_file_storage::rocks_db_file_storage(const std::string& filepath, IfcParse::IfcFile* ffile)
|
||||||
: file(ffile)
|
: file(ffile)
|
||||||
@@ -413,6 +412,61 @@ IfcUtil::IfcBaseClass* IfcParse::impl::rocks_db_file_storage::instance_by_id(int
|
|||||||
return assert_existance(id);
|
return assert_existance(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IfcParse::impl::rocks_db_file_storage::process_deletion_inverse(IfcUtil::IfcBaseClass* inst)
|
||||||
|
{
|
||||||
|
auto id = inst->id();
|
||||||
|
|
||||||
|
{
|
||||||
|
// compute next prefix that does not start with v|{id}
|
||||||
|
auto prefix = "v|" + id;
|
||||||
|
auto it = db->NewIterator(rocksdb::ReadOptions());
|
||||||
|
it->Seek(prefix);
|
||||||
|
while (it->Valid()) {
|
||||||
|
it->Next();
|
||||||
|
if (!it->key().starts_with(prefix)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rocksdb::WriteBatch batch;
|
||||||
|
batch.DeleteRange(prefix, it->key());
|
||||||
|
db->Write(rocksdb::WriteOptions{}, &batch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is based on traversal which needs instances to still be contained in the map.
|
||||||
|
// another option would be to keep byid intact for the remainder of this loop
|
||||||
|
aggregate_of_instance::ptr entity_attributes = traverse(inst, 1);
|
||||||
|
for (aggregate_of_instance::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) {
|
||||||
|
IfcUtil::IfcBaseClass* entity_attribute = *it;
|
||||||
|
if (entity_attribute == inst) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const unsigned int name = entity_attribute->id();
|
||||||
|
// Do not update inverses for simple types (which have id()==0 in IfcOpenShell).
|
||||||
|
if (name != 0) {
|
||||||
|
// Find instances entity -> other
|
||||||
|
// and update inverses from entity into other
|
||||||
|
|
||||||
|
{
|
||||||
|
auto prefix = "v|" + name;
|
||||||
|
auto it = db->NewIterator(rocksdb::ReadOptions());
|
||||||
|
it->Seek(prefix);
|
||||||
|
while (it->Valid() && it->key().starts_with(prefix)) {
|
||||||
|
std::string s = it->value().ToString();
|
||||||
|
|
||||||
|
// Iterator are snapshotted? So don't get invalidated?
|
||||||
|
std::vector<size_t> vals(s.size() / sizeof(size_t));
|
||||||
|
memcpy(vals.data(), s.data(), s.size());
|
||||||
|
vals.erase(std::find(vals.begin(), vals.end(), (size_t)id));
|
||||||
|
s.resize(vals.size() * sizeof(size_t));
|
||||||
|
memcpy(s.data(), vals.data(), s.size());
|
||||||
|
db->Put(rocksdb::WriteOptions{}, it->key(), s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IfcUtil::IfcBaseClass* IfcParse::impl::in_memory_file_storage::instance_by_id(int id)
|
IfcUtil::IfcBaseClass* IfcParse::impl::in_memory_file_storage::instance_by_id(int id)
|
||||||
{
|
{
|
||||||
auto it = byid_.find(id);
|
auto it = byid_.find(id);
|
||||||
|
|||||||
+14
-5
@@ -206,8 +206,6 @@ namespace impl {
|
|||||||
typedef map_transformer<identity_by_id_t, std::function<IfcUtil::IfcBaseClass* (size_t)>, std::function<size_t(IfcUtil::IfcBaseClass*)>> entity_by_id_t;
|
typedef map_transformer<identity_by_id_t, std::function<IfcUtil::IfcBaseClass* (size_t)>, std::function<size_t(IfcUtil::IfcBaseClass*)>> entity_by_id_t;
|
||||||
typedef entity_by_id_t::iterator iterator;
|
typedef entity_by_id_t::iterator iterator;
|
||||||
|
|
||||||
identity_by_id_t idenbyid_;
|
|
||||||
|
|
||||||
in_memory_file_storage()
|
in_memory_file_storage()
|
||||||
: byid_(
|
: byid_(
|
||||||
&idenbyid_,
|
&idenbyid_,
|
||||||
@@ -216,6 +214,9 @@ namespace impl {
|
|||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
in_memory_file_storage(const in_memory_file_storage&) = delete;
|
||||||
|
in_memory_file_storage(const in_memory_file_storage&&) = delete;
|
||||||
|
|
||||||
class type_iterator : private entities_by_type_t::const_iterator {
|
class type_iterator : private entities_by_type_t::const_iterator {
|
||||||
public:
|
public:
|
||||||
using iterator_category = std::forward_iterator_tag;
|
using iterator_category = std::forward_iterator_tag;
|
||||||
@@ -260,7 +261,6 @@ namespace impl {
|
|||||||
static bool guid_map() { return guid_map_; }
|
static bool guid_map() { return guid_map_; }
|
||||||
static void guid_map(bool b) { guid_map_ = b; }
|
static void guid_map(bool b) { guid_map_ = b; }
|
||||||
|
|
||||||
entity_by_id_t byid_;
|
|
||||||
// this is for simple types
|
// this is for simple types
|
||||||
entity_by_iden_t byidentity_;
|
entity_by_iden_t byidentity_;
|
||||||
// entities_by_type_t bytype_;
|
// entities_by_type_t bytype_;
|
||||||
@@ -268,6 +268,8 @@ namespace impl {
|
|||||||
// entities_by_ref_t byref_;
|
// entities_by_ref_t byref_;
|
||||||
entities_by_ref_t byref_excl_;
|
entities_by_ref_t byref_excl_;
|
||||||
entity_by_guid_t byguid_;
|
entity_by_guid_t byguid_;
|
||||||
|
identity_by_id_t idenbyid_;
|
||||||
|
entity_by_id_t byid_;
|
||||||
|
|
||||||
void load(unsigned entity_instance_name, const IfcParse::entity* entity, parse_context&, int attribute_index = -1);
|
void load(unsigned entity_instance_name, const IfcParse::entity* entity, parse_context&, int attribute_index = -1);
|
||||||
void try_read_semicolon() const;
|
void try_read_semicolon() const;
|
||||||
@@ -291,7 +293,14 @@ namespace impl {
|
|||||||
bytype_excl_[ty]->push(new_entity);
|
bytype_excl_[ty]->push(new_entity);
|
||||||
}
|
}
|
||||||
void remove_type_ref(IfcUtil::IfcBaseClass* new_entity) {
|
void remove_type_ref(IfcUtil::IfcBaseClass* new_entity) {
|
||||||
// @todo
|
auto ty = new_entity->declaration().as_entity();
|
||||||
|
auto it = bytype_excl_.find(ty);
|
||||||
|
if (it != bytype_excl_.end()) {
|
||||||
|
it->second->remove(new_entity);
|
||||||
|
if (it->second->size() == 0) {
|
||||||
|
bytype_excl_.erase(ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_inverse_ref(IfcUtil::IfcBaseClass* new_entity) {
|
void add_inverse_ref(IfcUtil::IfcBaseClass* new_entity) {
|
||||||
@@ -509,6 +518,7 @@ namespace impl {
|
|||||||
const IfcParse::declaration* operator*() const;
|
const IfcParse::declaration* operator*() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// @todo rocksdb_instance_iterator?
|
||||||
using const_iterator = rocksdb_types_iterator;
|
using const_iterator = rocksdb_types_iterator;
|
||||||
|
|
||||||
void register_inverse(unsigned, const IfcParse::entity* from_entity, int inst_id, int attribute_index);
|
void register_inverse(unsigned, const IfcParse::entity* from_entity, int inst_id, int attribute_index);
|
||||||
@@ -707,7 +717,6 @@ private:
|
|||||||
|
|
||||||
void build_inverses();
|
void build_inverses();
|
||||||
|
|
||||||
// @todo variant apply_visitor
|
|
||||||
void register_inverse(unsigned, const IfcParse::entity* from_entity, int inst_id, int attribute_index);
|
void register_inverse(unsigned, const IfcParse::entity* from_entity, int inst_id, int attribute_index);
|
||||||
void unregister_inverse(unsigned, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass*, int attribute_index);
|
void unregister_inverse(unsigned, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass*, int attribute_index);
|
||||||
|
|
||||||
|
|||||||
+58
-11
@@ -811,6 +811,28 @@ void IfcParse::impl::rocks_db_file_storage::unregister_inverse(unsigned id_from,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IfcParse::impl::rocks_db_file_storage::add_type_ref(IfcUtil::IfcBaseClass* new_entity)
|
||||||
|
{
|
||||||
|
size_t v = new_entity->identity();
|
||||||
|
std::string s(sizeof(size_t), ' ');
|
||||||
|
memcpy(s.data(), &v, sizeof(size_t));
|
||||||
|
db->Merge(rocksdb::WriteOptions{}, "t|" + std::to_string(new_entity->declaration().index_in_schema()), s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IfcParse::impl::rocks_db_file_storage::remove_type_ref(IfcUtil::IfcBaseClass* new_entity)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
auto key = "t|" + std::to_string(new_entity->declaration().index_in_schema());
|
||||||
|
if (db->Get(rocksdb::ReadOptions{}, key, &s).ok()) {
|
||||||
|
std::vector<size_t> vals(s.size() / sizeof(size_t));
|
||||||
|
memcpy(vals.data(), s.data(), s.size());
|
||||||
|
vals.erase(std::find(vals.begin(), vals.end(), (size_t)new_entity->identity()));
|
||||||
|
s.resize(vals.size() * sizeof(size_t));
|
||||||
|
memcpy(s.data(), vals.data(), s.size());
|
||||||
|
db->Put(rocksdb::WriteOptions{}, key, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class StringBuilderVisitor : public boost::static_visitor<void> {
|
class StringBuilderVisitor : public boost::static_visitor<void> {
|
||||||
private:
|
private:
|
||||||
@@ -1231,7 +1253,9 @@ IfcFile::IfcFile(const std::string& path, filetype ty) {
|
|||||||
// @todo allow for rocksdb from path
|
// @todo allow for rocksdb from path
|
||||||
if (ty == ifcspf) {
|
if (ty == ifcspf) {
|
||||||
IfcSpfStream s(path);
|
IfcSpfStream s(path);
|
||||||
storage_ = impl::in_memory_file_storage{};
|
storage_.emplace<1>(); // impl::in_memory_file_storage{};
|
||||||
|
// @todo assign in constructor
|
||||||
|
std::get<impl::in_memory_file_storage>(storage_).file = this;
|
||||||
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_);
|
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_);
|
||||||
} else {
|
} else {
|
||||||
storage_ = impl::rocks_db_file_storage(path, this);
|
storage_ = impl::rocks_db_file_storage(path, this);
|
||||||
@@ -1243,20 +1267,20 @@ IfcFile::IfcFile(const std::string& path, filetype ty) {
|
|||||||
|
|
||||||
IfcFile::IfcFile(std::istream& stream, int length) {
|
IfcFile::IfcFile(std::istream& stream, int length) {
|
||||||
IfcSpfStream s(stream, length);
|
IfcSpfStream s(stream, length);
|
||||||
storage_ = impl::in_memory_file_storage{};
|
storage_.emplace<1>();
|
||||||
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_);
|
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_);
|
||||||
ifcroot_type_ = schema_->declaration_by_name("IfcRoot");
|
ifcroot_type_ = schema_->declaration_by_name("IfcRoot");
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcFile::IfcFile(void* data, int length) {
|
IfcFile::IfcFile(void* data, int length) {
|
||||||
IfcSpfStream s(data, length);
|
IfcSpfStream s(data, length);
|
||||||
storage_ = impl::in_memory_file_storage{};
|
storage_.emplace<1>();
|
||||||
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_);
|
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_);
|
||||||
ifcroot_type_ = schema_->declaration_by_name("IfcRoot");
|
ifcroot_type_ = schema_->declaration_by_name("IfcRoot");
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcFile::IfcFile(IfcParse::IfcSpfStream* s) {
|
IfcFile::IfcFile(IfcParse::IfcSpfStream* s) {
|
||||||
storage_ = impl::in_memory_file_storage{};
|
storage_.emplace<1>();
|
||||||
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(s, schema_, max_id_);
|
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(s, schema_, max_id_);
|
||||||
ifcroot_type_ = schema_->declaration_by_name("IfcRoot");
|
ifcroot_type_ = schema_->declaration_by_name("IfcRoot");
|
||||||
}
|
}
|
||||||
@@ -1266,7 +1290,7 @@ IfcFile::IfcFile(const IfcParse::schema_definition* schema)
|
|||||||
, ifcroot_type_(schema_->declaration_by_name("IfcRoot"))
|
, ifcroot_type_(schema_->declaration_by_name("IfcRoot"))
|
||||||
, max_id_(0)
|
, max_id_(0)
|
||||||
{
|
{
|
||||||
storage_ = impl::in_memory_file_storage{};
|
storage_.emplace<1>();
|
||||||
setDefaultHeaderValues();
|
setDefaultHeaderValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1283,7 +1307,8 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::IfcSpfSt
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens = new IfcSpfLexer(stream, file);
|
// @todo file ptr arg removed?
|
||||||
|
tokens = new IfcSpfLexer(stream, nullptr);
|
||||||
|
|
||||||
std::vector<std::string> schemas;
|
std::vector<std::string> schemas;
|
||||||
|
|
||||||
@@ -2014,7 +2039,7 @@ void IfcParse::impl::in_memory_file_storage::process_deletion_inverse(IfcUtil::I
|
|||||||
ids.erase(std::remove(ids.begin(), ids.end(), id), ids.end());
|
ids.erase(std::remove(ids.begin(), ids.end(), id), ids.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -2102,7 +2127,7 @@ aggregate_of_instance::ptr IfcFile::instances_by_reference(int t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IfcUtil::IfcBaseClass* IfcFile::instance_by_id(int id) {
|
IfcUtil::IfcBaseClass* IfcFile::instance_by_id(int id) {
|
||||||
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>) {
|
||||||
throw std::runtime_error("Storage not initialized");
|
throw std::runtime_error("Storage not initialized");
|
||||||
return (IfcUtil::IfcBaseClass*) nullptr;
|
return (IfcUtil::IfcBaseClass*) nullptr;
|
||||||
@@ -2185,7 +2210,7 @@ std::ostream& operator<<(std::ostream& out, const IfcParse::IfcFile& file) {
|
|||||||
|
|
||||||
typedef std::vector<IfcUtil::IfcBaseClass*> vector_t;
|
typedef std::vector<IfcUtil::IfcBaseClass*> vector_t;
|
||||||
vector_t sorted;
|
vector_t sorted;
|
||||||
std::transform(file.begin(), file.end(), std::back_inserter(sorted), [file](const auto& x) { return file.byidentity_.find(x.second)->second; });
|
std::transform(file.begin(), file.end(), std::back_inserter(sorted), [&file](const auto& x) { return file.byidentity_.find(x.second)->second; });
|
||||||
std::sort(sorted.begin(), sorted.end(), [](const auto& a, const auto& b) { return a->id() < b->id(); });
|
std::sort(sorted.begin(), sorted.end(), [](const auto& a, const auto& b) { return a->id() < b->id(); });
|
||||||
|
|
||||||
for (auto& e : sorted) {
|
for (auto& e : sorted) {
|
||||||
@@ -2436,6 +2461,28 @@ void IfcParse::IfcFile::build_inverses() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IfcParse::IfcFile::register_inverse(unsigned id_from, const IfcParse::entity* from_entity, int inst_id, int attribute_index)
|
||||||
|
{
|
||||||
|
std::visit([id_from, from_entity, inst_id, attribute_index](auto& x) {
|
||||||
|
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, std::monostate>) {
|
||||||
|
throw std::runtime_error("Storage not initialized");
|
||||||
|
} else {
|
||||||
|
return x.register_inverse(id_from, from_entity, inst_id, attribute_index);
|
||||||
|
}
|
||||||
|
}, storage_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IfcParse::IfcFile::unregister_inverse(unsigned id_from, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass* inst, int attribute_index)
|
||||||
|
{
|
||||||
|
std::visit([id_from, from_entity, inst, attribute_index](auto& x) {
|
||||||
|
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, std::monostate>) {
|
||||||
|
throw std::runtime_error("Storage not initialized");
|
||||||
|
} else {
|
||||||
|
return x.unregister_inverse(id_from, from_entity, inst, attribute_index);
|
||||||
|
}
|
||||||
|
}, storage_);
|
||||||
|
}
|
||||||
|
|
||||||
std::atomic_uint32_t IfcUtil::IfcBaseClass::counter_(0);
|
std::atomic_uint32_t IfcUtil::IfcBaseClass::counter_(0);
|
||||||
|
|
||||||
// bool IfcParse::IfcFile::guid_map_ = true;
|
// bool IfcParse::IfcFile::guid_map_ = true;
|
||||||
@@ -2497,9 +2544,9 @@ IfcEntityInstanceData::IfcEntityInstanceData(const IfcEntityInstanceData& data)
|
|||||||
AttributeValue IfcEntityInstanceData::get_attribute_value(size_t index) const
|
AttributeValue IfcEntityInstanceData::get_attribute_value(size_t index) const
|
||||||
{
|
{
|
||||||
return std::visit([index](const auto& x) {
|
return std::visit([index](const auto& x) {
|
||||||
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, IfcParse::impl::in_memory_file_storage>) {
|
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, in_memory_attribute_storage>) {
|
||||||
return AttributeValue(&x, (uint8_t)index);
|
return AttributeValue(&x, (uint8_t)index);
|
||||||
} else if constexpr (std::is_same_v<std::decay_t<decltype(x)>, IfcParse::impl::rocks_db_file_storage>) {
|
} else if constexpr (std::is_same_v<std::decay_t<decltype(x)>, rocks_db_attribute_storage>) {
|
||||||
// @todo
|
// @todo
|
||||||
return AttributeValue{};
|
return AttributeValue{};
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user