mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Support defined types with instance references in parser (IfcPropertySetDefinitionSet; #6330)
This commit is contained in:
@@ -225,7 +225,7 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional<size_t> expected_size) {
|
||||
IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional<size_t> expected_size, int resolve_reference_index) {
|
||||
std::vector<const IfcParse::parameter_type*> parameter_types;
|
||||
std::unique_ptr<IfcParse::named_type> transient_named_type;
|
||||
|
||||
@@ -274,16 +274,16 @@ IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_re
|
||||
|
||||
auto index = (uint8_t) std::distance(tokens_.begin(), it);
|
||||
|
||||
boost::apply_visitor([this, &storage, name, &references_to_resolve, index, param_type](const auto& v) {
|
||||
boost::apply_visitor([this, &storage, name, &references_to_resolve, index, param_type, resolve_reference_index](const auto& v) {
|
||||
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::Token>) {
|
||||
dispatch_token(name, index, v, param_type && param_type->as_named_type() ? param_type->as_named_type()->declared_type() : nullptr, [this, &storage, name, &references_to_resolve, index](auto v) {
|
||||
dispatch_token(name, index, v, param_type && param_type->as_named_type() ? param_type->as_named_type()->declared_type() : nullptr, [this, &storage, name, &references_to_resolve, index, resolve_reference_index](auto v) {
|
||||
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::reference_or_simple_type>) {
|
||||
if (name > 0) {
|
||||
references_to_resolve.push_back(std::make_pair(
|
||||
// @todo previously this was storage but apparently the
|
||||
// pointer is not constant with the moving and temporary nature
|
||||
// maybe it ought to be and in that case a pointer is more direct
|
||||
MutableAttributeValue{ name, index },
|
||||
MutableAttributeValue{ name, resolve_reference_index == -1 ? index : (uint8_t) resolve_reference_index },
|
||||
v
|
||||
));
|
||||
}
|
||||
@@ -298,14 +298,14 @@ IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_re
|
||||
pt = pt->as_named_type()->declared_type()->as_type_declaration()->declared_type();
|
||||
}
|
||||
}
|
||||
construct_<0>(name, index, *v, pt ? pt->as_aggregation_type() : nullptr, [this, &storage, name, &references_to_resolve, index](const auto& v) {
|
||||
construct_<0>(name, index, *v, pt ? pt->as_aggregation_type() : nullptr, [this, &storage, name, &references_to_resolve, index, resolve_reference_index](const auto& v) {
|
||||
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<reference_or_simple_type>>) {
|
||||
if (name > 0) {
|
||||
references_to_resolve.push_back({ {name, index }, v });
|
||||
references_to_resolve.push_back({ {name, resolve_reference_index == -1 ? index : (uint8_t)resolve_reference_index }, v });
|
||||
}
|
||||
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<std::vector<reference_or_simple_type>>>) {
|
||||
if (name > 0) {
|
||||
references_to_resolve.push_back({ {name, index }, v });
|
||||
references_to_resolve.push_back({ {name, resolve_reference_index == -1 ? index : (uint8_t)resolve_reference_index }, v });
|
||||
}
|
||||
} else {
|
||||
storage.set(index, v);
|
||||
|
||||
@@ -100,7 +100,7 @@ struct parse_context {
|
||||
|
||||
void push(IfcUtil::IfcBaseClass* inst);
|
||||
|
||||
IfcEntityInstanceData construct(int name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional<size_t> expected_size);
|
||||
IfcEntityInstanceData construct(int name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional<size_t> expected_size, int resolve_reference_index=-1);
|
||||
};
|
||||
|
||||
/// This class provides several static convenience functions and variables
|
||||
|
||||
@@ -720,8 +720,14 @@ void IfcParse::IfcFile::load(unsigned entity_instance_name, const IfcParse::enti
|
||||
const auto* decl = schema_->declaration_by_name(TokenFunc::asStringRef(next));
|
||||
parse_context ps;
|
||||
tokens->Next();
|
||||
load(0, nullptr, ps, -1);
|
||||
auto* simple_type_instance = schema_->instantiate(decl, ps.construct(-1, references_to_resolve, decl, boost::none));
|
||||
// The only case we know where a defined type contains entity
|
||||
// instance references is IfcPropertySetDefinitionSet. For
|
||||
// that purpose we propagate the entity_instance_name to
|
||||
// register inverses to the host entity (and not the defined
|
||||
// type) and to be able to actually register the references in
|
||||
// the 2nd pass.
|
||||
load(entity_instance_name, entity, ps, attribute_index == -1 ? (int)attribute_index_within_data : attribute_index);
|
||||
auto* simple_type_instance = schema_->instantiate(decl, ps.construct(entity_instance_name, references_to_resolve, decl, boost::none, attribute_index == -1 ? (int)attribute_index_within_data : attribute_index));
|
||||
//@todo decide addEntity(((IfcUtil::IfcBaseClass*)*entity));
|
||||
context.push(simple_type_instance);
|
||||
simple_type_instance->file_ = this;
|
||||
@@ -1428,10 +1434,40 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
|
||||
if (it == byid_.end()) {
|
||||
Logger::Error("Instance reference #" + std::to_string(*name) + " used by instance #" + std::to_string(ref) + " at attribute index " + std::to_string(refattr) + " not found at offset " + std::to_string(name->file_offset));
|
||||
} else {
|
||||
byid_[p.first.name_]->data().storage_.set(p.first.index_, it->second);
|
||||
auto* storage = &byid_[p.first.name_]->data().storage_;
|
||||
auto attr_index = p.first.index_;
|
||||
|
||||
if (storage->has<IfcUtil::IfcBaseClass*>(attr_index)) {
|
||||
auto inst = storage->get<IfcUtil::IfcBaseClass*>(attr_index);
|
||||
if (!inst->declaration().as_entity()) {
|
||||
storage = &inst->data().storage_;
|
||||
attr_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (storage->has<Blank>(attr_index)) {
|
||||
storage->set(attr_index, it->second);
|
||||
} else {
|
||||
Logger::Error("Duplicate definition for instance reference");
|
||||
}
|
||||
}
|
||||
} else if (auto* inst = boost::get<IfcUtil::IfcBaseClass*>(v)) {
|
||||
byid_[p.first.name_]->data().storage_.set(p.first.index_, *inst);
|
||||
auto* storage = &byid_[p.first.name_]->data().storage_;
|
||||
auto attr_index = p.first.index_;
|
||||
|
||||
if (storage->has<IfcUtil::IfcBaseClass*>(attr_index)) {
|
||||
auto inst = storage->get<IfcUtil::IfcBaseClass*>(attr_index);
|
||||
if (!inst->declaration().as_entity()) {
|
||||
storage = &inst->data().storage_;
|
||||
attr_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (storage->has<Blank>(attr_index)) {
|
||||
storage->set(attr_index, *inst);
|
||||
} else {
|
||||
Logger::Error("Duplicate definition for instance reference");
|
||||
}
|
||||
}
|
||||
} else if (auto* v = boost::get<std::vector<reference_or_simple_type>>(&p.second)) {
|
||||
aggregate_of_instance::ptr instances(new aggregate_of_instance);
|
||||
@@ -1448,7 +1484,23 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
|
||||
instances->push(*inst);
|
||||
}
|
||||
}
|
||||
byid_[p.first.name_]->data().storage_.set(p.first.index_, instances);
|
||||
|
||||
auto* storage = &byid_[p.first.name_]->data().storage_;
|
||||
auto attr_index = p.first.index_;
|
||||
|
||||
if (storage->has<IfcUtil::IfcBaseClass*>(attr_index)) {
|
||||
auto inst = storage->get<IfcUtil::IfcBaseClass*>(attr_index);
|
||||
if (!inst->declaration().as_entity()) {
|
||||
storage = &inst->data().storage_;
|
||||
attr_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (storage->has<Blank>(attr_index)) {
|
||||
storage->set(attr_index, instances);
|
||||
} else {
|
||||
Logger::Error("Duplicate definition for instance reference");
|
||||
}
|
||||
} else if (auto* v = boost::get<std::vector<std::vector<reference_or_simple_type>>>(&p.second)) {
|
||||
aggregate_of_aggregate_of_instance::ptr instances(new aggregate_of_aggregate_of_instance);
|
||||
for (const auto& vi : *v) {
|
||||
@@ -1467,7 +1519,23 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
|
||||
}
|
||||
instances->push(inner);
|
||||
}
|
||||
byid_[p.first.name_]->data().storage_.set(p.first.index_, instances);
|
||||
|
||||
auto* storage = &byid_[p.first.name_]->data().storage_;
|
||||
auto attr_index = p.first.index_;
|
||||
|
||||
if (storage->has<IfcUtil::IfcBaseClass*>(attr_index)) {
|
||||
auto inst = storage->get<IfcUtil::IfcBaseClass*>(attr_index);
|
||||
if (!inst->declaration().as_entity()) {
|
||||
storage = &inst->data().storage_;
|
||||
attr_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (storage->has<Blank>(attr_index)) {
|
||||
storage->set(attr_index, instances);
|
||||
} else {
|
||||
Logger::Error("Duplicate definition for instance reference");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user