Begin phasing out type enumeration in favour of declaration pointers

This commit is contained in:
Thomas Krijnen
2017-12-13 13:16:49 +01:00
parent 33fc2080df
commit 85515e904e
15 changed files with 10463 additions and 10419 deletions
+1 -1
View File
@@ -210,7 +210,7 @@ class Implementation(codegen.Base):
simple_type_impl.append(templates.simpletype_impl_comment % {'name': class_name})
simple_type_impl.extend(map(compose, map(lambda x: (class_name, attr_type, superclass, "(IfcEntityInstanceData*)0")+x, (
('Class', templates.function, 'Type::Enum', (), templates.simpletype_impl_class ),
('Class', templates.function, 'const IfcParse::type_declaration&', (), templates.simpletype_impl_class ),
('declaration', templates.const_function, 'const IfcParse::type_declaration&', (), templates.simpletype_impl_declaration ),
('', constructor, '', ('IfcEntityInstanceData* e',), templates.simpletype_impl_explicit_constructor),
('', constructor, '', ("%s v" % type_str,), simpletype_impl_constructor ),
+46 -10
View File
@@ -29,6 +29,8 @@ class SchemaClass(codegen.Base):
class UnmetDependenciesException(Exception): pass
schema_name = mapping.schema.name
self.schema_name = schema_name_title = schema_name.capitalize()
declared_types = []
def get_declared_type(type, emitted_names=None):
@@ -68,12 +70,12 @@ class SchemaClass(codegen.Base):
else:
raise Exception("No declared type for <%r>" % type)
self.schema_name = mapping.schema.name.capitalize()
statements = ['',
'#include "../ifcparse/IfcSchema.h"',
'#include "../ifcparse/%(schema_name_title)s.h"' % locals(),
'',
'using namespace IfcParse;'
'using namespace IfcParse;',
'using namespace %(schema_name_title)s;' % locals(),
'']
collections_by_type = (('entity', mapping.schema.entities ),
@@ -84,13 +86,17 @@ class SchemaClass(codegen.Base):
for cpp_type, collection in collections_by_type:
for name in collection.keys():
statements.append('%(cpp_type)s* %(name)s_type = 0;' % locals())
declarations_by_index = []
statements.append("{factory_placeholder}")
statements.append("""
#ifdef _MSC_VER
#pragma optimize("", off)
#endif
""")
statements.append('schema_definition* populate_schema() {')
statements.append('IfcParse::schema_definition* populate_schema() {')
emitted_types = set()
while len(emitted_types) < len(mapping.schema.simpletypes):
@@ -103,19 +109,21 @@ class SchemaClass(codegen.Base):
# print("Unmet", repr(name))
continue
statements.append(' %(name)s_type = new type_declaration(IfcSchema::Type::%(name)s, %(declared_type)s);' % locals())
statements.append(' %(name)s_type = new type_declaration("%(name)s", %%(index_in_schema_%(name)s)d, %(declared_type)s);' % locals())
emitted_types.add(name.lower())
declared_types.append('%(name)s_type' % locals())
declarations_by_index.append(name)
for name, enum in mapping.schema.enumerations.items():
statements.append(' {')
statements.append(' std::vector<std::string> items; items.reserve(%d);' % len(enum.values))
statements.extend(map(lambda v: ' items.push_back("%s");' % v, sorted(enum.values)))
statements.append(' %(name)s_type = new enumeration_type(IfcSchema::Type::%(name)s, items);' % locals())
statements.append(' %(name)s_type = new enumeration_type("%(name)s", %%(index_in_schema_%(name)s)d, items);' % locals())
statements.append(' }')
declared_types.append('%(name)s_type' % locals())
declarations_by_index.append(name)
emitted_entities = set()
while len(emitted_entities) < len(mapping.schema.entities):
@@ -123,10 +131,11 @@ class SchemaClass(codegen.Base):
if name.lower() in emitted_entities: continue
if len(type.supertypes) == 0 or set(map(lambda s: s.lower(), type.supertypes)) < emitted_entities:
supertype = '0' if len(type.supertypes) == 0 else '%s_type' % type.supertypes[0]
statements.append(' %(name)s_type = new entity(IfcSchema::Type::%(name)s, %(supertype)s);' % locals())
statements.append(' %(name)s_type = new entity("%(name)s", %%(index_in_schema_%(name)s)d, %(supertype)s);' % locals())
emitted_entities.add(name.lower())
declared_types.append('%(name)s_type' % locals())
declarations_by_index.append(name)
emmited = emitted_types | emitted_entities | set(mapping.schema.enumerations.keys())
@@ -138,12 +147,13 @@ class SchemaClass(codegen.Base):
statements.append(' {')
statements.append(' std::vector<const declaration*> items; items.reserve(%d);' % len(type.values))
statements.extend(map(lambda v: ' items.push_back(%s_type);' % v, sorted(type.values)))
statements.append(' %(name)s_type = new select_type(IfcSchema::Type::%(name)s, items);' % locals())
statements.append(' %(name)s_type = new select_type("%(name)s", %%(index_in_schema_%(name)s)d, items);' % locals())
statements.append(' }')
emitted_selects.add(name.lower())
emmited.add(name)
declared_types.append('%(name)s_type' % locals())
declarations_by_index.append(name)
num_declarations = len(declared_types)
@@ -184,7 +194,7 @@ class SchemaClass(codegen.Base):
for type_name in declared_types:
statements.append(' declarations.push_back(%(type_name)s);' % locals())
statements.append(' return new schema_definition("%(schema_name)s", declarations, true);' % locals())
statements.append(' return new schema_definition("%(schema_name)s", declarations, new %(schema_name)s_instance_factory());' % locals())
statements.extend(('}',''))
@@ -202,7 +212,33 @@ class SchemaClass(codegen.Base):
' return *s;',
'}','}','',''))
self.str = "\n".join(statements)
declarations_by_index.sort()
declarations_by_index_map = dict(("index_in_schema_%s" % j,i) for i,j in enumerate(declarations_by_index))
def bind(s):
if "%" in s: return s % declarations_by_index_map
else: return s
can_be_instantiated_set = set(list(mapping.schema.entities.keys()) + list(mapping.schema.simpletypes.keys()))
def can_be_instantiated(idx_name):
name = idx_name[1]
return name in can_be_instantiated_set
instance_mapping = """switch(data->type()->index_in_schema()) {
%s
default: throw IfcParse::IfcException(data->type()->name() + " cannot be instantiated");
}
""" % "\n ".join(map(lambda tup: "case %d: return new %s(data);" % tup, filter(can_be_instantiated, enumerate(declarations_by_index))))
statements[statements.index("{factory_placeholder}")] = """
class %(schema_name)s_instance_factory : public IfcParse::instance_factory {
virtual IfcUtil::IfcBaseClass* operator()(IfcEntityInstanceData* data) const {
%(instance_mapping)s
}
};
""" % locals()
self.str = "\n".join(map(bind, statements))
self.file_name = '%s-schema.cpp'%self.schema_name
+11 -19
View File
@@ -51,7 +51,6 @@ const char* const Identifier = "%(schema_name_upper)s";
%(class_definitions)s
IFC_PARSE_API void InitStringMap();
IFC_PARSE_API IfcUtil::IfcBaseClass* SchemaEntity(IfcEntityInstanceData* e = 0);
}
#endif
@@ -128,13 +127,6 @@ using namespace IfcWrite;
// External definitions
%(external_definitions)s
IfcUtil::IfcBaseClass* %(schema_name)s::SchemaEntity(IfcEntityInstanceData* e) {
switch(e->type()) {
%(schema_entity_statements)s
default: throw IfcException("Unable to find find keyword in schema"); break;
}
}
const std::string& Type::ToString(Enum v) {
if (v < 0 || v >= %(max_id)d) throw IfcException("Unable to find find keyword in schema");
static std::string names[] = { %(type_name_strings)s };
@@ -361,7 +353,7 @@ simpletype = """%(documentation)s
class IFC_PARSE_API %(name)s : public %(superclass)s {
public:
virtual const IfcParse::type_declaration& declaration() const;
static Type::Enum Class();
static const IfcParse::type_declaration& Class();
explicit %(name)s (IfcEntityInstanceData* e);
%(name)s (%(type)s v);
operator %(type)s() const;
@@ -371,13 +363,13 @@ public:
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_is_with_supertype = "return v == %(class_name)s_type || %(superclass)s::is(v);"
simpletype_impl_is_without_supertype = "return v == %(class_name)s_type;"
simpletype_impl_type = "return *%(class_name)s_type;"
simpletype_impl_class = "return *%(class_name)s_type;"
simpletype_impl_explicit_constructor = "data_ = e;"
simpletype_impl_constructor = "data_ = new IfcEntityInstanceData(Class()); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v" +"); data_->setArgument(0, attr);}"
simpletype_impl_constructor_templated = "data_ = new IfcEntityInstanceData(Class()); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v->generalize()); data_->setArgument(0, attr);}"
simpletype_impl_constructor = "data_ = new IfcEntityInstanceData(%(class_name)s_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v" +"); data_->setArgument(0, attr);}"
simpletype_impl_constructor_templated = "data_ = new IfcEntityInstanceData(%(class_name)s_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v->generalize()); data_->setArgument(0, attr);}"
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;"
@@ -398,7 +390,7 @@ entity = """%(documentation)s
class IFC_PARSE_API %(name)s %(superclass)s{
public:
%(attributes)s %(inverse)s virtual const IfcParse::entity& declaration() const;
static Type::Enum Class();
static const IfcParse::entity& Class();
%(name)s (IfcEntityInstanceData* e);
%(name)s (%(constructor_arguments)s);
typedef IfcTemplatedEntityList< %(name)s > list;
@@ -422,9 +414,9 @@ 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(IfcEntityInstanceData* e) : %(superclass)s { if (!e) return; if (e->type() != Type::%(name)s) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
%(name)s::%(name)s(%(constructor_arguments)s) : %(superclass)s {data_ = new IfcEntityInstanceData(Class()); %(constructor_implementation)s }
const IfcParse::entity& %(name)s::Class() { return *%(name)s_type; }
%(name)s::%(name)s(IfcEntityInstanceData* e) : %(superclass)s { if (!e) return; if (e->type() != %(name)s_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
%(name)s::%(name)s(%(constructor_arguments)s) : %(superclass)s {data_ = new IfcEntityInstanceData(%(name)s_type); %(constructor_implementation)s }
"""
optional_attribute_description = "/// Whether the optional attribute %s is defined for this %s"
File diff suppressed because it is too large Load Diff
+2193 -2969
View File
File diff suppressed because one or more lines are too long
+770 -771
View File
File diff suppressed because it is too large Load Diff
+2079 -1167
View File
File diff suppressed because it is too large Load Diff
+2566 -3471
View File
File diff suppressed because one or more lines are too long
+899 -900
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -44,7 +44,7 @@ public:
template <class U>
typename U::list::ptr as() {
typename U::list::ptr r(new typename U::list);
const bool all = U::Class() == IfcSchema::Type::UNDEFINED;
const bool all = !U::Class().as_entity();
for (it i = begin(); i != end(); ++i) if (all || (*i)->declaration().is(U::Class())) r->push((U*)*i);
return r;
}
+10 -10
View File
@@ -35,7 +35,7 @@ namespace IfcParse {
/// and provide access to the entities in an IFC file
class IFC_PARSE_API IfcFile {
public:
typedef std::map<IfcSchema::Type::Enum, IfcEntityList::ptr> entities_by_type_t;
typedef std::map<const IfcParse::declaration*, IfcEntityList::ptr> entities_by_type_t;
typedef std::map<unsigned int, IfcUtil::IfcBaseClass*> entity_by_id_t;
typedef std::map<std::string, IfcSchema::IfcRoot*> entity_by_guid_t;
typedef std::map<unsigned int, std::vector<unsigned int> > entities_by_ref_t;
@@ -58,7 +58,7 @@ public:
}
const std::string& as_string() const {
return IfcSchema::Type::ToString(**this);
return (**this)->name();
}
};
@@ -119,8 +119,8 @@ public:
/// NOTE: This also returns subtypes of the requested type, for example:
/// IfcWall will also return IfcWallStandardCase entities
template <class T>
typename T::list::ptr entitiesByType() {
IfcEntityList::ptr untyped_list = entitiesByType(T::Class());
typename T::list::ptr instances_by_type() {
IfcEntityList::ptr untyped_list = instances_by_type(&T::Class());
if (untyped_list) {
return untyped_list->as<T>();
} else {
@@ -131,24 +131,24 @@ public:
/// Returns all entities in the file that match the positional argument.
/// NOTE: This also returns subtypes of the requested type, for example:
/// IfcWall will also return IfcWallStandardCase entities
IfcEntityList::ptr entitiesByType(IfcSchema::Type::Enum t);
IfcEntityList::ptr instances_by_type(const IfcParse::declaration*);
/// Returns all entities in the file that match the positional argument.
IfcEntityList::ptr entitiesByTypeExclSubtypes(IfcSchema::Type::Enum t);
IfcEntityList::ptr instances_by_type_excl_subtypes(const IfcParse::declaration*);
/// Returns all entities in the file that match the positional argument.
/// NOTE: This also returns subtypes of the requested type, for example:
/// IfcWall will also return IfcWallStandardCase entities
IfcEntityList::ptr entitiesByType(const std::string& t);
IfcEntityList::ptr instances_by_type(const std::string& t);
/// Returns all entities in the file that reference the id
IfcEntityList::ptr entitiesByReference(int id);
IfcEntityList::ptr instances_by_reference(int id);
/// Returns the entity with the specified id
IfcUtil::IfcBaseClass* entityById(int id);
IfcUtil::IfcBaseClass* instance_by_id(int id);
/// Returns the entity with the specified GlobalId
IfcSchema::IfcRoot* entityByGuid(const std::string& guid);
IfcSchema::IfcRoot* instance_by_guid(const std::string& guid);
/// Performs a depth-first traversal, returning all entity instance
/// attributes as a flat list. NB: includes the root instance specified
+2 -2
View File
@@ -179,7 +179,7 @@ template <>
inline void IfcHierarchyHelper::addRelatedObject <IfcSchema::IfcRelContainedInSpatialStructure> (IfcSchema::IfcObjectDefinition* relating_structure,
IfcSchema::IfcObjectDefinition* related_object, IfcSchema::IfcOwnerHistory* owner_hist)
{
IfcSchema::IfcRelContainedInSpatialStructure::list::ptr li = entitiesByType<IfcSchema::IfcRelContainedInSpatialStructure>();
IfcSchema::IfcRelContainedInSpatialStructure::list::ptr li = instances_by_type<IfcSchema::IfcRelContainedInSpatialStructure>();
bool found = false;
for (IfcSchema::IfcRelContainedInSpatialStructure::list::it i = li->begin(); i != li->end(); ++i) {
IfcSchema::IfcRelContainedInSpatialStructure* rel = *i;
@@ -211,7 +211,7 @@ template <>
inline void IfcHierarchyHelper::addRelatedObject <IfcSchema::IfcRelDefinesByType> (IfcSchema::IfcObjectDefinition* relating_type,
IfcSchema::IfcObjectDefinition* related_object, IfcSchema::IfcOwnerHistory* owner_hist)
{
IfcSchema::IfcRelDefinesByType::list::ptr li = entitiesByType<IfcSchema::IfcRelDefinesByType>();
IfcSchema::IfcRelDefinesByType::list::ptr li = instances_by_type<IfcSchema::IfcRelDefinesByType>();
bool found = false;
for (IfcSchema::IfcRelDefinesByType::list::it i = li->begin(); i != li->end(); ++i) {
IfcSchema::IfcRelDefinesByType* rel = *i;
+62 -68
View File
@@ -601,7 +601,7 @@ EntityArgument::EntityArgument(const Token& t) {
// Data needs to be loaded, for the tokens
// to be consumed and parsing to continue.
data->load();
entity = IfcSchema::SchemaEntity(data);
entity = file->schema()->instantiate(data);
}
//
@@ -800,7 +800,7 @@ TokenArgument::operator bool() const { return TokenFunc::asBool(token); }
TokenArgument::operator double() const { return TokenFunc::asFloat(token); }
TokenArgument::operator std::string() const { return TokenFunc::asString(token); }
TokenArgument::operator boost::dynamic_bitset<>() const { return TokenFunc::asBinary(token); }
TokenArgument::operator IfcUtil::IfcBaseClass*() const { return token.lexer->file->entityById(TokenFunc::asIdentifier(token)); }
TokenArgument::operator IfcUtil::IfcBaseClass*() const { return token.lexer->file->instance_by_id(TokenFunc::asIdentifier(token)); }
unsigned int TokenArgument::size() const { return 1; }
Argument* TokenArgument::operator [] (unsigned int /*i*/) const { throw IfcException("Argument is not a list of attributes"); }
std::string TokenArgument::toString(bool upper) const {
@@ -838,7 +838,7 @@ IfcEntityInstanceData* IfcParse::read(unsigned int i, IfcFile* f, boost::optiona
}
Token datatype = f->tokens->Next();
if (!TokenFunc::isKeyword(datatype)) throw IfcException("Unexpected token while parsing entity");
IfcSchema::Type::Enum ty = IfcSchema::Type::FromString(TokenFunc::asStringRef(datatype));
const IfcParse::declaration* ty = f->schema()->declaration_by_name(TokenFunc::asStringRef(datatype));
IfcEntityInstanceData* e = new IfcEntityInstanceData(ty, f, i, offset.get_value_or(0));
return e;
}
@@ -849,8 +849,8 @@ void IfcParse::IfcFile::load(const IfcEntityInstanceData& data) {
Token datatype = tokens->Next();
if (!TokenFunc::isKeyword(datatype)) throw IfcException("Unexpected token while parsing entity instance");
}
tokens->Next();
// TODO: reserve based on number of schema attrs
load(data.id(), data.attributes());
unsigned int old_offset = tokens->stream->Tell();
Token semilocon = tokens->Next();
@@ -891,12 +891,12 @@ std::string IfcEntityInstanceData::toString(bool upper) const {
std::stringstream ss;
ss.imbue(std::locale::classic());
std::string dt = IfcSchema::Type::ToString(type());
std::string dt = type()->name();
if (upper) {
boost::to_upper(dt);
}
if (!IfcSchema::Type::IsSimple(type()) || id_ != 0) {
if (type()->as_entity() || id_ != 0) {
ss << "#" << id_ << "=";
}
@@ -1116,7 +1116,7 @@ void IfcEntityInstanceData::setArgument(unsigned int i, Argument* a, IfcUtil::Ar
// Remove leading and trailing '.'
enum_literal = enum_literal.substr(1, enum_literal.size() - 2);
const IfcParse::enumeration_type* enum_type = file->schema()->declaration_by_name(type())->as_entity()->
const IfcParse::enumeration_type* enum_type = type()->as_entity()->
attribute_by_index(i)->type_of_attribute()->as_named_type()->declared_type()->as_enumeration_type();
std::vector<std::string>::const_iterator it = std::find(
@@ -1163,7 +1163,7 @@ void IfcEntityInstanceData::setArgument(unsigned int i, Argument* a, IfcUtil::Ar
break; }
case IfcUtil::Argument_EMPTY_AGGREGATE:
case IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE: {
IfcUtil::ArgumentType t2 = IfcUtil::from_parameter_type(file->schema()->declaration_by_name(type())->as_entity()->all_attributes()[i]->type_of_attribute());
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);
@@ -1300,16 +1300,16 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
token_stream[2].type == IfcParse::Token_KEYWORD)
{
current_id = (unsigned) TokenFunc::asIdentifier(token_stream[0]);
IfcSchema::Type::Enum entity_type;
const IfcParse::declaration* entity_type;
try {
entity_type = IfcSchema::Type::FromString(TokenFunc::asStringRef(token_stream[2]));
entity_type = schema_->declaration_by_name(TokenFunc::asStringRef(token_stream[2]));
} catch (const IfcException& ex) {
Logger::Message(Logger::LOG_ERROR, ex.what());
goto advance;
}
data = new IfcEntityInstanceData(entity_type, this, current_id, token_stream[2].startPos);
instance = IfcSchema::SchemaEntity(data);
instance = schema()->instantiate(data);
/// @todo Printing to stdout in a library class feels weird. Maybe move the progress prints to the client code?
// Update the status after every 1000 instances parsed
@@ -1333,27 +1333,27 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
}
}
IfcSchema::Type::Enum ty = instance->declaration().type();
const IfcParse::declaration* ty = &instance->declaration();
{
IfcEntityList::ptr instances_by_type = entitiesByTypeExclSubtypes(ty);
if (!instances_by_type) {
instances_by_type = IfcEntityList::ptr(new IfcEntityList());
bytype_excl[ty] = instances_by_type;
IfcEntityList::ptr insts = instances_by_type_excl_subtypes(ty);
if (!insts) {
insts = IfcEntityList::ptr(new IfcEntityList());
bytype_excl[ty] = insts;
}
instances_by_type->push(instance);
insts->push(instance);
}
for (;;) {
IfcEntityList::ptr instances_by_type = entitiesByType(ty);
if (!instances_by_type) {
instances_by_type = IfcEntityList::ptr(new IfcEntityList());
bytype[ty] = instances_by_type;
IfcEntityList::ptr insts = instances_by_type(ty);
if (!insts) {
insts = IfcEntityList::ptr(new IfcEntityList());
bytype[ty] = insts;
}
instances_by_type->push(instance);
boost::optional<IfcSchema::Type::Enum> pt = IfcSchema::Type::Parent(ty);
insts->push(instance);
const IfcParse::declaration* pt = ty->as_entity()->supertype();
if (pt) {
ty = *pt;
ty = pt;
} else {
break;
}
@@ -1485,7 +1485,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
// need to be updated to point to instances in this file.
IfcFile* other_file = entity->data().file;
IfcEntityInstanceData* we = new IfcEntityInstanceData(entity->data());
new_entity = IfcSchema::SchemaEntity(we);
new_entity = schema()->instantiate(we);
// In case an entity is added that contains geometry, the unit
// information needs to be accounted for for IfcLengthMeasures.
@@ -1498,10 +1498,6 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
IfcUtil::ArgumentType attr_type = attr->type();
IfcParse::declaration* decl = attribute_types[i]->type_of_attribute()->as_named_type()->declared_type();
IfcSchema::Type::Enum decl_type = IfcSchema::Type::UNDEFINED;
if (decl) {
decl_type = decl->type();
}
if (attr_type == IfcUtil::Argument_ENTITY_INSTANCE) {
entity_entity_map_t::const_iterator eit = entity_file_map.find(*attr);
@@ -1538,10 +1534,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument();
copy->set(new_instances);
we->setArgument(i, copy);
} else if (decl_type == IfcSchema::Type::IfcLengthMeasure ||
decl_type == IfcSchema::Type::IfcPositiveLengthMeasure)
{
} else if (decl && decl->is(*schema()->declaration_by_name("IfcLengthMeasure"))) {
if (boost::math::isnan(conversion_factor)) {
const std::pair<IfcSchema::IfcNamedUnit*, double> this_file_unit = getUnit(IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT);
const std::pair<IfcSchema::IfcNamedUnit*, double> other_file_unit = other_file->getUnit(IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT);
@@ -1575,7 +1568,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
// A new entity instance name is generated and
// the instance is pointed to this file.
we->file = this;
if (!IfcSchema::Type::IsSimple(we->type())) {
if (we->type()->as_entity()) {
we->set_id(FreshId());
}
@@ -1599,29 +1592,29 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
}
// The mapping by entity type is updated.
IfcSchema::Type::Enum ty = new_entity->declaration().type();
const IfcParse::declaration* ty = &new_entity->declaration();
{
IfcEntityList::ptr instances_by_type = entitiesByTypeExclSubtypes(ty);
if (!instances_by_type) {
instances_by_type = IfcEntityList::ptr(new IfcEntityList());
bytype_excl[ty] = instances_by_type;
IfcEntityList::ptr insts = instances_by_type_excl_subtypes(ty);
if (!insts) {
insts = IfcEntityList::ptr(new IfcEntityList());
bytype_excl[ty] = insts;
}
instances_by_type->push(new_entity);
insts->push(new_entity);
}
for (;;) {
IfcEntityList::ptr instances_by_type = entitiesByType(ty);
if (!instances_by_type) {
instances_by_type = IfcEntityList::ptr(new IfcEntityList());
bytype[ty] = instances_by_type;
IfcEntityList::ptr insts = instances_by_type(ty);
if (!insts) {
insts = IfcEntityList::ptr(new IfcEntityList());
bytype[ty] = insts;
}
instances_by_type->push(new_entity);
boost::optional<IfcSchema::Type::Enum> pt = IfcSchema::Type::Parent(ty);
insts->push(new_entity);
const IfcParse::declaration* pt = ty->as_entity()->supertype();
if (pt) {
ty = *pt;
}
else {
ty = pt;
} else {
break;
}
}
@@ -1659,7 +1652,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
IfcUtil::IfcBaseClass* entity_attribute = *it;
if (*it == new_entity) continue;
try {
if (!IfcSchema::Type::IsSimple(entity_attribute->declaration().type())) {
if (entity_attribute->declaration().as_entity()) {
unsigned entity_attribute_id = entity_attribute->data().id();
byref[entity_attribute_id].push_back(new_entity->data().id());
}
@@ -1673,7 +1666,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) {
const unsigned id = entity->data().id();
IfcUtil::IfcBaseClass* file_entity = entityById(id);
IfcUtil::IfcBaseClass* file_entity = instance_by_id(id);
// TODO: Create a set of weak relations. Inverse relations that do not dictate an
// instance to be retained. For example: when deleting an IfcRepresentation, the
@@ -1686,7 +1679,7 @@ void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) {
throw IfcParse::IfcException("Instance not part of this file");
}
IfcEntityList::ptr references = entitiesByReference(id);
IfcEntityList::ptr references = instances_by_reference(id);
// Alter entity instances with INVERSE relations to the entity being
// deleted. This is necessary to maintain a valid IFC file, because
@@ -1769,10 +1762,10 @@ void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) {
byid.erase(byid.find(id));
IfcSchema::Type::Enum ty = entity->declaration().type();
const IfcParse::declaration* ty = &entity->declaration();
{
IfcEntityList::ptr instances_of_same_type = entitiesByTypeExclSubtypes(ty);
IfcEntityList::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);
@@ -1780,16 +1773,17 @@ void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) {
}
for (;;) {
IfcEntityList::ptr instances_of_same_type = entitiesByType(ty);
IfcEntityList::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);
}
boost::optional<IfcSchema::Type::Enum> pt = IfcSchema::Type::Parent(ty);
const IfcParse::declaration* pt = ty->as_entity()->supertype();
if (pt) {
ty = *pt;
ty = pt;
} else {
break;
}
@@ -1798,21 +1792,21 @@ void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) {
delete entity;
}
IfcEntityList::ptr IfcFile::entitiesByType(IfcSchema::Type::Enum t) {
IfcEntityList::ptr IfcFile::instances_by_type(const IfcParse::declaration* t) {
entities_by_type_t::const_iterator it = bytype.find(t);
return (it == bytype.end()) ? IfcEntityList::ptr() : it->second;
}
IfcEntityList::ptr IfcFile::entitiesByTypeExclSubtypes(IfcSchema::Type::Enum t) {
IfcEntityList::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()) ? IfcEntityList::ptr() : it->second;
}
IfcEntityList::ptr IfcFile::entitiesByType(const std::string& t) {
return entitiesByType(IfcSchema::Type::FromString(boost::to_upper_copy(t)));
IfcEntityList::ptr IfcFile::instances_by_type(const std::string& t) {
return instances_by_type(schema()->declaration_by_name(t));
}
IfcEntityList::ptr IfcFile::entitiesByReference(int t) {
IfcEntityList::ptr IfcFile::instances_by_reference(int t) {
entities_by_ref_t::const_iterator it = byref.find(t);
IfcEntityList::ptr return_value;
if (it != byref.end()) {
@@ -1821,13 +1815,13 @@ IfcEntityList::ptr IfcFile::entitiesByReference(int t) {
if (!return_value) {
return_value.reset(new IfcEntityList);
}
return_value->push(entityById(*jt));
return_value->push(instance_by_id(*jt));
}
}
return return_value;
}
IfcUtil::IfcBaseClass* IfcFile::entityById(int id) {
IfcUtil::IfcBaseClass* IfcFile::instance_by_id(int id) {
entity_by_id_t::const_iterator it = byid.find(id);
if (it == byid.end()) {
throw IfcException("Entity not found");
@@ -1835,7 +1829,7 @@ IfcUtil::IfcBaseClass* IfcFile::entityById(int id) {
return it->second;
}
IfcSchema::IfcRoot* IfcFile::entityByGuid(const std::string& guid) {
IfcSchema::IfcRoot* IfcFile::instance_by_guid(const std::string& guid) {
entity_by_guid_t::const_iterator it = byguid.find(guid);
if ( it == byguid.end() ) {
throw IfcException("Entity not found");
@@ -1910,10 +1904,10 @@ std::string IfcFile::createTimestamp() const {
}
IfcEntityList::ptr IfcFile::getInverse(int instance_id, IfcSchema::Type::Enum type, int attribute_index) {
IfcUtil::IfcBaseClass* instance = entityById(instance_id);
IfcUtil::IfcBaseClass* instance = instance_by_id(instance_id);
IfcEntityList::ptr l = IfcEntityList::ptr(new IfcEntityList);
IfcEntityList::ptr all = entitiesByReference(instance_id);
IfcEntityList::ptr all = instances_by_reference(instance_id);
if (!all) return l;
for(IfcEntityList::it it = all->begin(); it != all->end(); ++it) {
@@ -1961,7 +1955,7 @@ void IfcFile::setDefaultHeaderValues() {
std::pair<IfcSchema::IfcNamedUnit*, double> IfcFile::getUnit(IfcSchema::IfcUnitEnum::IfcUnitEnum type) {
std::pair<IfcSchema::IfcNamedUnit*, double> return_value((IfcSchema::IfcNamedUnit*)0, 1.);
IfcSchema::IfcProject::list::ptr projects = entitiesByType<IfcSchema::IfcProject>();
IfcSchema::IfcProject::list::ptr projects = instances_by_type<IfcSchema::IfcProject>();
if (projects->size() == 1) {
IfcSchema::IfcProject* project = *projects->begin();
IfcEntityList::ptr units = project->UnitsInContext()->Units();
+4 -3
View File
@@ -24,12 +24,13 @@ bool IfcParse::named_type::is(IfcSchema::Type::Enum name) const {
static std::map<std::string, const IfcParse::schema_definition*> schemas;
IfcParse::schema_definition::schema_definition(const std::string& name, const std::vector<const declaration*>& declarations, const bool built_in = false)
IfcParse::schema_definition::schema_definition(const std::string& name, const std::vector<const declaration*>& declarations, instance_factory* factory, bool built_in)
: name_(name)
, declarations_(declarations)
, built_in_(built_in)
, factory_(factory)
{
std::sort(declarations_.begin(), declarations_.end(), declaration_by_enum_sort());
std::sort(declarations_.begin(), declarations_.end(), declaration_by_index_sort());
for (std::vector<const declaration*>::const_iterator it = declarations_.begin(); it != declarations_.end(); ++it) {
if ((**it).as_type_declaration()) type_declarations_.push_back((**it).as_type_declaration());
if ((**it).as_select_type()) select_types_.push_back((**it).as_select_type());
@@ -47,7 +48,7 @@ IfcParse::schema_definition::~schema_definition() {
}
const IfcParse::schema_definition* schema_by_name(const std::string& name) {
std::map<std::string, IfcParse::schema_definition*>::const_iterator it = schemas.find(name);
std::map<std::string, const IfcParse::schema_definition*>::const_iterator it = schemas.find(name);
if (it == schemas.end()) {
throw IfcParse::IfcException("No schema named " + name);
}
+54 -45
View File
@@ -35,6 +35,13 @@
#include "../ifcparse/Ifc2x3enum.h"
#endif
// Forward declarations
class IfcEntityInstanceData;
namespace IfcUtil {
class IfcBaseClass;
}
namespace IfcParse {
class declaration;
@@ -112,29 +119,29 @@ namespace IfcParse {
class declaration {
protected:
// std::string name_;
IfcSchema::Type::Enum name_;
std::string name_;
int index_in_schema_;
public:
declaration(IfcSchema::Type::Enum name)
: name_(name) {}
declaration(const std::string& name)
: name_(IfcSchema::Type::FromString(name)) {}
public:
declaration(const std::string& name, int index_in_schema)
: name_(name)
, index_in_schema_(index_in_schema)
{}
std::string name() const { return IfcSchema::Type::ToString(name_); }
std::string name() const { return name_; }
virtual const type_declaration* as_type_declaration() const { return static_cast<type_declaration*>(0); }
virtual const select_type* as_select_type() const { return static_cast<select_type*>(0); }
virtual const enumeration_type* as_enumeration_type() const { return static_cast<enumeration_type*>(0); }
virtual const entity* as_entity() const { return static_cast<entity*>(0); }
// TODO: Type checking by Enum value
bool is(const std::string& name) const;
bool is(IfcSchema::Type::Enum name) const;
bool is(int index) const;
bool is(const IfcParse::declaration& decl) const;
IfcSchema::Type::Enum type() const {
return name_;
}
int index_in_schema() const { return index_in_schema_; }
int type() const { return index_in_schema_; }
};
class type_declaration : public declaration {
@@ -142,11 +149,8 @@ namespace IfcParse {
const parameter_type* declared_type_;
public:
type_declaration(const std::string& name, const parameter_type* declared_type)
: declaration(name)
, declared_type_(declared_type) {}
type_declaration(IfcSchema::Type::Enum name, const parameter_type* declared_type)
: declaration(name)
type_declaration(const std::string& name, int index_in_schema, const parameter_type* declared_type)
: declaration(name, index_in_schema)
, declared_type_(declared_type) {}
const parameter_type* declared_type() const { return declared_type_; }
@@ -158,11 +162,8 @@ namespace IfcParse {
protected:
std::vector<const declaration*> select_list_;
public:
select_type(const std::string& name, const std::vector<const declaration*>& select_list)
: declaration(name)
, select_list_(select_list) {}
select_type(IfcSchema::Type::Enum name, const std::vector<const declaration*>& select_list)
: declaration(name)
select_type(const std::string& name, int index_in_schema, const std::vector<const declaration*>& select_list)
: declaration(name, index_in_schema)
, select_list_(select_list) {}
const std::vector<const declaration*>& select_list() const { return select_list_; }
@@ -174,11 +175,8 @@ namespace IfcParse {
protected:
std::vector<std::string> enumeration_items_;
public:
enumeration_type(const std::string& name, const std::vector<std::string>& enumeration_items)
: declaration(name)
, enumeration_items_(enumeration_items) {}
enumeration_type(IfcSchema::Type::Enum name, const std::vector<std::string>& enumeration_items)
: declaration(name)
enumeration_type(const std::string& name, int index_in_schema, const std::vector<std::string>& enumeration_items)
: declaration(name, index_in_schema)
, enumeration_items_(enumeration_items) {}
const std::vector<std::string>& enumeration_items() const { return enumeration_items_; }
@@ -267,25 +265,29 @@ namespace IfcParse {
}
public:
entity(const std::string& name, entity* supertype)
: declaration(name)
, supertype_(supertype)
{}
entity(IfcSchema::Type::Enum name, entity* supertype)
: declaration(name)
entity(const std::string& name, int index_in_schema, entity* supertype)
: declaration(name, index_in_schema)
, supertype_(supertype)
{}
bool is(const std::string& name) const {
return is(IfcSchema::Type::FromString(name));
}
bool is(IfcSchema::Type::Enum name) const {
if (name == name_) return true;
else if (supertype_) return supertype_->is(name);
else return false;
}
bool is(int name) const {
if (name == index_in_schema_) return true;
else if (supertype_) return supertype_->is(name);
else return false;
}
bool is(const IfcParse::declaration& decl) const {
if (this == &decl) return true;
else if (supertype_) return supertype_->is(decl);
else return false;
}
void set_subtypes(const std::vector<const entity*>& subtypes) {
subtypes_ = subtypes;
}
@@ -378,10 +380,13 @@ namespace IfcParse {
virtual const entity* as_entity() const { return this; }
};
class instance_factory {
public:
virtual IfcUtil::IfcBaseClass* operator()(IfcEntityInstanceData* data) const = 0;
};
class schema_definition {
private:
bool built_in_;
std::string name_;
std::vector<const declaration*> declarations_;
@@ -406,15 +411,18 @@ namespace IfcParse {
}
};
class declaration_by_enum_sort : public std::binary_function<const declaration*, const declaration*, bool> {
class declaration_by_index_sort : public std::binary_function<const declaration*, const declaration*, bool> {
public:
bool operator()(const declaration* a, const declaration* b) {
return a->type() < b->type();
return a->index_in_schema() < b->index_in_schema();
}
};
instance_factory* factory_;
public:
schema_definition(const std::string& name, const std::vector<const declaration*>& declarations, const bool built_in = false);
schema_definition(const std::string& name, const std::vector<const declaration*>& declarations, instance_factory* factory);
~schema_definition();
@@ -427,8 +435,7 @@ namespace IfcParse {
}
}
const declaration* declaration_by_name(IfcSchema::Type::Enum name) const {
if (!built_in_) throw;
const declaration* declaration_by_name(int name) const {
return declarations_[name];
}
@@ -439,6 +446,8 @@ namespace IfcParse {
const std::vector<const entity*>& entities() const { return entities_; }
const std::string& name() const { return name_; }
IfcUtil::IfcBaseClass* instantiate(IfcEntityInstanceData* data) const { return (*factory_)(data); }
};
const schema_definition* schema_by_name(const std::string&);