############################################################################### # # # This file is part of IfcOpenShell. # # # # IfcOpenShell is free software: you can redistribute it and/or modify # # it under the terms of the Lesser GNU General Public License as published by # # the Free Software Foundation, either version 3.0 of the License, or # # (at your option) any later version. # # # # IfcOpenShell is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # Lesser GNU General Public License for more details. # # # # You should have received a copy of the Lesser GNU General Public License # # along with this program. If not, see . # # # ############################################################################### header = """ #ifndef %(schema_name_upper)s_H #define %(schema_name_upper)s_H #include #include #include #include "../ifcparse/IfcUtil.h" #include "../ifcparse/IfcSchema.h" #include "../ifcparse/IfcException.h" #include "../ifcparse/%(schema_name)senum.h" const IfcParse::schema_definition& get_schema(); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4100) #endif #define IfcSchema %(schema_name)s namespace %(schema_name)s { const char* const Identifier = "%(schema_name_upper)s"; // Forward definitions %(forward_definitions)s %(declarations)s %(class_definitions)s void InitStringMap(); IfcUtil::IfcBaseClass* SchemaEntity(IfcAbstractEntity* e = 0); } #ifdef _MSC_VER #pragma warning(pop) #endif #endif """ enum_header = """ #ifndef %(schema_name_upper)sENUM_H #define %(schema_name_upper)sENUM_H #define IfcSchema %(schema_name)s namespace %(schema_name)s { namespace Type { typedef enum { %(types)s, UNDEFINED } Enum; Enum Parent(Enum v); Enum FromString(const std::string& s); std::string ToString(Enum v); bool IsSimple(Enum v); } } #endif """ lb_header = """ #ifndef %(schema_name_upper)sRT_H #define %(schema_name_upper)sRT_H #define IfcSchema %(schema_name)s #include "../ifcparse/IfcUtil.h" #include "../ifcparse/IfcEntityDescriptor.h" #include "../ifcparse/IfcWritableEntity.h" namespace %(schema_name)s { namespace Type { int GetAttributeCount(Enum t); int GetAttributeIndex(Enum t, const std::string& a); IfcUtil::ArgumentType GetAttributeType(Enum t, unsigned char a); Enum GetAttributeEntity(Enum t, unsigned char a); const std::string& GetAttributeName(Enum t, unsigned char a); bool GetAttributeOptional(Enum t, unsigned char a); bool GetAttributeDerived(Enum t, unsigned char a); std::pair GetEnumerationIndex(Enum t, const std::string& a); std::pair GetInverseAttribute(Enum t, const std::string& a); std::set GetInverseAttributeNames(Enum t); void PopulateDerivedFields(IfcWrite::IfcWritableEntity* e); }} #endif """ implementation= """ #include "../ifcparse/%(schema_name)s.h" #include "../ifcparse/IfcSchema.h" #include "../ifcparse/IfcException.h" #include "../ifcparse/IfcWrite.h" #include "../ifcparse/IfcWritableEntity.h" #include using namespace %(schema_name)s; using namespace IfcParse; using namespace IfcWrite; // External definitions %(external_definitions)s IfcUtil::IfcBaseClass* %(schema_name)s::SchemaEntity(IfcAbstractEntity* e) { switch(e->type()) { %(schema_entity_statements)s default: throw IfcException("Unable to find find keyword in schema"); break; } } std::string Type::ToString(Enum v) { if (v < 0 || v >= %(max_id)d) throw IfcException("Unable to find find keyword in schema"); const char* names[] = { %(type_name_strings)s }; return names[v]; } static std::map string_map; void %(schema_name)s::InitStringMap() { %(string_map_statements)s } Type::Enum Type::FromString(const std::string& s) { if (string_map.empty()) InitStringMap(); std::map::const_iterator it = string_map.find(s); if ( it == string_map.end() ) throw IfcException("Unable to find find keyword in schema"); else return it->second; } Type::Enum Type::Parent(Enum v){ if (v < 0 || v >= %(max_id)d) return (Enum)-1; %(parent_type_statements)s return (Enum)-1; } bool Type::IsSimple(Enum v) { return %(simple_type_statement)s; } %(enumeration_functions)s %(simple_type_impl)s %(entity_implementations)s """ lb_implementation = """ #include #include "../ifcparse/%(schema_name)s.h" #include "../ifcparse/%(schema_name)s-latebound.h" #include "../ifcparse/IfcException.h" #include "../ifcparse/IfcWrite.h" #include "../ifcparse/IfcWritableEntity.h" #include "../ifcparse/IfcUtil.h" #include "../ifcparse/IfcEntityDescriptor.h" using namespace %(schema_name)s; using namespace IfcParse; using namespace IfcWrite; using namespace IfcUtil; typedef std::map entity_descriptor_map_t; typedef std::map enumeration_descriptor_map_t; typedef std::map > > inverse_map_t; typedef std::map > derived_map_t; entity_descriptor_map_t entity_descriptor_map; enumeration_descriptor_map_t enumeration_descriptor_map; inverse_map_t inverse_map; derived_map_t derived_map; #if defined(__clang__) #elif defined(__GNUC__) || defined(__GNUG__) #pragma GCC push_options #pragma GCC optimize ("O0") #elif defined(_MSC_VER) #pragma optimize("", off) #endif void InitDescriptorMap() { IfcEntityDescriptor* current; %(entity_descriptors)s // Enumerations IfcEnumerationDescriptor* current_enum; std::vector values; %(enumeration_descriptors)s } void InitInverseMap() { %(inverse_implementations)s } void InitDerivedMap() { %(derived_field_statements)s } #if defined(__clang__) #elif defined(__GNUC__) || defined(__GNUG__) #pragma GCC pop_options #elif defined(_MSC_VER) #pragma optimize("", on) #endif int Type::GetAttributeIndex(Enum t, const std::string& a) { if (entity_descriptor_map.empty()) ::InitDescriptorMap(); std::map::const_iterator i = entity_descriptor_map.find(t); if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found"); else return i->second->getArgumentIndex(a); } int Type::GetAttributeCount(Enum t) { if (entity_descriptor_map.empty()) ::InitDescriptorMap(); std::map::const_iterator i = entity_descriptor_map.find(t); if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found"); else return i->second->getArgumentCount(); } ArgumentType Type::GetAttributeType(Enum t, unsigned char a) { if (entity_descriptor_map.empty()) ::InitDescriptorMap(); std::map::const_iterator i = entity_descriptor_map.find(t); if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found"); else return i->second->getArgumentType(a); } Type::Enum Type::GetAttributeEntity(Enum t, unsigned char a) { if (entity_descriptor_map.empty()) ::InitDescriptorMap(); std::map::const_iterator i = entity_descriptor_map.find(t); if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found"); else return i->second->getArgumentEntity(a); } const std::string& Type::GetAttributeName(Enum t, unsigned char a) { if (entity_descriptor_map.empty()) ::InitDescriptorMap(); std::map::const_iterator i = entity_descriptor_map.find(t); if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found"); else return i->second->getArgumentName(a); } bool Type::GetAttributeOptional(Enum t, unsigned char a) { if (entity_descriptor_map.empty()) ::InitDescriptorMap(); std::map::const_iterator i = entity_descriptor_map.find(t); if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found"); else return i->second->getArgumentOptional(a); } bool Type::GetAttributeDerived(Enum t, unsigned char a) { if (derived_map.empty()) ::InitDerivedMap(); std::map >::const_iterator i = derived_map.find(t); return i != derived_map.end() && i->second.find(a) != i->second.end(); } std::pair Type::GetEnumerationIndex(Enum t, const std::string& a) { if (enumeration_descriptor_map.empty()) ::InitDescriptorMap(); std::map::const_iterator i = enumeration_descriptor_map.find(t); if ( i == enumeration_descriptor_map.end() ) throw IfcException("Value not found"); else return i->second->getIndex(a); } std::pair Type::GetInverseAttribute(Enum t, const std::string& a) { if (inverse_map.empty()) ::InitInverseMap(); inverse_map_t::const_iterator it; inverse_map_t::mapped_type::const_iterator jt; for(;;) { it = inverse_map.find(t); if (it != inverse_map.end()) { jt = it->second.find(a); if (jt != it->second.end()) { return jt->second; } } if ((t = Parent(t)) == -1) break; } throw IfcException("Attribute not found"); } std::set Type::GetInverseAttributeNames(Enum t) { if (inverse_map.empty()) ::InitInverseMap(); inverse_map_t::const_iterator it; inverse_map_t::mapped_type::const_iterator jt; std::set return_value; for (;;) { it = inverse_map.find(t); if (it != inverse_map.end()) { for (jt = it->second.begin(); jt != it->second.end(); ++jt) { return_value.insert(jt->first); } } if ((t = Parent(t)) == -1) break; } return return_value; } void Type::PopulateDerivedFields(IfcWrite::IfcWritableEntity* e) { std::map >::const_iterator i = derived_map.find(e->type()); if (i != derived_map.end()) { for (std::set::const_iterator it = i->second.begin(); it != i->second.end(); ++it) { e->setArgumentDerived(*it); } } } """ entity_descriptor = """ current = entity_descriptor_map[Type::%(type)s] = new IfcEntityDescriptor(Type::%(type)s,%(parent_statement)s); %(entity_descriptor_attributes)s""" entity_descriptor_parent = "entity_descriptor_map.find(Type::%(type)s)->second" entity_descriptor_attribute_without_entity = ' current->add("%(name)s",%(optional)s,%(type)s);' entity_descriptor_attribute_with_entity = ' current->add("%(name)s",%(optional)s,%(type)s,Type::%(entity_name)s);' enumeration_descriptor = """ values.clear(); values.reserve(128); %(enumeration_descriptor_values)s current_enum = enumeration_descriptor_map[Type::%(type)s] = new IfcEnumerationDescriptor(Type::%(type)s, values);""" enumeration_descriptor_value = ' values.push_back("%(name)s");' derived_field_statement = ' {std::set idxs; %(statements)sderived_map[Type::%(type)s] = idxs;}'; derived_field_statement_attrs = 'idxs.insert(%d); ' simpletype = """%(documentation)s class %(name)s : public %(superclass)s { public: virtual const IfcParse::type_declaration& declaration() const; static Type::Enum Class(); explicit %(name)s (IfcAbstractEntity* e); %(name)s (%(type)s v); operator %(type)s() const; }; """ simpletype_impl_comment = "// Function implementations for %(name)s" simpletype_impl_argument_type = "if (i == 0) { return %(attr_type)s; } else { throw IfcParse::IfcAttributeOutOfRangeException(\"Argument index out of range\"); }" simpletype_impl_argument = "return data_->getArgument(i);" simpletype_impl_is_with_supertype = "return v == Type::%(class_name)s || %(superclass)s::is(v);" simpletype_impl_is_without_supertype = "return v == %(class_name)s::Class();" simpletype_impl_type = "return Type::%(class_name)s;" simpletype_impl_class = "return Type::%(class_name)s;" simpletype_impl_explicit_constructor = "data_ = e;" simpletype_impl_constructor = "IfcWritableEntity* e = new IfcWritableEntity(Type::%(class_name)s); e->setArgument(0, v); data_ = e;" simpletype_impl_constructor_templated = "IfcWritableEntity* e = new IfcWritableEntity(Type::%(class_name)s); e->setArgument(0, v->generalize()); data_ = e;" simpletype_impl_cast = "return *data_->getArgument(0);" simpletype_impl_cast_templated = "IfcEntityList::ptr es = *data_->getArgument(0); return es->as<%(underlying_type)s>();" simpletype_impl_declaration = "return *%(class_name)s_type;" select = """%(documentation)s typedef IfcUtil::IfcBaseClass %(name)s; """ enumeration = """namespace %(name)s { %(documentation)s typedef enum {%(values)s} %(name)s; const char* ToString(%(name)s v); %(name)s FromString(const std::string& s); } """ entity = """%(documentation)s class %(name)s %(superclass)s{ public: %(attributes)s %(inverse)s virtual const IfcParse::entity& declaration() const; static Type::Enum Class(); %(name)s (IfcAbstractEntity* e); %(name)s (%(constructor_arguments)s); typedef IfcTemplatedEntityList< %(name)s > list; }; """ enumeration_function=""" const char* %(name)s::ToString(%(name)s v) { if ( v < 0 || v >= %(max_id)d ) throw IfcException("Unable to find find keyword in schema"); const char* names[] = { %(values)s }; return names[v]; } %(name)s::%(name)s %(name)s::FromString(const std::string& s) { %(from_string_statements)s throw IfcException("Unable to find find keyword in schema"); } """ entity_implementation = """// Function implementations for %(name)s %(attributes)s %(inverse)s const IfcParse::entity& %(name)s::declaration() const { return *%(name)s_type; } Type::Enum %(name)s::Class() { return Type::%(name)s; } %(name)s::%(name)s(IfcAbstractEntity* e) : %(superclass)s { if (!e) return; if (!e->is(Type::%(name)s)) throw IfcException("Unable to find find keyword in schema"); data_ = e; } %(name)s::%(name)s(%(constructor_arguments)s) : %(superclass)s { IfcWritableEntity* e = new IfcWritableEntity(Class());%(constructor_implementation)s data_ = e; EntityBuffer::Add(this); } """ optional_attribute_description = "/// Whether the optional attribute %s is defined for this %s" function = "%(return_type)s %(class_name)s::%(name)s(%(arguments)s) { %(body)s }" const_function = "%(return_type)s %(class_name)s::%(name)s(%(arguments)s) const { %(body)s }" constructor = "%(class_name)s::%(class_name)s(%(arguments)s) { %(body)s }" constructor_single_initlist = "%(class_name)s::%(class_name)s(%(arguments)s) : %(superclass)s(%(superclass_init)s) { %(body)s }" cast_function = "%(class_name)s::operator %(return_type)s() const { %(body)s }" array_type = "std::vector< %(instance_type)s > /*[%(lower)s:%(upper)s]*/" nested_array_type = "std::vector< std::vector< %(instance_type)s > >" list_type = "IfcTemplatedEntityList< %(instance_type)s >::ptr" list_list_type = "IfcTemplatedEntityListList< %(instance_type)s >::ptr" untyped_list = "IfcEntityList::ptr" inverse_attr = "IfcTemplatedEntityList< %(entity)s >::ptr %(name)s() const; // INVERSE %(entity)s::%(attribute)s" enum_from_string_stmt = ' if (s == "%(value)s") return ::%(schema_name)s::%(name)s::%(short_name)s_%(value)s;' schema_entity_stmt = ' case Type::%(name)s: return new %(name)s(e); break;' string_map_statement = ' string_map["%(uppercase_name)s"%(padding)s] = Type::%(name)s;' parent_type_stmt = ' if(v==%(name)s%(padding)s) { return %(parent)s; }' parent_type_test = " || %s::is(v)" optional_attr_stmt = "return !data_->getArgument(%(index)d)->isNull();" get_attr_stmt = "return *data_->getArgument(%(index)d);" get_attr_stmt_enum = "return %(type)s::FromString(*data_->getArgument(%(index)d));" get_attr_stmt_entity = "return (%(type)s)((IfcUtil::IfcBaseClass*)(*data_->getArgument(%(index)d)));" get_attr_stmt_array = "IfcEntityList::ptr es = *data_->getArgument(%(index)d); return es->as<%(list_instance_type)s>();" get_attr_stmt_nested_array = "IfcEntityListList::ptr es = *data_->getArgument(%(index)d); return es->as<%(list_instance_type)s>();" get_inverse = "return data_->getInverse(Type::%(type)s, %(index)d)->as<%(type)s>();" set_attr_stmt = "if ( ! data_->isWritable() ) { data_ = new IfcWritableEntity(data_); } ((IfcWritableEntity*)data_)->setArgument(%(index)d,v);" set_attr_stmt_enum = "if ( ! data_->isWritable() ) { data_ = new IfcWritableEntity(data_); } ((IfcWritableEntity*)data_)->setArgument(%(index)d,v,%(type)s::ToString(v));" set_attr_stmt_array = "if ( ! data_->isWritable() ) { data_ = new IfcWritableEntity(data_); } ((IfcWritableEntity*)data_)->setArgument(%(index)d,v->generalize());" constructor_stmt = " e->setArgument(%(index)d,(%(name)s));" constructor_stmt_enum = " e->setArgument(%(index)d,%(name)s,%(type)s::ToString(%(name)s));" constructor_stmt_array = " e->setArgument(%(index)d,(%(name)s)->generalize());" constructor_stmt_optional = " if (%(name)s) {%(stmt)s } else { e->setArgument(%(index)d); }" constructor_stmt_derived = " e->setArgumentDerived(%(index)d);" inverse_implementation = " inverse_map[Type::%(type)s].insert(std::make_pair(\"%(name)s\", std::make_pair(Type::%(related_type)s, %(index)d)));" def multi_line_comment(li): return ("/// %s"%("\n/// ".join(li))) if len(li) else ""