From 872dd4e83183e30fc2c9b70403bdf07b511e3b7a Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 2 Nov 2014 18:36:51 +0000 Subject: [PATCH] Rewrite IfcFile::AddEntity() not to rely on exceptions, as suggested by ch0kee. --- src/ifcparse/IfcParse.cpp | 92 ++++++++++++++++++++++++++++---- src/ifcparse/IfcParse.h | 24 ++++++--- src/ifcparse/IfcUtil.h | 22 ++++++-- src/ifcparse/IfcWritableEntity.h | 4 +- src/ifcparse/IfcWrite.cpp | 14 ++++- src/ifcparse/IfcWrite.h | 3 +- 6 files changed, 133 insertions(+), 26 deletions(-) diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index 3c1292e95d..f3b2352b1e 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -346,6 +346,27 @@ bool TokenFunc::isEnumeration(const Token& t) { bool TokenFunc::isDatatype(const Token& t) { return ! isOperator(t) && startsWith(t, 'I'); } +bool TokenFunc::isInt(const Token& t) { + if (isOperator(t)) return false; + const std::string str = asString(t); + const char* start = str.c_str(); + char* end; + long result = strtol(start,&end,10); + return ((end - start) == str.length()); +} +bool TokenFunc::isBool(const Token& t) { + if (!isEnumeration(t)) return false; + const std::string str = asString(t); + return str == "T" || str == "F"; +} +bool TokenFunc::isFloat(const Token& t) { + if (isOperator(t)) return false; + const std::string str = asString(t); + const char* start = str.c_str(); + char* end; + double result = strtod(start,&end); + return ((end - start) == str.length()); +} int TokenFunc::asInt(const Token& t) { const std::string str = asString(t); // In case of an ENTITY_INSTANCE_NAME skip the leading # @@ -415,6 +436,22 @@ ArgumentList::ArgumentList(Tokens* t, std::vector& ids) { } } +IfcUtil::ArgumentType ArgumentList::type() const { + if (list.empty()) return IfcUtil::Argument_UNKNOWN; + const IfcUtil::ArgumentType elem_type = list[0]->type(); + if (elem_type == IfcUtil::Argument_INT) { + return IfcUtil::Argument_VECTOR_INT; + } else if (elem_type == IfcUtil::Argument_DOUBLE) { + return IfcUtil::Argument_VECTOR_DOUBLE; + } else if (elem_type == IfcUtil::Argument_STRING) { + return IfcUtil::Argument_VECTOR_STRING; + } else if (elem_type == IfcUtil::Argument_ENTITY) { + return IfcUtil::Argument_ENTITY_LIST; + } else { + return IfcUtil::Argument_UNKNOWN; + } +} + void ArgumentList::Push(Argument* l) { list.push_back(l); } @@ -499,6 +536,24 @@ ArgumentList::~ArgumentList() { list.clear(); } +IfcUtil::ArgumentType TokenArgument::type() const { + if (TokenFunc::isInt(token)) { + return IfcUtil::Argument_INT; + } else if (TokenFunc::isBool(token)) { + return IfcUtil::Argument_BOOL; + } else if (TokenFunc::isFloat(token)) { + return IfcUtil::Argument_DOUBLE; + } else if (TokenFunc::isString(token)) { + return IfcUtil::Argument_STRING; + } else if (TokenFunc::isEnumeration(token)) { + return IfcUtil::Argument_ENUMERATION; + } else if (TokenFunc::isIdentifier(token)) { + return IfcUtil::Argument_ENTITY; + } else { + return IfcUtil::Argument_UNKNOWN; + } +} + // // Functions for casting the TokenArgument to other types // @@ -522,6 +577,11 @@ std::string TokenArgument::toString(bool upper) const { } } bool TokenArgument::isNull() const { return TokenFunc::isOperator(token,'$'); } + +IfcUtil::ArgumentType EntityArgument::type() const { + return IfcUtil::Argument_ENTITY; +} + // // Functions for casting the EntityArgument to other types // @@ -679,8 +739,8 @@ IfcEntityList::ptr Entity::getInverse(IfcSchema::Type::Enum c, int i, const std: bool Entity::is(IfcSchema::Type::Enum v) const { return _type == v; } unsigned int Entity::id() { return _id; } -bool Entity::isWritable() { - return false; +IfcWrite::IfcWritableEntity* Entity::isWritable() { + return 0; } IfcFile::IfcFile() { @@ -822,7 +882,7 @@ void IfcFile::AddEntity(IfcUtil::IfcBaseClass* entity) { // For newly created entities ensure a valid ENTITY_INSTANCE_NAME is set if ( entity->entity->isWritable() ) { if ( ! entity->entity->file ) entity->entity->file = this; - new_id = ((IfcWrite::IfcWritableEntity*)(entity->entity))->setId(); + new_id = entity->entity->isWritable()->setId(); } else { // TODO: Detect and fix ENTITY_INSTANCE_NAME collisions new_id = entity->entity->id(); @@ -837,22 +897,32 @@ void IfcFile::AddEntity(IfcUtil::IfcBaseClass* entity) { unsigned arg_count = entity->entity->getArgumentCount(); for (unsigned i = 0; i < arg_count; ++i) { Argument* arg = entity->entity->getArgument(i); + + // Create a flat list of entity instances referenced by the instance that is being added IfcEntityList::ptr entity_attributes(new IfcEntityList); - try { + if (arg->type() == IfcUtil::Argument_ENTITY) { IfcUtil::IfcBaseClass* entity_attribute = *arg; entity_attributes->push(entity_attribute); - } catch(IfcParse::IfcException&) { - try { - IfcEntityList::ptr entity_list_attribute = *arg; - entity_attributes->push(entity_list_attribute); - } catch(IfcParse::IfcException&) {} + } else if (arg->type() == IfcUtil::Argument_ENTITY_LIST) { + IfcEntityList::ptr entity_list_attribute = *arg; + entity_attributes->push(entity_list_attribute); + } else if (arg->type() == IfcUtil::Argument_ENTITY_LIST_LIST) { + IfcEntityListList::ptr entity_list_attribute = *arg; + for (IfcEntityListList::outer_it it = entity_list_attribute->begin(); it != entity_list_attribute->end(); ++it) { + for (IfcEntityListList::inner_it jt = it->begin(); jt != it->end(); ++jt) { + entity_attributes->push(*jt); + } + } } + for (IfcEntityList::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) { IfcUtil::IfcBaseClass* entity_attribute = *it; try { if (entity_attribute->entity->isWritable()) { - if ( ! entity_attribute->entity->file ) entity_attribute->entity->file = this; - ((IfcWrite::IfcWritableEntity*)(entity_attribute->entity))->setId(); + if ( ! entity_attribute->entity->file ) { + entity_attribute->entity->file = this; + } + entity_attribute->entity->isWritable()->setId(); } unsigned entity_attribute_id = entity_attribute->entity->id(); IfcEntityList::ptr refs = EntitiesByReference(entity_attribute_id); diff --git a/src/ifcparse/IfcParse.h b/src/ifcparse/IfcParse.h index 5c550a4412..3ccf11dda0 100644 --- a/src/ifcparse/IfcParse.h +++ b/src/ifcparse/IfcParse.h @@ -69,12 +69,18 @@ namespace IfcParse { static bool isString(const Token& t); /// Returns whether the token can be interpreted as an identifier static bool isIdentifier(const Token& t); - /// Returns whether the token can be interpreted as an syntactical operator + /// Returns whether the token can be interpreted as a syntactical operator static bool isOperator(const Token& t, char op = 0); /// Returns whether the token can be interpreted as an enumerated value static bool isEnumeration(const Token& t); - /// Returns whether the token can be interpreted as an datatype name + /// Returns whether the token can be interpreted as a datatype name static bool isDatatype(const Token& t); + /// Returns whether the token can be interpreted as an integer + static bool isInt(const Token& t); + /// Returns whether the token can be interpreted as a boolean + static bool isBool(const Token& t); + /// Returns whether the token can be interpreted as a floating point number + static bool isFloat(const Token& t); /// Returns the token interpreted as an integer static int asInt(const Token& t); /// Returns the token interpreted as an boolean (.T. or .F.) @@ -120,6 +126,9 @@ namespace IfcParse { public: ArgumentList(Tokens* t, std::vector& ids); ~ArgumentList(); + + IfcUtil::ArgumentType type() const; + operator int() const; operator bool() const; operator double() const; @@ -128,7 +137,6 @@ namespace IfcParse { operator std::vector() const; operator std::vector() const; operator IfcUtil::IfcBaseClass*() const; - //operator IfcUtil::IfcAbstractSelect::ptr() const; operator IfcEntityList::ptr() const; operator IfcEntityListList::ptr() const; unsigned int Size() const; @@ -146,6 +154,9 @@ namespace IfcParse { public: Token token; TokenArgument(const Token& t); + + IfcUtil::ArgumentType type() const; + operator int() const; operator bool() const; operator double() const; @@ -154,7 +165,6 @@ namespace IfcParse { operator std::vector() const; operator std::vector() const; operator IfcUtil::IfcBaseClass*() const; - //operator IfcUtil::IfcAbstractSelect::ptr() const; operator IfcEntityList::ptr() const; operator IfcEntityListList::ptr() const; unsigned int Size() const; @@ -172,6 +182,9 @@ namespace IfcParse { public: EntityArgument(IfcSchema::Type::Enum ty, const Token& t); ~EntityArgument(); + + IfcUtil::ArgumentType type() const; + operator int() const; operator bool() const; operator double() const; @@ -180,7 +193,6 @@ namespace IfcParse { operator std::vector() const; operator std::vector() const; operator IfcUtil::IfcBaseClass*() const; - //operator IfcUtil::IfcAbstractSelect::ptr() const; operator IfcEntityList::ptr() const; operator IfcEntityListList::ptr() const; unsigned int Size() const; @@ -214,7 +226,7 @@ namespace IfcParse { IfcSchema::Type::Enum type() const; bool is(IfcSchema::Type::Enum v) const; unsigned int id(); - bool isWritable(); + IfcWrite::IfcWritableEntity* isWritable(); }; typedef std::map MapEntitiesByType; diff --git a/src/ifcparse/IfcUtil.h b/src/ifcparse/IfcUtil.h index 65ca9c050a..b59ca6a9a5 100644 --- a/src/ifcparse/IfcUtil.h +++ b/src/ifcparse/IfcUtil.h @@ -36,10 +36,24 @@ class Argument; class IfcEntityList; class IfcEntityListList; class IfcAbstractEntity; +namespace IfcWrite { + class IfcWritableEntity; +} namespace IfcUtil { enum ArgumentType { - Argument_INT, Argument_BOOL, Argument_DOUBLE, Argument_STRING, Argument_VECTOR_INT, Argument_VECTOR_DOUBLE, Argument_VECTOR_STRING, Argument_ENTITY, Argument_ENTITY_LIST, Argument_ENTITY_LIST_LIST, Argument_ENUMERATION, Argument_UNKNOWN + Argument_INT, + Argument_BOOL, + Argument_DOUBLE, + Argument_STRING, + Argument_VECTOR_INT, + Argument_VECTOR_DOUBLE, + Argument_VECTOR_STRING, + Argument_ENUMERATION, + Argument_ENTITY, + Argument_ENTITY_LIST, + Argument_ENTITY_LIST_LIST, + Argument_UNKNOWN }; class IfcBaseClass { @@ -208,8 +222,7 @@ namespace IfcParse { class Argument { public: - //void* file; -//public: + virtual IfcUtil::ArgumentType type() const = 0; virtual operator int() const = 0; virtual operator bool() const = 0; virtual operator double() const = 0; @@ -218,7 +231,6 @@ public: virtual operator std::vector() const = 0; virtual operator std::vector() const = 0; virtual operator IfcUtil::IfcBaseClass*() const = 0; - //virtual operator IfcUtil::IfcAbstractSelect::ptr() const = 0; virtual operator IfcEntityList::ptr() const = 0; virtual operator IfcEntityListList::ptr() const = 0; virtual unsigned int Size() const = 0; @@ -241,7 +253,7 @@ public: virtual bool is(IfcSchema::Type::Enum v) const = 0; virtual std::string toString(bool upper=false) const = 0; virtual unsigned int id() = 0; - virtual bool isWritable() = 0; + virtual IfcWrite::IfcWritableEntity* isWritable() = 0; }; class Logger { diff --git a/src/ifcparse/IfcWritableEntity.h b/src/ifcparse/IfcWritableEntity.h index b5f6b3d095..06b52a60d5 100644 --- a/src/ifcparse/IfcWritableEntity.h +++ b/src/ifcparse/IfcWritableEntity.h @@ -48,6 +48,7 @@ namespace IfcWrite { public: IfcWritableEntity(IfcSchema::Type::Enum t); ~IfcWritableEntity(); + int setId(int i=-1); IfcWritableEntity(IfcAbstractEntity* e); IfcEntityList::ptr getInverse(IfcSchema::Type::Enum c = IfcSchema::Type::ALL); @@ -59,7 +60,8 @@ namespace IfcWrite { bool is(IfcSchema::Type::Enum v) const; std::string toString(bool upper=false) const; unsigned int id(); - bool isWritable(); + IfcWritableEntity* isWritable(); + void setArgument(int i); void setArgumentDerived(int i); void setArgument(int i,bool v); diff --git a/src/ifcparse/IfcWrite.cpp b/src/ifcparse/IfcWrite.cpp index 75e8f9a7bd..75d72294ac 100644 --- a/src/ifcparse/IfcWrite.cpp +++ b/src/ifcparse/IfcWrite.cpp @@ -110,7 +110,7 @@ unsigned int IfcWritableEntity::id() { } return *_id; } -bool IfcWritableEntity::isWritable() { return true; } +IfcWritableEntity* IfcWritableEntity::isWritable() { return this; } bool IfcWritableEntity::arg_writable(int i) { std::map::const_iterator it = writemask.find(i); if ( it == writemask.end() ) return false; @@ -322,6 +322,16 @@ IfcWriteArgument::argument_type IfcWriteArgument::argumentType() const { return static_cast(container.which()); } +IfcUtil::ArgumentType IfcWriteArgument::type() const { + // TODO: Make these the same enumeration + int ty = static_cast(container.which()) - 2; + if (ty < 0) { + return IfcUtil::Argument_UNKNOWN; + } else { + static_cast(ty); + } +} + IfcEntityList::ptr IfcSelectHelperEntity::getInverse(IfcSchema::Type::Enum,int,const std::string &) {throw IfcParse::IfcException("Invalid cast");} IfcEntityList::ptr IfcSelectHelperEntity::getInverse(IfcSchema::Type::Enum) {throw IfcParse::IfcException("Invalid cast");} std::string IfcSelectHelperEntity::datatype() const { return IfcSchema::Type::ToString(_type); } @@ -342,7 +352,7 @@ std::string IfcSelectHelperEntity::toString(bool upper) const { return ss.str(); } unsigned int IfcSelectHelperEntity::id() { throw IfcParse::IfcException("Invalid cast"); } -bool IfcSelectHelperEntity::isWritable() { throw IfcParse::IfcException("Invalid cast"); } +IfcWrite::IfcWritableEntity* IfcSelectHelperEntity::isWritable() { throw IfcParse::IfcException("Invalid cast"); } IfcSelectHelper::IfcSelectHelper(const std::string& v, IfcSchema::Type::Enum t) { IfcWriteArgument* a = new IfcWriteArgument(0); diff --git a/src/ifcparse/IfcWrite.h b/src/ifcparse/IfcWrite.h index e28f4a87a4..d09d014c43 100644 --- a/src/ifcparse/IfcWrite.h +++ b/src/ifcparse/IfcWrite.h @@ -132,6 +132,7 @@ namespace IfcWrite { std::string toString(bool upper=false) const; unsigned int Size() const; argument_type argumentType() const; + IfcUtil::ArgumentType IfcWriteArgument::type() const; }; /// An entity to help with passing of SELECT arguments that @@ -154,7 +155,7 @@ namespace IfcWrite { bool is(IfcSchema::Type::Enum t) const; std::string toString(bool upper = false) const; unsigned int id(); - bool isWritable(); + IfcWritableEntity* isWritable(); }; /// A helper class for passing of SELECT arguments that