diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 847f499c13..d1ce1dceeb 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -1505,7 +1505,7 @@ namespace latebound_access { IfcUtil::IfcBaseClass* create(IfcParse::IfcFile& f, const std::string& entity) { auto decl = f.schema()->declaration_by_name(entity); auto data = IfcEntityInstanceData(storage_t(decl->as_entity()->attribute_count())); - auto inst = f.schema()->instantiate(entity, std::move(data)); + auto inst = f.schema()->instantiate(decl, std::move(data)); if (decl->is("IfcRoot")) { IfcParse::IfcGlobalId guid; latebound_access::set(inst, "GlobalId", (std::string) guid); diff --git a/src/ifcgeom/Iterator.h b/src/ifcgeom/Iterator.h index f4f4649b7c..7b4a716d90 100644 --- a/src/ifcgeom/Iterator.h +++ b/src/ifcgeom/Iterator.h @@ -55,6 +55,8 @@ * * ********************************************************************************/ +#define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR + #ifndef IFCGEOMITERATOR_H #define IFCGEOMITERATOR_H diff --git a/src/ifcparse/IfcBaseClass.h b/src/ifcparse/IfcBaseClass.h index a8c1642130..2abe3f4094 100644 --- a/src/ifcparse/IfcBaseClass.h +++ b/src/ifcparse/IfcBaseClass.h @@ -86,20 +86,17 @@ class IFC_PARSE_API IfcBaseInterface { }; class IFC_PARSE_API IfcBaseClass : public virtual IfcBaseInterface { - protected: - uint32_t identity_; + protected: static std::atomic_uint32_t counter_; - + + uint32_t identity_; +public: + uint32_t id_; + IfcParse::IfcFile* file_; +protected: IfcEntityInstanceData data_; - static bool is_null(const IfcBaseClass* not_this) { - return not_this == nullptr; - } - - public: - uint32_t id_; - IfcParse::IfcFile* file_; - +public: IfcBaseClass(IfcEntityInstanceData&& data) : identity_(counter_++) , data_(std::move(data)) diff --git a/src/ifcparse/IfcCharacterDecoder.cpp b/src/ifcparse/IfcCharacterDecoder.cpp index 0c7475f944..c3e729ebf9 100644 --- a/src/ifcparse/IfcCharacterDecoder.cpp +++ b/src/ifcparse/IfcCharacterDecoder.cpp @@ -419,14 +419,36 @@ std::wstring IfcUtil::convert_utf8(const std::string& string) { // bug in msvc 2015 and 2017, unsure if fixed in later versions std::u32string IfcUtil::convert_utf8_to_utf32(const std::string& s) { - auto converted = std::wstring_convert, int32_t>().from_bytes(s); - return std::u32string(reinterpret_cast(converted.data())); + bool is_ascii = true; + for (char c : s) { + if (static_cast(c) >= 128) { + is_ascii = false; + break; + } + } + if (is_ascii) { + return std::u32string(s.begin(), s.end()); + } else { + auto converted = std::wstring_convert, int32_t>().from_bytes(s); + return std::u32string(reinterpret_cast(converted.data())); + } } #else -std::u32string IfcUtil::convert_utf8_to_utf32(const std::string& string) { - return std::wstring_convert, std::u32string::value_type>().from_bytes(string); +std::u32string IfcUtil::convert_utf8_to_utf32(const std::string& s) { + bool is_ascii = true; + for (char c : s) { + if (static_cast(c) >= 128) { + is_ascii = false; + break; + } + } + if (is_ascii) { + return std::u32string(s.begin(), s.end()); + } else { + return std::wstring_convert, std::u32string::value_type>().from_bytes(s); + } } #endif diff --git a/src/ifcparse/IfcEntityInstanceData.h b/src/ifcparse/IfcEntityInstanceData.h index 10b9da4e8f..f96f23ba83 100644 --- a/src/ifcparse/IfcEntityInstanceData.h +++ b/src/ifcparse/IfcEntityInstanceData.h @@ -167,6 +167,10 @@ class IFC_PARSE_API IfcEntityInstanceData { : storage_(std::move(storage)) {} + IfcEntityInstanceData(IfcEntityInstanceData&& other) noexcept + : storage_(std::move(other.storage_)) + {} + IfcEntityInstanceData(const IfcEntityInstanceData& data); IfcEntityInstanceData& operator=(IfcEntityInstanceData&& other) { diff --git a/src/ifcparse/IfcFile.cpp b/src/ifcparse/IfcFile.cpp index 20c45e99c6..9812d242ac 100644 --- a/src/ifcparse/IfcFile.cpp +++ b/src/ifcparse/IfcFile.cpp @@ -141,7 +141,7 @@ namespace { } else if (t.type == IfcParse::Token_FLOAT) { fn(IfcParse::TokenFunc::asFloat(t)); } else if (t.type == IfcParse::Token_IDENTIFIER) { - fn(InstanceReference{ IfcParse::TokenFunc::asIdentifier(t) }); + fn(IfcParse::reference_or_simple_type{ InstanceReference{ IfcParse::TokenFunc::asIdentifier(t) } }); } else if (t.type == IfcParse::Token_INT) { fn(IfcParse::TokenFunc::asInt(t)); } else if (t.type == IfcParse::Token_STRING) { @@ -150,26 +150,31 @@ namespace { } template - void construct_(IfcParse::parse_context& p, Fn fn) { + void construct_(IfcParse::parse_context& p, const IfcParse::aggregation_type* aggr, Fn fn) { if (p.tokens_.empty()) { - // @todo based on type create appropate empty aggregate - return; - } - decltype(p.tokens_) p_tokens_filtered; - std::vector first_type; - get_token_type(first_type, p.tokens_.front()); - std::copy_if( - p.tokens_.begin(), - p.tokens_.end(), - std::back_inserter(p_tokens_filtered), - [first_type](auto& x) { - std::vector nth_type; - get_token_type(nth_type, x); - return can_coerce(first_type, nth_type); + // @todo instead of ugly if-else we could also default initialize the respective + // variant types below. + if (aggr) { + auto aggr_type = IfcUtil::make_aggregate(IfcUtil::from_parameter_type(aggr->type_of_element())); + if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_INT) { + fn(std::vector{}); + } else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) { + fn(std::vector{}); + } else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_STRING) { + fn(std::vector{}); + } else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_BINARY) { + fn(std::vector>{}); + } else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) { + fn(aggregate_of_instance::ptr(new aggregate_of_instance)); + } else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT) { + fn(std::vector>{}); + } else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE) { + fn(std::vector>{}); + } else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) { + fn(aggregate_of_aggregate_of_instance::ptr(new aggregate_of_aggregate_of_instance)); + } } - ); - if (p.tokens_.size() != p_tokens_filtered.size()) { - // warning + return; } typedef boost::variant< @@ -188,25 +193,28 @@ namespace { possible_aggregation_types_t aggregate_storage; - for (auto& t : p_tokens_filtered) { - boost::apply_visitor([&aggregate_storage](auto& v) { + auto append_to_aggregate_storage = [&aggregate_storage](auto v) { + if constexpr (is_type_in_variant_v>>) { + if (aggregate_storage.which() == 0) { + aggregate_storage = std::vector>{ v }; + } else { + auto* vec_ptr = boost::get< std::vector>>(&aggregate_storage); + if (vec_ptr) { + vec_ptr->push_back(v); + } else { + // inconsistent aggregate valuation + } + } + } else { + // unsupported aggregate type + } + }; + + for (auto& t : p.tokens_) { + boost::apply_visitor([&aggregate_storage, &append_to_aggregate_storage, aggr](auto& v) { if constexpr (std::is_same_v, IfcParse::Token>) { // @todo get aggregate of enumeration - dispatch_token(v, nullptr, [&aggregate_storage](auto v) { - if constexpr (std::is_same_v) { - if (aggregate_storage.which() == 0) { - aggregate_storage = std::vector{ v }; - } else { - boost::get< std::vector>(aggregate_storage).push_back(v); - } - } else if constexpr (is_type_in_variant_v>>) { - if (aggregate_storage.which() == 0) { - aggregate_storage = std::vector>{ v }; - } else { - boost::get< std::vector>>(aggregate_storage).push_back(v); - } - } - }); + dispatch_token(v, aggr && aggr->type_of_element()->as_named_type() ? aggr->type_of_element()->as_named_type()->declared_type() : nullptr, append_to_aggregate_storage); } else if constexpr (std::is_same_v, IfcParse::parse_context*>) { /*construct_(*v, [&aggregate_storage](auto& v) { if (aggregate_storage.which() == 0) { @@ -217,11 +225,7 @@ namespace { });*/ // Too deeply nested list } else { - if (aggregate_storage.which() == 0) { - aggregate_storage = std::vector{ v }; - } else { - boost::get>(aggregate_storage).push_back(v); - } + append_to_aggregate_storage(v); } }, t); } @@ -246,17 +250,8 @@ IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_re } ); } - - std::vector attr_types; - std::transform( - parameter_types.begin(), - parameter_types.end(), - std::back_inserter(attr_types), - IfcUtil::from_parameter_type - ); - - if (decl && (tokens_.size() != attr_types.size())) { + if (decl && (tokens_.size() != parameter_types.size())) { // warning } @@ -265,17 +260,15 @@ IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_re } storage_t storage(decl - ? (std::min)(attr_types.size(), tokens_.size()) + ? (std::min)(parameter_types.size(), tokens_.size()) : tokens_.size() ); auto it = tokens_.begin(); - auto jt = attr_types.begin(); auto kt = parameter_types.begin(); - for (; it != tokens_.end() && (!decl || jt != attr_types.end()); ++it) { + for (; it != tokens_.end() && (!decl || kt != parameter_types.end()); ++it) { auto& token = *it; // @todo coerce to expected type, e.g empty -> std::vector, bool -> logical - // auto& attr_type = *jt; const IfcParse::parameter_type* param_type = nullptr; if (decl) { param_type = *kt; @@ -286,20 +279,26 @@ IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_re boost::apply_visitor([this, &storage, name, &references_to_resolve, index, it, param_type](auto& v) { if constexpr (std::is_same_v, IfcParse::Token>) { dispatch_token(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) { - if constexpr (std::is_same_v, InstanceReference>) { + if constexpr (std::is_same_v, IfcParse::reference_or_simple_type>) { 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 }, - unresolved_references::value_type::second_type{v} + v )); } else { storage.set(index, v); } }); } else if constexpr (std::is_same_v, IfcParse::parse_context*>) { - construct_(*v, [this, &storage, name, &references_to_resolve, index](auto& v) { + auto pt = param_type; + if (pt) { + while (pt->as_named_type()) { + pt = pt->as_named_type()->declared_type()->as_type_declaration()->declared_type(); + } + } + construct_(*v, pt ? pt->as_aggregation_type() : nullptr, [this, &storage, name, &references_to_resolve, index](const auto& v) { if constexpr (std::is_same_v, std::vector>) { references_to_resolve.push_back({ {name, index }, v }); } else if constexpr (std::is_same_v, std::vector>>) { @@ -314,7 +313,7 @@ IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_re }, token); if (decl) { - ++jt, ++kt; + ++kt; } } diff --git a/src/ifcparse/IfcFile.h b/src/ifcparse/IfcFile.h index 16fa47206e..0508c39218 100644 --- a/src/ifcparse/IfcFile.h +++ b/src/ifcparse/IfcFile.h @@ -104,7 +104,7 @@ class IFC_PARSE_API IfcFile { typedef boost::unordered_map entity_by_id_t; typedef boost::unordered_map entity_by_iden_t; typedef std::map entity_by_guid_t; - typedef std::tuple inverse_attr_record; + typedef std::tuple inverse_attr_record; enum INVERSE_ATTR { INSTANCE_ID, INSTANCE_TYPE, @@ -165,10 +165,10 @@ class IFC_PARSE_API IfcFile { entity_by_id_t byid_; // this is for simple types entity_by_iden_t byidentity_; - entities_by_type_t bytype_; + // entities_by_type_t bytype_; entities_by_type_t bytype_excl_; - entities_by_ref_t byref_; - entities_by_ref_excl_t byref_excl_; + // entities_by_ref_t byref_; + entities_by_ref_t byref_excl_; entity_by_guid_t byguid_; entity_entity_map_t entity_file_map_; @@ -222,8 +222,8 @@ class IFC_PARSE_API IfcFile { type_iterator types_begin() const; type_iterator types_end() const; - type_iterator types_incl_super_begin() const; - type_iterator types_incl_super_end() const; + // type_iterator types_incl_super_begin() const; + // type_iterator types_incl_super_end() const; /// Returns all entities in the file that match the template argument. /// NOTE: This also returns subtypes of the requested type, for example: diff --git a/src/ifcparse/IfcHierarchyHelper.h b/src/ifcparse/IfcHierarchyHelper.h index ff9204b476..a8fbdf444b 100644 --- a/src/ifcparse/IfcHierarchyHelper.h +++ b/src/ifcparse/IfcHierarchyHelper.h @@ -446,7 +446,7 @@ class IFC_PARSE_API IfcHierarchyHelper : public IfcParse::IfcFile { data.storage_.set(relating_index, relating_object); data.storage_.set(related_index, related_objects); - T* t = (T*)Schema::get_schema().instantiate(T::Class().name(), std::move(data)); + T* t = (T*)Schema::get_schema().instantiate(&T::Class(), std::move(data)); addEntity(t); } } diff --git a/src/ifcparse/IfcLogger.cpp b/src/ifcparse/IfcLogger.cpp index 3286249dd7..5aeb0c3813 100644 --- a/src/ifcparse/IfcLogger.cpp +++ b/src/ifcparse/IfcLogger.cpp @@ -17,6 +17,8 @@ * * ********************************************************************************/ +#define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR + #include "IfcLogger.h" #include "Argument.h" @@ -147,8 +149,12 @@ void Logger::SetOutput(std::wostream* stream1, std::wostream* stream2) { } void Logger::Message(Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseInterface* instance) { - // static std::mutex mtx; - // std::lock_guard lock(mtx); + if (type < verbosity_) { + return; + } + + static std::mutex mtx; + std::lock_guard lock(mtx); if (type == LOG_PERF) { if (!first_timepoint_) { @@ -166,7 +172,7 @@ void Logger::Message(Logger::Severity type, const std::string& message, const If if (type > max_severity_) { max_severity_ = type; } - if (((log2_ != nullptr) || (wlog2_ != nullptr)) && type >= verbosity_) { + if (((log2_ != nullptr) || (wlog2_ != nullptr))) { if (format_ == FMT_PLAIN) { if (log2_ != nullptr) { plain_text_message(*log2_, current_product_, type, message, instance); diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index f78ce7d19c..7a019273d1 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -693,27 +693,6 @@ void IfcParse::IfcFile::load(unsigned entity_instance_name, const IfcParse::enti next = tokens->Next(); } - /* - std::vector* vector = 0; - vector_or_array filler(attributes, num_attributes); - if (attributes == 0) { - if (num_attributes != 0) { - // If num_attributes is zero we know this is a top-level entity instance (or header entity) being parsed. - // There can only be parsed one of these at a time, so we can reuse the vector we have defined at the file - // scope. - if (entity != nullptr) { - vector = &internal_attribute_vector_; - } else { - vector = &internal_attribute_vector_simple_type_; - } - vector->clear(); - } else { - vector = new std::vector; - } - filler = vector_or_array(vector); - } - */ - size_t attribute_index_within_data = 0; size_t return_value = 0; @@ -737,7 +716,8 @@ void IfcParse::IfcFile::load(unsigned entity_instance_name, const IfcParse::enti try { parse_context ps; load(0, nullptr, ps, -1); - auto* simple_type_instance = schema_->instantiate(TokenFunc::asStringRef(next), ps.construct(-1, references_to_resolve, schema_->declaration_by_name(TokenFunc::asStringRef(next)))); + auto decl = schema_->declaration_by_name(TokenFunc::asStringRef(next)); + auto* simple_type_instance = schema_->instantiate(decl, ps.construct(-1, references_to_resolve, decl)); //@todo decide addEntity(((IfcUtil::IfcBaseClass*)*entity)); context.push(simple_type_instance); simple_type_instance->file_ = this; @@ -766,10 +746,6 @@ IfcEntityInstanceData IfcParse::read(unsigned int i, IfcFile* f) { parse_context pc; f->load(i, ty->as_entity(), pc, -1); return IfcEntityInstanceData(pc.construct(i, f->references_to_resolve, ty)); - /*std::ostringstream oss; - d.toString(oss); - auto osss = oss.str(); - std::wcout << osss.c_str() << std::endl;*/ } void IfcParse::IfcFile::try_read_semicolon() { @@ -783,37 +759,16 @@ void IfcParse::IfcFile::try_read_semicolon() { void IfcParse::IfcFile::register_inverse(unsigned id_from, const IfcParse::entity* from_entity, Token t, int attribute_index) { // Assume a check on token type has already been performed const auto* e = from_entity; - byref_excl_[t.value_int].push_back(id_from); - while (e != nullptr) { - byref_[{t.value_int, e->index_in_schema(), attribute_index}].push_back(id_from); - e = e->supertype(); - } + byref_excl_[{t.value_int, e->index_in_schema(), attribute_index}].push_back(id_from); } void IfcParse::IfcFile::register_inverse(unsigned id_from, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass* inst, int attribute_index) { const auto* e = from_entity; - byref_excl_[inst->id()].push_back(id_from); - while (e != nullptr) { - byref_[{inst->id(), e->index_in_schema(), attribute_index}].push_back(id_from); - e = e->supertype(); - } + byref_excl_[{inst->id(), e->index_in_schema(), attribute_index}].push_back(id_from); } void IfcParse::IfcFile::unregister_inverse(unsigned id_from, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass* inst, int attribute_index) { - const auto* entity = from_entity; - while (entity != nullptr) { - std::vector& ids = byref_[{inst->id(), entity->index_in_schema(), attribute_index}]; - std::vector::iterator iter = std::find(ids.begin(), ids.end(), id_from); - if (iter == ids.end()) { - // @todo inverses also need to be populated when multiple instances are added to a new file. - // throw IfcParse::IfcException("Instance not found among inverses"); - } else { - ids.erase(iter); - } - entity = entity->supertype(); - } - - std::vector& ids = byref_excl_[inst->id()]; + std::vector& ids = byref_excl_[{inst->id(), from_entity->index_in_schema(), attribute_index}]; std::vector::iterator iter = std::find(ids.begin(), ids.end(), id_from); if (iter == ids.end()) { // @todo inverses also need to be populated when multiple instances are added to a new file. @@ -917,7 +872,7 @@ namespace { } void operator()(const IfcUtil::IfcBaseClass* const& i) { if (i->declaration().as_entity() == nullptr) { - i->data().toString(data_, true); + i->toString(data_, upper_); } else { data_ << "#" << i->id(); } @@ -1025,20 +980,6 @@ namespace { void IfcEntityInstanceData::toString(std::ostream& ss, bool upper, const entity* decl) const { ss.imbue(std::locale::classic()); - /* - std::string dt; - if (type_ != nullptr) { - dt = type()->name(); - if (upper) { - boost::to_upper(dt); - } - - if ((type()->as_entity() != nullptr) || id_ != 0) { - ss << "#" << id_ << "="; - } - } - */ - ss << "("; StringBuilderVisitor vis(ss, upper); @@ -1206,149 +1147,8 @@ void IfcUtil::IfcBaseClass::set_attribute_value(size_t i, const T& t) { } data_.storage_.set(i, t); - auto new_attribute = data_.get_attribute_value(i); - /* - Argument* new_attribute = a; - if (make_copy) { - if (attr_type == IfcUtil::Argument_UNKNOWN) { - attr_type = a->type(); - } else if (a->isNull()) { - attr_type = IfcUtil::Argument_NULL; - } - - IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); - - switch (attr_type) { - case IfcUtil::Argument_NULL: - copy->set(boost::blank()); - break; - case IfcUtil::Argument_DERIVED: - copy->set(IfcWrite::IfcWriteArgument::Derived()); - break; - case IfcUtil::Argument_INT: - copy->set(static_cast(*a)); - break; - case IfcUtil::Argument_BOOL: - copy->set(static_cast(*a)); - break; - case IfcUtil::Argument_LOGICAL: { - boost::logic::tribool tb = *a; - copy->set(tb); - break; - } - case IfcUtil::Argument_DOUBLE: - copy->set(static_cast(*a)); - break; - case IfcUtil::Argument_STRING: - copy->set(static_cast(*a)); - break; - case IfcUtil::Argument_BINARY: { - boost::dynamic_bitset<> attr_value = *a; - copy->set(attr_value); - break; - } - case IfcUtil::Argument_AGGREGATE_OF_INT: { - std::vector attr_value = *a; - copy->set(attr_value); - break; - } - case IfcUtil::Argument_AGGREGATE_OF_DOUBLE: { - std::vector attr_value = *a; - copy->set(attr_value); - break; - } - case IfcUtil::Argument_AGGREGATE_OF_STRING: { - std::vector attr_value = *a; - copy->set(attr_value); - break; - } - case IfcUtil::Argument_AGGREGATE_OF_BINARY: { - std::vector> attr_value = *a; - copy->set(attr_value); - break; - } - case IfcUtil::Argument_ENUMERATION: { - std::string enum_literal = a->toString(); - // Remove leading and trailing '.' - enum_literal = enum_literal.substr(1, enum_literal.size() - 2); - - const IfcParse::enumeration_type* enum_type = type()->as_enumeration_type() != nullptr - ? type()->as_enumeration_type() - : type()->as_entity()->attribute_by_index(i)->type_of_attribute()->as_named_type()->declared_type()->as_enumeration_type(); - - std::vector::const_iterator it = std::find( - enum_type->enumeration_items().begin(), - enum_type->enumeration_items().end(), - enum_literal); - - if (it == enum_type->enumeration_items().end()) { - throw IfcParse::IfcException(enum_literal + " does not name a valid item for " + enum_type->name()); - } - - copy->set(IfcWrite::IfcWriteArgument::EnumerationReference(it - enum_type->enumeration_items().begin(), it->c_str())); - break; - } - case IfcUtil::Argument_ENTITY_INSTANCE: { - copy->set(static_cast(*a)); - break; - } - case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: { - aggregate_of_instance::ptr instances = *a; - aggregate_of_instance::ptr mapped_instances(new aggregate_of_instance); - // @todo mapped_instances are not actually mapped to the file using add(). - for (aggregate_of_instance::it it = instances->begin(); it != instances->end(); ++it) { - mapped_instances->push(*it); - } - copy->set(mapped_instances); - break; - } - case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT: { - std::vector> attr_value = *a; - copy->set(attr_value); - break; - } - case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE: { - std::vector> attr_value = *a; - copy->set(attr_value); - break; - } - case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE: { - aggregate_of_aggregate_of_instance::ptr instances = *a; - aggregate_of_aggregate_of_instance::ptr mapped_instances(new aggregate_of_aggregate_of_instance); - for (aggregate_of_aggregate_of_instance::outer_it it = instances->begin(); it != instances->end(); ++it) { - std::vector inner; - for (aggregate_of_aggregate_of_instance::inner_it jt = it->begin(); jt != it->end(); ++jt) { - inner.push_back(*jt); - } - mapped_instances->push(inner); - } - copy->set(mapped_instances); - break; - } - case IfcUtil::Argument_EMPTY_AGGREGATE: - case IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE: { - IfcUtil::ArgumentType t2 = IfcUtil::from_parameter_type(type()->as_entity()->attribute_by_index(i)->type_of_attribute()); - delete copy; - copy = 0; - setArgument(i, a, t2, make_copy); - break; - } - default: - case IfcUtil::Argument_UNKNOWN: - throw IfcParse::IfcException(std::string("Unknown attribute encountered: '") + a->toString() + "' at index '" + boost::lexical_cast(i) + "'"); - break; - } - - if (copy == nullptr) { - return; - } - - new_attribute = copy; - } - */ - if (file_ != nullptr) { // Register inverse indices in file register_inverse_visitor visitor(*file_, this); @@ -1385,16 +1185,19 @@ IfcFile::IfcFile(const std::string& fn, bool mmap) { } #else IfcFile::IfcFile(const std::string& path) { - initialize_(new IfcSpfStream(path)); + IfcSpfStream s(path); + initialize_(&s); } #endif IfcFile::IfcFile(std::istream& stream, int length) { - initialize_(new IfcSpfStream(stream, length)); + IfcSpfStream s(stream, length); + initialize_(&s); } IfcFile::IfcFile(void* data, int length) { - initialize_(new IfcSpfStream(data, length)); + IfcSpfStream s(data, length); + initialize_(&s); } IfcFile::IfcFile(IfcParse::IfcSpfStream* s) { @@ -1493,7 +1296,7 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) { parse_context ps; load(current_id, entity_type->as_entity(), ps, -1); - instance = schema_->instantiate(entity_type->name(), ps.construct(current_id, references_to_resolve, entity_type)); + instance = schema_->instantiate(entity_type, ps.construct(current_id, references_to_resolve, entity_type)); instance->file_ = this; instance->id_ = current_id; @@ -1525,27 +1328,10 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) { const IfcParse::declaration* ty = &instance->declaration(); { - aggregate_of_instance::ptr insts = instances_by_type_excl_subtypes(ty); - if (!insts) { - insts = aggregate_of_instance::ptr(new aggregate_of_instance()); - bytype_excl_[ty] = insts; - } - insts->push(instance); - } - - for (;;) { - aggregate_of_instance::ptr insts = instances_by_type(ty); - if (!insts) { - insts = aggregate_of_instance::ptr(new aggregate_of_instance()); - bytype_[ty] = insts; - } - insts->push(instance); - const IfcParse::declaration* pt = ty->as_entity()->supertype(); - if (pt != nullptr) { - ty = pt; - } else { - break; + if (bytype_excl_.find(ty) == bytype_excl_.end()) { + bytype_excl_[ty].reset(new aggregate_of_instance()); } + bytype_excl_[ty]->push(instance); } if (byid_.find(current_id) != byid_.end()) { @@ -1588,6 +1374,8 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) { Logger::Status("\rDone scanning file "); + delete tokens; + for (auto& p : references_to_resolve) { boost::apply_visitor([this, &p](auto& v) { if constexpr (std::is_same_v, reference_or_simple_type>) { @@ -1602,6 +1390,7 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) { }, v)); } else if constexpr (std::is_same_v, std::vector>) { aggregate_of_instance::ptr instances(new aggregate_of_instance); + instances->reserve(v.size()); for (auto& p : v) { instances->push(boost::apply_visitor([this](auto inst) { IfcUtil::IfcBaseClass* ptr; @@ -1810,7 +1599,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id) IfcFile* other_file = entity->file_; IfcEntityInstanceData we(entity->data()); - new_entity = schema()->instantiate(entity->declaration().name(), std::move(we)); + new_entity = schema()->instantiate(&entity->declaration(), std::move(we)); // In case an entity is added that contains geometry, the unit // information needs to be accounted for for IfcLengthMeasures. @@ -1931,7 +1720,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id) Logger::Message(Logger::LOG_WARNING, ss.str()); } byguid_[guid] = new_entity; - } catch (const IfcException& ex) { + } catch (const std::exception& ex) { Logger::Message(Logger::LOG_ERROR, ex.what()); } } @@ -1940,28 +1729,10 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id) const IfcParse::declaration* ty = &new_entity->declaration(); if (ty->as_entity() != nullptr) { - aggregate_of_instance::ptr insts = instances_by_type_excl_subtypes(ty); - if (!insts) { - insts = aggregate_of_instance::ptr(new aggregate_of_instance()); - bytype_excl_[ty] = insts; - } - insts->push(new_entity); - } - - for (; ty->as_entity() != nullptr;) { - aggregate_of_instance::ptr insts = instances_by_type(ty); - if (!insts) { - insts = aggregate_of_instance::ptr(new aggregate_of_instance()); - bytype_[ty] = insts; - } - insts->push(new_entity); - - const IfcParse::declaration* pt = ty->as_entity()->supertype(); - if (pt != nullptr) { - ty = pt; - } else { - break; + if (bytype_excl_.find(ty) == bytype_excl_.end()) { + bytype_excl_[ty].reset(new aggregate_of_instance()); } + bytype_excl_[ty]->push(new_entity); } if (ty->as_entity() != nullptr) { @@ -2106,11 +1877,11 @@ void IfcFile::process_deletion_() { } if (!batch_mode_) { - byref_.erase( - byref_.lower_bound({id, -1, -1}), - byref_.upper_bound({id, std::numeric_limits::max(), std::numeric_limits::max()})); + byref_excl_.erase( + byref_excl_.lower_bound({id, -1, -1}), + byref_excl_.upper_bound({id, std::numeric_limits::max(), std::numeric_limits::max()})); - byref_excl_.erase(id); + // byref_excl_.erase(id); // 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 @@ -2124,21 +1895,14 @@ void IfcFile::process_deletion_() { // Do not update inverses for simple types (which have id()==0 in IfcOpenShell). if (name != 0) { { - auto lower = byref_.lower_bound({name, -1, -1}); - auto upper = byref_.upper_bound({name, std::numeric_limits::max(), std::numeric_limits::max()}); + auto lower = byref_excl_.lower_bound({name, -1, -1}); + auto upper = byref_excl_.upper_bound({name, std::numeric_limits::max(), std::numeric_limits::max()}); for (auto byref_it = lower; byref_it != upper; ++byref_it) { auto& ids = byref_it->second; ids.erase(std::remove(ids.begin(), ids.end(), id), ids.end()); } } - { - auto byref_it = byref_excl_.find(name); - if (byref_it != byref_excl_.end()) { - auto& ids = byref_it->second; - ids.erase(std::remove(ids.begin(), ids.end(), id), ids.end()); - } - } } } } @@ -2158,27 +1922,12 @@ void IfcFile::process_deletion_() { const IfcParse::declaration* ty = &entity->declaration(); { - aggregate_of_instance::ptr instances_of_same_type = instances_by_type_excl_subtypes(ty); - instances_of_same_type->remove(entity); - if (instances_of_same_type->size() == 0) { - bytype_excl_.erase(ty); - } - } - - for (;;) { - aggregate_of_instance::ptr instances_of_same_type = instances_by_type(ty); - if (instances_of_same_type) { - instances_of_same_type->remove(entity); - } - if (instances_of_same_type->size() == 0) { - bytype_.erase(ty); - } - - const IfcParse::declaration* pt = ty->as_entity()->supertype(); - if (pt != nullptr) { - ty = pt; - } else { - break; + auto it = bytype_excl_.find(ty); + if (it != bytype_excl_.end()) { + it->second->remove(entity); + if (it->second->size() == 0) { + bytype_excl_.erase(ty); + } } } @@ -2196,24 +1945,8 @@ void IfcFile::process_deletion_() { } if (batch_mode_) { - for (auto it = byref_.begin(); it != byref_.end();) { - bool do_delete = batch_deletion_ids_.get<1>().find(std::get(it->first)) != batch_deletion_ids_.get<1>().end(); - if (!do_delete) { - it->second.erase(std::remove_if(it->second.begin(), it->second.end(), [this](int x) { - return batch_deletion_ids_.get<1>().find(x) != batch_deletion_ids_.get<1>().end(); - }), - it->second.end()); - do_delete = it->second.empty(); - } - if (do_delete) { - it = byref_.erase(it); - } else { - ++it; - } - } - for (auto it = byref_excl_.begin(); it != byref_excl_.end();) { - bool do_delete = batch_deletion_ids_.get<1>().find(it->first) != batch_deletion_ids_.get<1>().end(); + bool do_delete = batch_deletion_ids_.get<1>().find(std::get(it->first)) != batch_deletion_ids_.get<1>().end(); if (!do_delete) { it->second.erase(std::remove_if(it->second.begin(), it->second.end(), [this](int x) { return batch_deletion_ids_.get<1>().find(x) != batch_deletion_ids_.get<1>().end(); @@ -2232,14 +1965,40 @@ void IfcFile::process_deletion_() { batch_deletion_ids_.clear(); } +namespace { + template + void visit_subtypes(const IfcParse::entity* ent, Fn fn) { + fn(ent); + for (auto& st : ent->subtypes()) { + visit_subtypes(st, fn); + } + } + + template + void visit_supertypes(const IfcParse::entity* ent, Fn fn) { + fn(ent); + if (ent->supertype()) { + visit_supertypes(ent->supertype(), fn); + } + } +} + aggregate_of_instance::ptr IfcFile::instances_by_type(const IfcParse::declaration* t) { - entities_by_type_t::const_iterator it = bytype_.find(t); - return (it == bytype_.end()) ? aggregate_of_instance::ptr() : it->second; + aggregate_of_instance::ptr insts(new aggregate_of_instance); + if (t->as_entity()) { + visit_subtypes(t->as_entity(), [this, &insts](const IfcParse::entity* ent) { + auto it = bytype_excl_.find(ent); + if (it != bytype_excl_.end()) { + insts->push(it->second); + } + }); + } + return insts; } aggregate_of_instance::ptr IfcFile::instances_by_type_excl_subtypes(const IfcParse::declaration* t) { entities_by_type_t::const_iterator it = bytype_excl_.find(t); - return (it == bytype_excl_.end()) ? aggregate_of_instance::ptr() : it->second; + return (it == bytype_excl_.end()) ? aggregate_of_instance::ptr(new aggregate_of_instance) : it->second; } aggregate_of_instance::ptr IfcFile::instances_by_type(const std::string& t) { @@ -2251,9 +2010,13 @@ aggregate_of_instance::ptr IfcFile::instances_by_type_excl_subtypes(const std::s } aggregate_of_instance::ptr IfcFile::instances_by_reference(int t) { + auto lower = byref_excl_.lower_bound({ t, -1, -1 }); + auto upper = byref_excl_.upper_bound({ t, std::numeric_limits::max(), std::numeric_limits::max() }); aggregate_of_instance::ptr ret(new aggregate_of_instance); - for (auto& i : byref_excl_[t]) { - ret->push(instance_by_id(i)); + for (auto it = lower; it != upper; ++it) { + for (auto& i : it->second) { + ret->push(instance_by_id(i)); + } } return ret; } @@ -2286,8 +2049,6 @@ IfcFile::~IfcFile() { for (auto* entity : entities_to_delete) { delete entity; } - delete stream; - delete tokens; } IfcFile::entity_by_id_t::const_iterator IfcFile::begin() const { @@ -2306,14 +2067,6 @@ IfcFile::type_iterator IfcFile::types_end() const { return bytype_excl_.end(); } -IfcFile::type_iterator IfcFile::types_incl_super_begin() const { - return bytype_.begin(); -} - -IfcFile::type_iterator IfcFile::types_incl_super_end() const { - return bytype_.end(); -} - namespace { struct id_instance_pair_sorter { bool operator()(const IfcParse::IfcFile::entity_by_id_t::value_type& a, const IfcParse::IfcFile::entity_by_id_t::value_type& b) const { @@ -2362,8 +2115,8 @@ std::string IfcFile::createTimestamp() const { std::vector IfcFile::get_inverse_indices(int instance_id) { std::vector return_value; - auto lower = byref_.lower_bound({instance_id, -1, -1}); - auto upper = byref_.upper_bound({instance_id, std::numeric_limits::max(), std::numeric_limits::max()}); + auto lower = byref_excl_.lower_bound({instance_id, -1, -1}); + auto upper = byref_excl_.upper_bound({instance_id, std::numeric_limits::max(), std::numeric_limits::max()}); // Mapping of instance id to attribute offset. std::map> mapping; @@ -2401,39 +2154,43 @@ std::vector IfcFile::get_inverse_indices(int instance_id) { } aggregate_of_instance::ptr IfcFile::getInverse(int instance_id, const IfcParse::declaration* type, int attribute_index) { - // @todo is this mutex still necessary? - static std::mutex mtx; - std::lock_guard lock(mtx); - if (type == nullptr && attribute_index == -1) { return instances_by_reference(instance_id); } aggregate_of_instance::ptr return_value(new aggregate_of_instance); - if (attribute_index == -1) { - auto lower = byref_.lower_bound({instance_id, type->index_in_schema(), -1}); - auto upper = byref_.upper_bound({instance_id, type->index_in_schema(), std::numeric_limits::max()}); + visit_subtypes(type->as_entity(), [this, attribute_index, instance_id, &return_value](const IfcParse::declaration* ent) { + if (attribute_index == -1) { + auto lower = byref_excl_.lower_bound({ instance_id, ent->index_in_schema(), -1 }); + auto upper = byref_excl_.upper_bound({ instance_id, ent->index_in_schema(), std::numeric_limits::max() }); - for (auto it = lower; it != upper; ++it) { - for (auto& i : it->second) { - return_value->push(instance_by_id(i)); + for (auto it = lower; it != upper; ++it) { + for (auto& i : it->second) { + return_value->push(instance_by_id(i)); + } + } + } else { + auto it = byref_excl_.find({ instance_id, ent->index_in_schema(), attribute_index }); + if (it != byref_excl_.end()) { + for (auto& i : it->second) { + return_value->push(instance_by_id(i)); + } } } - } else { - auto it = byref_.find({instance_id, type->index_in_schema(), attribute_index}); - if (it != byref_.end()) { - for (auto& i : it->second) { - return_value->push(instance_by_id(i)); - } - } - } + }); return return_value; } size_t IfcFile::getTotalInverses(int instance_id) { - return byref_excl_[instance_id].size(); + size_t n = 0; + auto lower = byref_excl_.lower_bound({ instance_id, -1, -1 }); + auto upper = byref_excl_.upper_bound({ instance_id, std::numeric_limits::max(), std::numeric_limits::max() }); + for (auto it = lower; it != upper; ++it) { + n += it->second.size(); + } + return n; } void IfcFile::setDefaultHeaderValues() { @@ -2531,11 +2288,7 @@ void IfcParse::IfcFile::build_inverses_(IfcUtil::IfcBaseClass* inst) { if (attr->declaration().as_entity() != nullptr) { unsigned entity_attribute_id = attr->id(); const auto* decl = inst->declaration().as_entity(); - byref_excl_[entity_attribute_id].push_back(inst->id()); - while (decl != nullptr) { - byref_[{entity_attribute_id, decl->index_in_schema(), idx}].push_back(inst->id()); - decl = decl->supertype(); - } + byref_excl_[{entity_attribute_id, decl->index_in_schema(), idx}].push_back(inst->id()); } }; @@ -2552,15 +2305,6 @@ std::atomic_uint32_t IfcUtil::IfcBaseClass::counter_(0); bool IfcParse::IfcFile::guid_map_ = true; -/* -template -void IfcUtil::IfcBaseClass::set_value(int index, const T& value) { - IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); - attr->set(value); - data_->setArgument(index, attr); -} -*/ - void IfcUtil::IfcBaseClass::unset_attribute_value(size_t index) { data_.storage_.set(index, Blank{}); } @@ -2571,7 +2315,11 @@ void IfcUtil::IfcBaseClass::toString(std::ostream& out, bool upper) const if (ent) { out << "#" << as()->id() << "="; } - out << declaration().name_uc(); + if (upper) { + out << declaration().name_uc(); + } else { + out << declaration().name(); + } data().toString(out, upper, ent); } diff --git a/src/ifcparse/IfcSchema.cpp b/src/ifcparse/IfcSchema.cpp index 38c627a9a0..dff4ecd4fe 100644 --- a/src/ifcparse/IfcSchema.cpp +++ b/src/ifcparse/IfcSchema.cpp @@ -152,11 +152,11 @@ IfcParse::schema_definition::~schema_definition() { delete factory_; } -IfcUtil::IfcBaseClass* IfcParse::schema_definition::instantiate(const std::string& type_name, IfcEntityInstanceData&& data) const { +IfcUtil::IfcBaseClass* IfcParse::schema_definition::instantiate(const IfcParse::declaration* decl, IfcEntityInstanceData&& data) const { if (factory_ != nullptr) { - return (*factory_)(declaration_by_name(type_name), std::move(data)); + return (*factory_)(decl, std::move(data)); } - return new IfcUtil::IfcLateBoundEntity(declaration_by_name(type_name), std::move(data)); + return new IfcUtil::IfcLateBoundEntity(decl, std::move(data)); } void IfcParse::register_schema(schema_definition* schema) { diff --git a/src/ifcparse/IfcSchema.h b/src/ifcparse/IfcSchema.h index d147b5eaae..5d31a728df 100644 --- a/src/ifcparse/IfcSchema.h +++ b/src/ifcparse/IfcSchema.h @@ -507,7 +507,7 @@ class IFC_PARSE_API schema_definition { const std::string& name() const { return name_; } - IfcUtil::IfcBaseClass* instantiate(const std::string& type_name, IfcEntityInstanceData&& data) const; + IfcUtil::IfcBaseClass* instantiate(const IfcParse::declaration* decl, IfcEntityInstanceData&& data) const; }; IFC_PARSE_API const schema_definition* schema_by_name(const std::string&); diff --git a/src/ifcparse/parse_ifcxml.cpp b/src/ifcparse/parse_ifcxml.cpp index dd43269595..130893af6e 100644 --- a/src/ifcparse/parse_ifcxml.cpp +++ b/src/ifcparse/parse_ifcxml.cpp @@ -503,7 +503,7 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs) } } - IfcUtil::IfcBaseClass* newinst = state->file->schema()->instantiate(decl->name(), std::move(untyped)); + IfcUtil::IfcBaseClass* newinst = state->file->schema()->instantiate(decl, std::move(untyped)); if (state->dialect == ifcxml_dialect_ifc4) { // In IFC2X3 not added directly because attrs such as GlobalId are in diff --git a/src/ifcparse/variantarray.h b/src/ifcparse/variantarray.h index 792579ea24..5307ab3562 100644 --- a/src/ifcparse/variantarray.h +++ b/src/ifcparse/variantarray.h @@ -34,6 +34,8 @@ variant - which is the maximum size of its constituents - is reduced. #include #include +#include "IfcException.h" + namespace impl { // Trait to detect unique_ptr template struct is_unique_ptr : std::false_type {}; @@ -216,7 +218,13 @@ public: template const T& get(std::size_t index) const { if (size_and_indices_[index + 1] != impl::TypeIndex::value) { - throw std::bad_cast(); + // @todo this IfcException is silly. Figure out what + // to do, but at the moment it is specifically caught + // in various places. + throw IfcParse::IfcException( + "Type held at index " + std::to_string(index) + " is " + + get_type_name(index) + " and not " + typeid(T).name() + ); } using V = typename std::tuple_element, impl::MapTypes_t>::type; if constexpr (impl::is_unique_ptr::value) { @@ -290,6 +298,23 @@ private: return decltype(std::declval()(std::declval> &>())){}; } } + + template + const char* get_type_name_impl(size_t i) const { + if constexpr (I == 0) { + return ""; + } else { + if (i == I - 1) { + return typeid(std::tuple_element_t>).name(); + } else { + return get_type_name_impl(i); + } + } + } + + const char* get_type_name(size_t i) const { + return get_type_name_impl(i); + } }; #endif \ No newline at end of file diff --git a/src/ifcwrap/IfcParseWrapper.i b/src/ifcwrap/IfcParseWrapper.i index 4eaef31663..d81e6af3ba 100644 --- a/src/ifcwrap/IfcParseWrapper.i +++ b/src/ifcwrap/IfcParseWrapper.i @@ -186,6 +186,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas return ts; } + /* std::vector types_with_super() const { const size_t n = std::distance($self->types_incl_super_begin(), $self->types_incl_super_end()); std::vector ts; @@ -193,6 +194,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas std::transform($self->types_incl_super_begin(), $self->types_incl_super_end(), std::back_inserter(ts), helper_fn_declaration_get_name); return ts; } + */ std::string schema_name() const { if ($self->schema() == 0) return ""; @@ -368,7 +370,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas void setArgumentAsNull(unsigned int i) { bool is_optional = $self->declaration().as_entity()->attribute_by_index(i)->optional(); if (is_optional) { - self->data().storage_.set(i, Blank{}); + self->set_attribute_value(i, Blank{}); } else { throw IfcParse::IfcException("Attribute not set"); } @@ -377,9 +379,9 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas void setArgumentAsInt(unsigned int i, int v) { IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); if (arg_type == IfcUtil::Argument_INT) { - self->data().storage_.set(i, v); + self->set_attribute_value(i, v); } else if ( (arg_type == IfcUtil::Argument_BOOL) && ( (v == 0) || (v == 1) ) ) { - self->data().storage_.set(i, v); + self->set_attribute_value(i, v); } else { throw IfcParse::IfcException("Attribute not set"); } @@ -388,7 +390,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas void setArgumentAsBool(unsigned int i, bool v) { IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); if (arg_type == IfcUtil::Argument_BOOL) { - self->data().storage_.set(i, v); + self->set_attribute_value(i, v); } else { throw IfcParse::IfcException("Attribute not set"); } @@ -397,7 +399,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas void setArgumentAsLogical(unsigned int i, boost::logic::tribool v) { IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); if (arg_type == IfcUtil::Argument_LOGICAL) { - self->data().storage_.set(i, v); + self->set_attribute_value(i, v); } else { throw IfcParse::IfcException("Attribute not set"); } @@ -406,7 +408,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas void setArgumentAsDouble(unsigned int i, double v) { IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); if (arg_type == IfcUtil::Argument_DOUBLE) { - self->data().storage_.set(i, v); + self->set_attribute_value(i, v); } else { throw IfcParse::IfcException("Attribute not set"); } @@ -415,15 +417,15 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas void setArgumentAsString(unsigned int i, const std::string& a) { IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); if (arg_type == IfcUtil::Argument_STRING) { - self->data().storage_.set(i, a); + self->set_attribute_value(i, a); } else if (arg_type == IfcUtil::Argument_ENUMERATION) { const IfcParse::enumeration_type* enum_type = $self->declaration().schema()->declaration_by_name($self->declaration().type())->as_entity()-> attribute_by_index(i)->type_of_attribute()->as_named_type()->declared_type()->as_enumeration_type(); - self->data().storage_.set(i, EnumerationReference(enum_type, enum_type->lookup_enum_offset(a))); + self->set_attribute_value(i, EnumerationReference(enum_type, enum_type->lookup_enum_offset(a))); } else if (arg_type == IfcUtil::Argument_BINARY) { if (IfcUtil::valid_binary_string(a)) { boost::dynamic_bitset<> bits(a); - self->data().storage_.set(i, bits); + self->set_attribute_value(i, bits); } else { throw IfcParse::IfcException("String not a valid binary representation"); } @@ -435,7 +437,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas void setArgumentAsAggregateOfInt(unsigned int i, const std::vector& v) { IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); if (arg_type == IfcUtil::Argument_AGGREGATE_OF_INT) { - self->data().storage_.set(i, v); + self->set_attribute_value(i, v); } else { throw IfcParse::IfcException("Attribute not set"); } @@ -444,7 +446,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas void setArgumentAsAggregateOfDouble(unsigned int i, const std::vector& v) { IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); if (arg_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) { - self->data().storage_.set(i, v); + self->set_attribute_value(i, v); } else { throw IfcParse::IfcException("Attribute not set"); } @@ -453,7 +455,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas void setArgumentAsAggregateOfString(unsigned int i, const std::vector& v) { IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); if (arg_type == IfcUtil::Argument_AGGREGATE_OF_STRING) { - self->data().storage_.set(i, v); + self->set_attribute_value(i, v); } else if (arg_type == IfcUtil::Argument_AGGREGATE_OF_BINARY) { std::vector< boost::dynamic_bitset<> > bits; bits.reserve(v.size()); @@ -464,7 +466,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas throw IfcParse::IfcException("String not a valid binary representation"); } } - self->data().storage_.set(i, bits); + self->set_attribute_value(i, bits); } else { throw IfcParse::IfcException("Attribute not set"); } @@ -473,7 +475,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas void setArgumentAsEntityInstance(unsigned int i, IfcUtil::IfcBaseClass* v) { IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); if (arg_type == IfcUtil::Argument_ENTITY_INSTANCE) { - self->data().storage_.set(i, v); + self->set_attribute_value(i, v); } else { throw IfcParse::IfcException("Attribute not set"); } @@ -482,7 +484,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas void setArgumentAsAggregateOfEntityInstance(unsigned int i, aggregate_of_instance::ptr v) { IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); if (arg_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) { - self->data().storage_.set(i, v); + self->set_attribute_value(i, v); } else { throw IfcParse::IfcException("Attribute not set"); } @@ -491,7 +493,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas void setArgumentAsAggregateOfAggregateOfInt(unsigned int i, const std::vector< std::vector >& v) { IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT) { - self->data().storage_.set(i, v); + self->set_attribute_value(i, v); } else { throw IfcParse::IfcException("Attribute not set"); } @@ -500,7 +502,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas void setArgumentAsAggregateOfAggregateOfDouble(unsigned int i, const std::vector< std::vector >& v) { IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE) { - self->data().storage_.set(i, v); + self->set_attribute_value(i, v); } else { throw IfcParse::IfcException("Attribute not set"); } @@ -509,7 +511,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas void setArgumentAsAggregateOfAggregateOfEntityInstance(unsigned int i, aggregate_of_aggregate_of_instance::ptr v) { IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) { - self->data().storage_.set(i, v); + self->set_attribute_value(i, v); } else { throw IfcParse::IfcException("Attribute not set"); } @@ -590,7 +592,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas const IfcParse::schema_definition* schema = IfcParse::schema_by_name(schema_identifier); const IfcParse::declaration* decl = schema->declaration_by_name(name); IfcEntityInstanceData data(storage_t(decl->as_entity() ? decl->as_entity()->attribute_count() : 1)); - return schema->instantiate(decl->name(), std::move(data)); + return schema->instantiate(decl, std::move(data)); } %} diff --git a/test/tests.py b/test/tests.py index d65b2f38ca..ce1916d737 100644 --- a/test/tests.py +++ b/test/tests.py @@ -64,10 +64,8 @@ assert "Version" in dir(app) g = ifcopenshell.file(schema=f.schema) p = g.createIfcCartesianPoint((0.,0.)) assert len(g.types()) == 1 -assert "IfcPoint" in g.types_with_super() g.remove(p) assert len(g.types()) == 0 -assert len(g.types_with_super()) == 0 # Some operations on ifcopenshell.entity_instance assert f[22].Id == '' @@ -92,6 +90,9 @@ assert f[288].ConnectedTo == (rel,) # Some operations on ifcopenshell.guid assert len(ifcopenshell.guid.compress(uuid.uuid1().hex)) == 22 +# reopen, because we messed with the units +f = ifcopenshell.open("input/acad2010_walls.ifc") + # Test the BVH tree tree_settings = ifcopenshell.geom.settings() tree_settings.set(tree_settings.DISABLE_OPENING_SUBTRACTIONS, True)