Skip to content

Commit 872dd4e

Browse files
committed
Rewrite IfcFile::AddEntity() not to rely on exceptions, as suggested by ch0kee.
1 parent 6e44683 commit 872dd4e

File tree

6 files changed

+133
-26
lines changed

6 files changed

+133
-26
lines changed

src/ifcparse/IfcParse.cpp

Lines changed: 81 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,27 @@ bool TokenFunc::isEnumeration(const Token& t) {
346346
bool TokenFunc::isDatatype(const Token& t) {
347347
return ! isOperator(t) && startsWith(t, 'I');
348348
}
349+
bool TokenFunc::isInt(const Token& t) {
350+
if (isOperator(t)) return false;
351+
const std::string str = asString(t);
352+
const char* start = str.c_str();
353+
char* end;
354+
long result = strtol(start,&end,10);
355+
return ((end - start) == str.length());
356+
}
357+
bool TokenFunc::isBool(const Token& t) {
358+
if (!isEnumeration(t)) return false;
359+
const std::string str = asString(t);
360+
return str == "T" || str == "F";
361+
}
362+
bool TokenFunc::isFloat(const Token& t) {
363+
if (isOperator(t)) return false;
364+
const std::string str = asString(t);
365+
const char* start = str.c_str();
366+
char* end;
367+
double result = strtod(start,&end);
368+
return ((end - start) == str.length());
369+
}
349370
int TokenFunc::asInt(const Token& t) {
350371
const std::string str = asString(t);
351372
// In case of an ENTITY_INSTANCE_NAME skip the leading #
@@ -415,6 +436,22 @@ ArgumentList::ArgumentList(Tokens* t, std::vector<unsigned int>& ids) {
415436
}
416437
}
417438

439+
IfcUtil::ArgumentType ArgumentList::type() const {
440+
if (list.empty()) return IfcUtil::Argument_UNKNOWN;
441+
const IfcUtil::ArgumentType elem_type = list[0]->type();
442+
if (elem_type == IfcUtil::Argument_INT) {
443+
return IfcUtil::Argument_VECTOR_INT;
444+
} else if (elem_type == IfcUtil::Argument_DOUBLE) {
445+
return IfcUtil::Argument_VECTOR_DOUBLE;
446+
} else if (elem_type == IfcUtil::Argument_STRING) {
447+
return IfcUtil::Argument_VECTOR_STRING;
448+
} else if (elem_type == IfcUtil::Argument_ENTITY) {
449+
return IfcUtil::Argument_ENTITY_LIST;
450+
} else {
451+
return IfcUtil::Argument_UNKNOWN;
452+
}
453+
}
454+
418455
void ArgumentList::Push(Argument* l) {
419456
list.push_back(l);
420457
}
@@ -499,6 +536,24 @@ ArgumentList::~ArgumentList() {
499536
list.clear();
500537
}
501538

539+
IfcUtil::ArgumentType TokenArgument::type() const {
540+
if (TokenFunc::isInt(token)) {
541+
return IfcUtil::Argument_INT;
542+
} else if (TokenFunc::isBool(token)) {
543+
return IfcUtil::Argument_BOOL;
544+
} else if (TokenFunc::isFloat(token)) {
545+
return IfcUtil::Argument_DOUBLE;
546+
} else if (TokenFunc::isString(token)) {
547+
return IfcUtil::Argument_STRING;
548+
} else if (TokenFunc::isEnumeration(token)) {
549+
return IfcUtil::Argument_ENUMERATION;
550+
} else if (TokenFunc::isIdentifier(token)) {
551+
return IfcUtil::Argument_ENTITY;
552+
} else {
553+
return IfcUtil::Argument_UNKNOWN;
554+
}
555+
}
556+
502557
//
503558
// Functions for casting the TokenArgument to other types
504559
//
@@ -522,6 +577,11 @@ std::string TokenArgument::toString(bool upper) const {
522577
}
523578
}
524579
bool TokenArgument::isNull() const { return TokenFunc::isOperator(token,'$'); }
580+
581+
IfcUtil::ArgumentType EntityArgument::type() const {
582+
return IfcUtil::Argument_ENTITY;
583+
}
584+
525585
//
526586
// Functions for casting the EntityArgument to other types
527587
//
@@ -679,8 +739,8 @@ IfcEntityList::ptr Entity::getInverse(IfcSchema::Type::Enum c, int i, const std:
679739
bool Entity::is(IfcSchema::Type::Enum v) const { return _type == v; }
680740
unsigned int Entity::id() { return _id; }
681741

682-
bool Entity::isWritable() {
683-
return false;
742+
IfcWrite::IfcWritableEntity* Entity::isWritable() {
743+
return 0;
684744
}
685745

686746
IfcFile::IfcFile() {
@@ -822,7 +882,7 @@ void IfcFile::AddEntity(IfcUtil::IfcBaseClass* entity) {
822882
// For newly created entities ensure a valid ENTITY_INSTANCE_NAME is set
823883
if ( entity->entity->isWritable() ) {
824884
if ( ! entity->entity->file ) entity->entity->file = this;
825-
new_id = ((IfcWrite::IfcWritableEntity*)(entity->entity))->setId();
885+
new_id = entity->entity->isWritable()->setId();
826886
} else {
827887
// TODO: Detect and fix ENTITY_INSTANCE_NAME collisions
828888
new_id = entity->entity->id();
@@ -837,22 +897,32 @@ void IfcFile::AddEntity(IfcUtil::IfcBaseClass* entity) {
837897
unsigned arg_count = entity->entity->getArgumentCount();
838898
for (unsigned i = 0; i < arg_count; ++i) {
839899
Argument* arg = entity->entity->getArgument(i);
900+
901+
// Create a flat list of entity instances referenced by the instance that is being added
840902
IfcEntityList::ptr entity_attributes(new IfcEntityList);
841-
try {
903+
if (arg->type() == IfcUtil::Argument_ENTITY) {
842904
IfcUtil::IfcBaseClass* entity_attribute = *arg;
843905
entity_attributes->push(entity_attribute);
844-
} catch(IfcParse::IfcException&) {
845-
try {
846-
IfcEntityList::ptr entity_list_attribute = *arg;
847-
entity_attributes->push(entity_list_attribute);
848-
} catch(IfcParse::IfcException&) {}
906+
} else if (arg->type() == IfcUtil::Argument_ENTITY_LIST) {
907+
IfcEntityList::ptr entity_list_attribute = *arg;
908+
entity_attributes->push(entity_list_attribute);
909+
} else if (arg->type() == IfcUtil::Argument_ENTITY_LIST_LIST) {
910+
IfcEntityListList::ptr entity_list_attribute = *arg;
911+
for (IfcEntityListList::outer_it it = entity_list_attribute->begin(); it != entity_list_attribute->end(); ++it) {
912+
for (IfcEntityListList::inner_it jt = it->begin(); jt != it->end(); ++jt) {
913+
entity_attributes->push(*jt);
914+
}
915+
}
849916
}
917+
850918
for (IfcEntityList::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) {
851919
IfcUtil::IfcBaseClass* entity_attribute = *it;
852920
try {
853921
if (entity_attribute->entity->isWritable()) {
854-
if ( ! entity_attribute->entity->file ) entity_attribute->entity->file = this;
855-
((IfcWrite::IfcWritableEntity*)(entity_attribute->entity))->setId();
922+
if ( ! entity_attribute->entity->file ) {
923+
entity_attribute->entity->file = this;
924+
}
925+
entity_attribute->entity->isWritable()->setId();
856926
}
857927
unsigned entity_attribute_id = entity_attribute->entity->id();
858928
IfcEntityList::ptr refs = EntitiesByReference(entity_attribute_id);

src/ifcparse/IfcParse.h

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,18 @@ namespace IfcParse {
6969
static bool isString(const Token& t);
7070
/// Returns whether the token can be interpreted as an identifier
7171
static bool isIdentifier(const Token& t);
72-
/// Returns whether the token can be interpreted as an syntactical operator
72+
/// Returns whether the token can be interpreted as a syntactical operator
7373
static bool isOperator(const Token& t, char op = 0);
7474
/// Returns whether the token can be interpreted as an enumerated value
7575
static bool isEnumeration(const Token& t);
76-
/// Returns whether the token can be interpreted as an datatype name
76+
/// Returns whether the token can be interpreted as a datatype name
7777
static bool isDatatype(const Token& t);
78+
/// Returns whether the token can be interpreted as an integer
79+
static bool isInt(const Token& t);
80+
/// Returns whether the token can be interpreted as a boolean
81+
static bool isBool(const Token& t);
82+
/// Returns whether the token can be interpreted as a floating point number
83+
static bool isFloat(const Token& t);
7884
/// Returns the token interpreted as an integer
7985
static int asInt(const Token& t);
8086
/// Returns the token interpreted as an boolean (.T. or .F.)
@@ -120,6 +126,9 @@ namespace IfcParse {
120126
public:
121127
ArgumentList(Tokens* t, std::vector<unsigned int>& ids);
122128
~ArgumentList();
129+
130+
IfcUtil::ArgumentType type() const;
131+
123132
operator int() const;
124133
operator bool() const;
125134
operator double() const;
@@ -128,7 +137,6 @@ namespace IfcParse {
128137
operator std::vector<int>() const;
129138
operator std::vector<std::string>() const;
130139
operator IfcUtil::IfcBaseClass*() const;
131-
//operator IfcUtil::IfcAbstractSelect::ptr() const;
132140
operator IfcEntityList::ptr() const;
133141
operator IfcEntityListList::ptr() const;
134142
unsigned int Size() const;
@@ -146,6 +154,9 @@ namespace IfcParse {
146154
public:
147155
Token token;
148156
TokenArgument(const Token& t);
157+
158+
IfcUtil::ArgumentType type() const;
159+
149160
operator int() const;
150161
operator bool() const;
151162
operator double() const;
@@ -154,7 +165,6 @@ namespace IfcParse {
154165
operator std::vector<int>() const;
155166
operator std::vector<std::string>() const;
156167
operator IfcUtil::IfcBaseClass*() const;
157-
//operator IfcUtil::IfcAbstractSelect::ptr() const;
158168
operator IfcEntityList::ptr() const;
159169
operator IfcEntityListList::ptr() const;
160170
unsigned int Size() const;
@@ -172,6 +182,9 @@ namespace IfcParse {
172182
public:
173183
EntityArgument(IfcSchema::Type::Enum ty, const Token& t);
174184
~EntityArgument();
185+
186+
IfcUtil::ArgumentType type() const;
187+
175188
operator int() const;
176189
operator bool() const;
177190
operator double() const;
@@ -180,7 +193,6 @@ namespace IfcParse {
180193
operator std::vector<int>() const;
181194
operator std::vector<std::string>() const;
182195
operator IfcUtil::IfcBaseClass*() const;
183-
//operator IfcUtil::IfcAbstractSelect::ptr() const;
184196
operator IfcEntityList::ptr() const;
185197
operator IfcEntityListList::ptr() const;
186198
unsigned int Size() const;
@@ -214,7 +226,7 @@ namespace IfcParse {
214226
IfcSchema::Type::Enum type() const;
215227
bool is(IfcSchema::Type::Enum v) const;
216228
unsigned int id();
217-
bool isWritable();
229+
IfcWrite::IfcWritableEntity* isWritable();
218230
};
219231

220232
typedef std::map<IfcSchema::Type::Enum, IfcEntityList::ptr> MapEntitiesByType;

src/ifcparse/IfcUtil.h

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,24 @@ class Argument;
3636
class IfcEntityList;
3737
class IfcEntityListList;
3838
class IfcAbstractEntity;
39+
namespace IfcWrite {
40+
class IfcWritableEntity;
41+
}
3942

4043
namespace IfcUtil {
4144
enum ArgumentType {
42-
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
45+
Argument_INT,
46+
Argument_BOOL,
47+
Argument_DOUBLE,
48+
Argument_STRING,
49+
Argument_VECTOR_INT,
50+
Argument_VECTOR_DOUBLE,
51+
Argument_VECTOR_STRING,
52+
Argument_ENUMERATION,
53+
Argument_ENTITY,
54+
Argument_ENTITY_LIST,
55+
Argument_ENTITY_LIST_LIST,
56+
Argument_UNKNOWN
4357
};
4458

4559
class IfcBaseClass {
@@ -208,8 +222,7 @@ namespace IfcParse {
208222

209223
class Argument {
210224
public:
211-
//void* file;
212-
//public:
225+
virtual IfcUtil::ArgumentType type() const = 0;
213226
virtual operator int() const = 0;
214227
virtual operator bool() const = 0;
215228
virtual operator double() const = 0;
@@ -218,7 +231,6 @@ class Argument {
218231
virtual operator std::vector<int>() const = 0;
219232
virtual operator std::vector<std::string>() const = 0;
220233
virtual operator IfcUtil::IfcBaseClass*() const = 0;
221-
//virtual operator IfcUtil::IfcAbstractSelect::ptr() const = 0;
222234
virtual operator IfcEntityList::ptr() const = 0;
223235
virtual operator IfcEntityListList::ptr() const = 0;
224236
virtual unsigned int Size() const = 0;
@@ -241,7 +253,7 @@ class IfcAbstractEntity {
241253
virtual bool is(IfcSchema::Type::Enum v) const = 0;
242254
virtual std::string toString(bool upper=false) const = 0;
243255
virtual unsigned int id() = 0;
244-
virtual bool isWritable() = 0;
256+
virtual IfcWrite::IfcWritableEntity* isWritable() = 0;
245257
};
246258

247259
class Logger {

src/ifcparse/IfcWritableEntity.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ namespace IfcWrite {
4848
public:
4949
IfcWritableEntity(IfcSchema::Type::Enum t);
5050
~IfcWritableEntity();
51+
5152
int setId(int i=-1);
5253
IfcWritableEntity(IfcAbstractEntity* e);
5354
IfcEntityList::ptr getInverse(IfcSchema::Type::Enum c = IfcSchema::Type::ALL);
@@ -59,7 +60,8 @@ namespace IfcWrite {
5960
bool is(IfcSchema::Type::Enum v) const;
6061
std::string toString(bool upper=false) const;
6162
unsigned int id();
62-
bool isWritable();
63+
IfcWritableEntity* isWritable();
64+
6365
void setArgument(int i);
6466
void setArgumentDerived(int i);
6567
void setArgument(int i,bool v);

src/ifcparse/IfcWrite.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ unsigned int IfcWritableEntity::id() {
110110
}
111111
return *_id;
112112
}
113-
bool IfcWritableEntity::isWritable() { return true; }
113+
IfcWritableEntity* IfcWritableEntity::isWritable() { return this; }
114114
bool IfcWritableEntity::arg_writable(int i) {
115115
std::map<int,bool>::const_iterator it = writemask.find(i);
116116
if ( it == writemask.end() ) return false;
@@ -322,6 +322,16 @@ IfcWriteArgument::argument_type IfcWriteArgument::argumentType() const {
322322
return static_cast<argument_type>(container.which());
323323
}
324324

325+
IfcUtil::ArgumentType IfcWriteArgument::type() const {
326+
// TODO: Make these the same enumeration
327+
int ty = static_cast<int>(container.which()) - 2;
328+
if (ty < 0) {
329+
return IfcUtil::Argument_UNKNOWN;
330+
} else {
331+
static_cast<IfcUtil::ArgumentType>(ty);
332+
}
333+
}
334+
325335
IfcEntityList::ptr IfcSelectHelperEntity::getInverse(IfcSchema::Type::Enum,int,const std::string &) {throw IfcParse::IfcException("Invalid cast");}
326336
IfcEntityList::ptr IfcSelectHelperEntity::getInverse(IfcSchema::Type::Enum) {throw IfcParse::IfcException("Invalid cast");}
327337
std::string IfcSelectHelperEntity::datatype() const { return IfcSchema::Type::ToString(_type); }
@@ -342,7 +352,7 @@ std::string IfcSelectHelperEntity::toString(bool upper) const {
342352
return ss.str();
343353
}
344354
unsigned int IfcSelectHelperEntity::id() { throw IfcParse::IfcException("Invalid cast"); }
345-
bool IfcSelectHelperEntity::isWritable() { throw IfcParse::IfcException("Invalid cast"); }
355+
IfcWrite::IfcWritableEntity* IfcSelectHelperEntity::isWritable() { throw IfcParse::IfcException("Invalid cast"); }
346356

347357
IfcSelectHelper::IfcSelectHelper(const std::string& v, IfcSchema::Type::Enum t) {
348358
IfcWriteArgument* a = new IfcWriteArgument(0);

src/ifcparse/IfcWrite.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ namespace IfcWrite {
132132
std::string toString(bool upper=false) const;
133133
unsigned int Size() const;
134134
argument_type argumentType() const;
135+
IfcUtil::ArgumentType IfcWriteArgument::type() const;
135136
};
136137

137138
/// An entity to help with passing of SELECT arguments that
@@ -154,7 +155,7 @@ namespace IfcWrite {
154155
bool is(IfcSchema::Type::Enum t) const;
155156
std::string toString(bool upper = false) const;
156157
unsigned int id();
157-
bool isWritable();
158+
IfcWritableEntity* isWritable();
158159
};
159160

160161
/// A helper class for passing of SELECT arguments that

0 commit comments

Comments
 (0)