diff --git a/src/ifcopenshell-python/ifcopenshell/express/schema_class.py b/src/ifcopenshell-python/ifcopenshell/express/schema_class.py index f6be4e888e..ba38778175 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/schema_class.py +++ b/src/ifcopenshell-python/ifcopenshell/express/schema_class.py @@ -283,10 +283,22 @@ __attribute__((optnone)) self.statements.extend( ( - "const schema_definition& %s::get_schema() {" % schema_name_title, + "static std::unique_ptr schema;", "", - " static const schema_definition* s = %(schema_name)s_populate_schema();" % locals(), - " return *s;", + "void %s::clear_schema() {" % schema_name_title, + " schema.reset();", + "}", + "", + ) + ) + + self.statements.extend( + ( + "const schema_definition& %s::get_schema() {" % schema_name_title, + " if (!schema) {", + " schema.reset(%(schema_name)s_populate_schema());" % locals(), + " }", + " return *schema;", "}", "", "", diff --git a/src/ifcopenshell-python/ifcopenshell/express/templates.py b/src/ifcopenshell-python/ifcopenshell/express/templates.py index af9ad4d1e9..f52580f516 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/templates.py +++ b/src/ifcopenshell-python/ifcopenshell/express/templates.py @@ -38,6 +38,8 @@ struct %(schema_name)s { IFC_PARSE_API static const IfcParse::schema_definition& get_schema(); +IFC_PARSE_API static void clear_schema(); + static const char* const Identifier; // Forward definitions diff --git a/src/ifcparse/Ifc2x3-schema.cpp b/src/ifcparse/Ifc2x3-schema.cpp index 09168c89db..06ad4c3a2a 100644 --- a/src/ifcparse/Ifc2x3-schema.cpp +++ b/src/ifcparse/Ifc2x3-schema.cpp @@ -12533,9 +12533,16 @@ IfcParse::schema_definition* IFC2X3_populate_schema() { #pragma optimize("", on) #endif -const schema_definition& Ifc2x3::get_schema() { +static std::unique_ptr schema; - static const schema_definition* s = IFC2X3_populate_schema(); - return *s; +void Ifc2x3::clear_schema() { + schema.reset(); +} + +const schema_definition& Ifc2x3::get_schema() { + if (!schema) { + schema.reset(IFC2X3_populate_schema()); + } + return *schema; } diff --git a/src/ifcparse/Ifc2x3.h b/src/ifcparse/Ifc2x3.h index 0be1e861d7..a9ff0fbf90 100644 --- a/src/ifcparse/Ifc2x3.h +++ b/src/ifcparse/Ifc2x3.h @@ -44,6 +44,8 @@ struct Ifc2x3 { IFC_PARSE_API static const IfcParse::schema_definition& get_schema(); +IFC_PARSE_API static void clear_schema(); + static const char* const Identifier; // Forward definitions diff --git a/src/ifcparse/Ifc4-schema.cpp b/src/ifcparse/Ifc4-schema.cpp index 9263819618..5e8d1add16 100644 --- a/src/ifcparse/Ifc4-schema.cpp +++ b/src/ifcparse/Ifc4-schema.cpp @@ -15071,9 +15071,16 @@ IfcParse::schema_definition* IFC4_populate_schema() { #pragma optimize("", on) #endif -const schema_definition& Ifc4::get_schema() { +static std::unique_ptr schema; - static const schema_definition* s = IFC4_populate_schema(); - return *s; +void Ifc4::clear_schema() { + schema.reset(); +} + +const schema_definition& Ifc4::get_schema() { + if (!schema) { + schema.reset(IFC4_populate_schema()); + } + return *schema; } diff --git a/src/ifcparse/Ifc4.h b/src/ifcparse/Ifc4.h index 2a0652b192..8b80139d29 100644 --- a/src/ifcparse/Ifc4.h +++ b/src/ifcparse/Ifc4.h @@ -44,6 +44,8 @@ struct Ifc4 { IFC_PARSE_API static const IfcParse::schema_definition& get_schema(); +IFC_PARSE_API static void clear_schema(); + static const char* const Identifier; // Forward definitions diff --git a/src/ifcparse/Ifc4x1-schema.cpp b/src/ifcparse/Ifc4x1-schema.cpp index d442a761bf..277c319cc6 100644 --- a/src/ifcparse/Ifc4x1-schema.cpp +++ b/src/ifcparse/Ifc4x1-schema.cpp @@ -15472,9 +15472,16 @@ IfcParse::schema_definition* IFC4X1_populate_schema() { #pragma optimize("", on) #endif -const schema_definition& Ifc4x1::get_schema() { +static std::unique_ptr schema; - static const schema_definition* s = IFC4X1_populate_schema(); - return *s; +void Ifc4x1::clear_schema() { + schema.reset(); +} + +const schema_definition& Ifc4x1::get_schema() { + if (!schema) { + schema.reset(IFC4X1_populate_schema()); + } + return *schema; } diff --git a/src/ifcparse/Ifc4x1.h b/src/ifcparse/Ifc4x1.h index 72ddc03341..c2e6ba7490 100644 --- a/src/ifcparse/Ifc4x1.h +++ b/src/ifcparse/Ifc4x1.h @@ -44,6 +44,8 @@ struct Ifc4x1 { IFC_PARSE_API static const IfcParse::schema_definition& get_schema(); +IFC_PARSE_API static void clear_schema(); + static const char* const Identifier; // Forward definitions diff --git a/src/ifcparse/Ifc4x2-schema.cpp b/src/ifcparse/Ifc4x2-schema.cpp index 100ce7795f..0a9f35563f 100644 --- a/src/ifcparse/Ifc4x2-schema.cpp +++ b/src/ifcparse/Ifc4x2-schema.cpp @@ -15808,9 +15808,16 @@ IfcParse::schema_definition* IFC4X2_populate_schema() { #pragma optimize("", on) #endif -const schema_definition& Ifc4x2::get_schema() { +static std::unique_ptr schema; - static const schema_definition* s = IFC4X2_populate_schema(); - return *s; +void Ifc4x2::clear_schema() { + schema.reset(); +} + +const schema_definition& Ifc4x2::get_schema() { + if (!schema) { + schema.reset(IFC4X2_populate_schema()); + } + return *schema; } diff --git a/src/ifcparse/Ifc4x2.h b/src/ifcparse/Ifc4x2.h index 832b401d23..5be96d9c8c 100644 --- a/src/ifcparse/Ifc4x2.h +++ b/src/ifcparse/Ifc4x2.h @@ -44,6 +44,8 @@ struct Ifc4x2 { IFC_PARSE_API static const IfcParse::schema_definition& get_schema(); +IFC_PARSE_API static void clear_schema(); + static const char* const Identifier; // Forward definitions diff --git a/src/ifcparse/Ifc4x3_rc1-schema.cpp b/src/ifcparse/Ifc4x3_rc1-schema.cpp index 643f2101bf..01fc5d876b 100644 --- a/src/ifcparse/Ifc4x3_rc1-schema.cpp +++ b/src/ifcparse/Ifc4x3_rc1-schema.cpp @@ -17143,9 +17143,16 @@ IfcParse::schema_definition* IFC4X3_RC1_populate_schema() { #pragma optimize("", on) #endif -const schema_definition& Ifc4x3_rc1::get_schema() { +static std::unique_ptr schema; - static const schema_definition* s = IFC4X3_RC1_populate_schema(); - return *s; +void Ifc4x3_rc1::clear_schema() { + schema.reset(); +} + +const schema_definition& Ifc4x3_rc1::get_schema() { + if (!schema) { + schema.reset(IFC4X3_RC1_populate_schema()); + } + return *schema; } diff --git a/src/ifcparse/Ifc4x3_rc1.h b/src/ifcparse/Ifc4x3_rc1.h index 970c7d88cf..0d49d07989 100644 --- a/src/ifcparse/Ifc4x3_rc1.h +++ b/src/ifcparse/Ifc4x3_rc1.h @@ -44,6 +44,8 @@ struct Ifc4x3_rc1 { IFC_PARSE_API static const IfcParse::schema_definition& get_schema(); +IFC_PARSE_API static void clear_schema(); + static const char* const Identifier; // Forward definitions diff --git a/src/ifcparse/Ifc4x3_rc2-schema.cpp b/src/ifcparse/Ifc4x3_rc2-schema.cpp index 944de6b57a..bc307a9205 100644 --- a/src/ifcparse/Ifc4x3_rc2-schema.cpp +++ b/src/ifcparse/Ifc4x3_rc2-schema.cpp @@ -17245,9 +17245,16 @@ IfcParse::schema_definition* IFC4X3_RC2_populate_schema() { #pragma optimize("", on) #endif -const schema_definition& Ifc4x3_rc2::get_schema() { +static std::unique_ptr schema; - static const schema_definition* s = IFC4X3_RC2_populate_schema(); - return *s; +void Ifc4x3_rc2::clear_schema() { + schema.reset(); +} + +const schema_definition& Ifc4x3_rc2::get_schema() { + if (!schema) { + schema.reset(IFC4X3_RC2_populate_schema()); + } + return *schema; } diff --git a/src/ifcparse/Ifc4x3_rc2.h b/src/ifcparse/Ifc4x3_rc2.h index 9648cad06e..473b69a065 100644 --- a/src/ifcparse/Ifc4x3_rc2.h +++ b/src/ifcparse/Ifc4x3_rc2.h @@ -44,6 +44,8 @@ struct Ifc4x3_rc2 { IFC_PARSE_API static const IfcParse::schema_definition& get_schema(); +IFC_PARSE_API static void clear_schema(); + static const char* const Identifier; // Forward definitions diff --git a/src/ifcparse/Ifc4x3_rc3-schema.cpp b/src/ifcparse/Ifc4x3_rc3-schema.cpp index eac792db0a..68b4918a47 100644 --- a/src/ifcparse/Ifc4x3_rc3-schema.cpp +++ b/src/ifcparse/Ifc4x3_rc3-schema.cpp @@ -17122,9 +17122,16 @@ IfcParse::schema_definition* IFC4X3_RC3_populate_schema() { #pragma optimize("", on) #endif -const schema_definition& Ifc4x3_rc3::get_schema() { +static std::unique_ptr schema; - static const schema_definition* s = IFC4X3_RC3_populate_schema(); - return *s; +void Ifc4x3_rc3::clear_schema() { + schema.reset(); +} + +const schema_definition& Ifc4x3_rc3::get_schema() { + if (!schema) { + schema.reset(IFC4X3_RC3_populate_schema()); + } + return *schema; } diff --git a/src/ifcparse/Ifc4x3_rc3.h b/src/ifcparse/Ifc4x3_rc3.h index 1cc2ffcd4a..0ba741a6e1 100644 --- a/src/ifcparse/Ifc4x3_rc3.h +++ b/src/ifcparse/Ifc4x3_rc3.h @@ -44,6 +44,8 @@ struct Ifc4x3_rc3 { IFC_PARSE_API static const IfcParse::schema_definition& get_schema(); +IFC_PARSE_API static void clear_schema(); + static const char* const Identifier; // Forward definitions diff --git a/src/ifcparse/Ifc4x3_rc4-schema.cpp b/src/ifcparse/Ifc4x3_rc4-schema.cpp index edab421d43..0c875db269 100644 --- a/src/ifcparse/Ifc4x3_rc4-schema.cpp +++ b/src/ifcparse/Ifc4x3_rc4-schema.cpp @@ -17136,9 +17136,16 @@ IfcParse::schema_definition* IFC4X3_RC4_populate_schema() { #pragma optimize("", on) #endif -const schema_definition& Ifc4x3_rc4::get_schema() { +static std::unique_ptr schema; - static const schema_definition* s = IFC4X3_RC4_populate_schema(); - return *s; +void Ifc4x3_rc4::clear_schema() { + schema.reset(); +} + +const schema_definition& Ifc4x3_rc4::get_schema() { + if (!schema) { + schema.reset(IFC4X3_RC4_populate_schema()); + } + return *schema; } diff --git a/src/ifcparse/Ifc4x3_rc4.h b/src/ifcparse/Ifc4x3_rc4.h index 2a35062a95..e27ef42f96 100644 --- a/src/ifcparse/Ifc4x3_rc4.h +++ b/src/ifcparse/Ifc4x3_rc4.h @@ -44,6 +44,8 @@ struct Ifc4x3_rc4 { IFC_PARSE_API static const IfcParse::schema_definition& get_schema(); +IFC_PARSE_API static void clear_schema(); + static const char* const Identifier; // Forward definitions diff --git a/src/ifcparse/IfcSchema.cpp b/src/ifcparse/IfcSchema.cpp index e9b479aae6..9f4fcf6c02 100644 --- a/src/ifcparse/IfcSchema.cpp +++ b/src/ifcparse/IfcSchema.cpp @@ -37,6 +37,14 @@ bool IfcParse::named_type::is(const IfcParse::declaration& decl) const { return declared_type()->is(decl); } +IfcParse::entity::~entity() { + for (auto attribute : attributes_) { + delete attribute; + } + for (auto inverse_attribute : inverse_attributes_) { + delete inverse_attribute; + } +} static std::map schemas; IfcParse::schema_definition::schema_definition(const std::string& name, const std::vector& declarations, instance_factory* factory) @@ -61,6 +69,7 @@ IfcParse::schema_definition::~schema_definition() { for (std::vector::const_iterator it = declarations_.begin(); it != declarations_.end(); ++it) { delete *it; } + delete factory_; } IfcUtil::IfcBaseClass* IfcParse::schema_definition::instantiate(IfcEntityInstanceData * data) const { @@ -149,3 +158,36 @@ std::vector IfcParse::schema_names() { return return_value; } + +void IfcParse::clear_schemas() { +#ifdef HAS_SCHEMA_2x3 + Ifc2x3::clear_schema(); +#endif +#ifdef HAS_SCHEMA_4 + Ifc4::clear_schema(); +#endif +#ifdef HAS_SCHEMA_4x1 + Ifc4x1::clear_schema(); +#endif +#ifdef HAS_SCHEMA_4x2 + Ifc4x2::clear_schema(); +#endif +#ifdef HAS_SCHEMA_4x3_rc1 + Ifc4x3_rc1::clear_schema(); +#endif +#ifdef HAS_SCHEMA_4x3_rc2 + Ifc4x3_rc2::clear_schema(); +#endif +#ifdef HAS_SCHEMA_4x3_rc3 + Ifc4x3_rc3::clear_schema(); +#endif +#ifdef HAS_SCHEMA_4x3_rc4 + Ifc4x3_rc4::clear_schema(); +#endif + + // clear any remaining registered schemas + // we pop schemas until map is empty, because map iteration is invalidated after each erasure + while (!schemas.empty()) { + delete schemas.begin()->second; + } +} diff --git a/src/ifcparse/IfcSchema.h b/src/ifcparse/IfcSchema.h index 5b7c805429..b11a115982 100644 --- a/src/ifcparse/IfcSchema.h +++ b/src/ifcparse/IfcSchema.h @@ -55,6 +55,8 @@ namespace IfcParse { class IFC_PARSE_API parameter_type { public: + virtual ~parameter_type() {} + virtual const named_type* as_named_type() const { return static_cast(0); } virtual const simple_type* as_simple_type() const { return static_cast(0); } virtual const aggregation_type* as_aggregation_type() const { return static_cast(0); } @@ -107,6 +109,8 @@ namespace IfcParse { , type_of_element_(type_of_element) {} + virtual ~aggregation_type() { delete type_of_element_; } + aggregate_type type_of_aggregation() const { return type_of_aggregation_; } int bound1() const { return bound1_; } int bound2() const { return bound2_; } @@ -160,6 +164,8 @@ namespace IfcParse { : declaration(name, index_in_schema) , declared_type_(declared_type) {} + virtual ~type_declaration() { delete declared_type_; } + const parameter_type* declared_type() const { return declared_type_; } virtual const type_declaration* as_type_declaration() const { return this; } @@ -203,6 +209,8 @@ namespace IfcParse { , type_of_attribute_(type_of_attribute) , optional_(optional) {} + ~attribute() { delete type_of_attribute_; } + const std::string& name() const { return name_; } const parameter_type* type_of_attribute() const { return type_of_attribute_; } bool optional() const { return optional_; } @@ -277,6 +285,8 @@ namespace IfcParse { , supertype_(supertype) {} + virtual ~entity(); + bool is(const std::string& name) const { if (name == name_) return true; else if (supertype_) return supertype_->is(name); @@ -387,6 +397,8 @@ namespace IfcParse { class IFC_PARSE_API instance_factory { public: + virtual ~instance_factory() {} + virtual IfcUtil::IfcBaseClass* operator()(IfcEntityInstanceData* data) const = 0; }; @@ -453,6 +465,8 @@ namespace IfcParse { IFC_PARSE_API std::vector schema_names(); IFC_PARSE_API void register_schema(schema_definition*); + + IFC_PARSE_API void clear_schemas(); } #endif