diff --git a/src/ifcparse/IfcBaseClass.h b/src/ifcparse/IfcBaseClass.h index b27b6671b0..76105aa2ad 100644 --- a/src/ifcparse/IfcBaseClass.h +++ b/src/ifcparse/IfcBaseClass.h @@ -28,6 +28,8 @@ #include +#include + class Argument; class aggregate_of_instance; @@ -67,15 +69,19 @@ namespace IfcUtil { }; class IFC_PARSE_API IfcBaseClass : public virtual IfcBaseInterface { - protected: + private: + uint32_t identity_; + static std::atomic_uint32_t counter_; + + protected: IfcEntityInstanceData* data_; static bool is_null(const IfcBaseClass* not_this) { return !not_this; } public: - IfcBaseClass() : data_(0) {} - IfcBaseClass(IfcEntityInstanceData* d) : data_(d) {} + IfcBaseClass() : identity_(counter_++), data_(0) {} + IfcBaseClass(IfcEntityInstanceData* d) : identity_(counter_++), data_(d) {} virtual ~IfcBaseClass() { delete data_; } const IfcEntityInstanceData& data() const { return *data_; } @@ -83,6 +89,8 @@ namespace IfcUtil { void data(IfcEntityInstanceData* d); virtual const IfcParse::declaration& declaration() const = 0; + + uint32_t identity() const { return identity_; } }; class IFC_PARSE_API IfcLateBoundEntity : public IfcBaseClass { diff --git a/src/ifcparse/IfcFile.h b/src/ifcparse/IfcFile.h index b3952bfb1e..15a61e8890 100644 --- a/src/ifcparse/IfcFile.h +++ b/src/ifcparse/IfcFile.h @@ -23,6 +23,7 @@ #include #include #include + #include #include #include @@ -112,7 +113,7 @@ public: }; private: - typedef std::map entity_entity_map_t; + typedef std::map entity_entity_map_t; bool parsing_complete_; file_open_status good_ = file_open_status::SUCCESS; diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index c4828ebf26..1c8ca87a7e 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -1703,7 +1703,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id) // If this instance has been inserted before, return // a reference to the copy that was created from it. - entity_entity_map_t::iterator mit = entity_file_map.find(entity); + entity_entity_map_t::iterator mit = entity_file_map.find(entity->identity()); if (mit != entity_file_map.end()) { return mit->second; } @@ -1717,9 +1717,9 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id) aggregate_of_instance::ptr entity_attributes = traverse(entity, 1); for (aggregate_of_instance::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) { if (*it != entity) { - entity_entity_map_t::iterator mit2 = entity_file_map.find(*it); + entity_entity_map_t::iterator mit2 = entity_file_map.find((*it)->identity()); if (mit2 == entity_file_map.end()) { - entity_file_map.insert(entity_entity_map_t::value_type(*it, addEntity(*it))); + entity_file_map.insert(entity_entity_map_t::value_type((*it)->identity(), addEntity(*it))); } } } @@ -1764,7 +1764,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id) } if (attr_type == IfcUtil::Argument_ENTITY_INSTANCE) { - entity_entity_map_t::const_iterator eit = entity_file_map.find(*attr); + entity_entity_map_t::const_iterator eit = entity_file_map.find(((IfcUtil::IfcBaseClass*)(*attr))->identity()); if (eit == entity_file_map.end()) throw IfcParse::IfcException("Unable to map instance to file"); IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); @@ -1774,7 +1774,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id) aggregate_of_instance::ptr instances = *attr; aggregate_of_instance::ptr new_instances(new aggregate_of_instance); for (aggregate_of_instance::it it = instances->begin(); it != instances->end(); ++it) { - entity_entity_map_t::const_iterator eit = entity_file_map.find(*it); + entity_entity_map_t::const_iterator eit = entity_file_map.find((*it)->identity()); if (eit == entity_file_map.end()) throw IfcParse::IfcException("Unable to map instance to file"); new_instances->push(eit->second); } @@ -1788,7 +1788,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id) for (aggregate_of_aggregate_of_instance::outer_it it = instances->begin(); it != instances->end(); ++it) { std::vector list; for (aggregate_of_aggregate_of_instance::inner_it jt = it->begin(); jt != it->end(); ++jt) { - entity_entity_map_t::const_iterator eit = entity_file_map.find(*jt); + entity_entity_map_t::const_iterator eit = entity_file_map.find((*jt)->identity()); if (eit == entity_file_map.end()) throw IfcParse::IfcException("Unable to map instance to file"); list.push_back(eit->second); } @@ -1842,8 +1842,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id) } } - // @todo entity_file_map: use weak_ptr - entity_file_map.insert(entity_entity_map_t::value_type(entity, new_entity)); + entity_file_map.insert(entity_entity_map_t::value_type(entity->identity(), new_entity)); } // For subtypes of IfcRoot, the GUID mapping needs to be updated. @@ -2096,13 +2095,12 @@ void IfcFile::process_deletion_() { } } - // This entity_file_map remains obviously flawed, but until we have proper lookup by value, or another mechanism, - // to prevent duplicate definitions with usage of add() we have to keep it. This might be a good moment to clear it. + // entity_file_map is in place to prevent duplicate definitions with usage of add(). + // Upon deletion the pairs need to be erased. for (auto it = entity_file_map.begin(); it != entity_file_map.end();) { if (it->second == entity) { it = entity_file_map.erase(it); - } - else { + } else { ++it; } } @@ -2401,3 +2399,5 @@ void IfcParse::IfcFile::build_inverses() { build_inverses_(pair.second); } } + +std::atomic_uint32_t IfcUtil::IfcBaseClass::counter_ = 0; \ No newline at end of file diff --git a/src/ifcwrap/IfcParseWrapper.i b/src/ifcwrap/IfcParseWrapper.i index 49e3cf20c5..1aeb470dbe 100644 --- a/src/ifcwrap/IfcParseWrapper.i +++ b/src/ifcwrap/IfcParseWrapper.i @@ -236,17 +236,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas } bool __eq__(IfcUtil::IfcBaseClass* other) const { - if ($self == other) { - return true; - } - if (!$self->declaration().as_entity() || !other->declaration().as_entity()) { - /// @todo - return false; - } else { - IfcUtil::IfcBaseEntity* self_ = (IfcUtil::IfcBaseEntity*) self; - IfcUtil::IfcBaseEntity* other_ = (IfcUtil::IfcBaseEntity*) other; - return self_->data().id() == other_->data().id() && self_->data().file == other_->data().file; - } + return $self->identity() == other->identity(); } std::string __repr__() const {