Skip to content

Commit df18059

Browse files
committed
Create writable argument copies when duplicating entity instances
1 parent 5ea1397 commit df18059

File tree

3 files changed

+101
-9
lines changed

3 files changed

+101
-9
lines changed

src/ifcparse/IfcParse.cpp

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,9 @@ bool TokenFunc::isKeyword(const Token& t) {
382382
}
383383

384384
bool TokenFunc::isInt(const Token& t) {
385-
if (isOperator(t)) return false;
385+
if (isOperator(t) || isString(t) || isEnumeration(t)) {
386+
return false;
387+
}
386388
const std::string str = asString(t);
387389
const char* start = str.c_str();
388390
char* end;
@@ -397,7 +399,9 @@ bool TokenFunc::isBool(const Token& t) {
397399
}
398400

399401
bool TokenFunc::isFloat(const Token& t) {
400-
if (isOperator(t)) return false;
402+
if (isOperator(t) || isString(t) || isEnumeration(t)) {
403+
return false;
404+
}
401405
const std::string str = asString(t);
402406
const char* start = str.c_str();
403407
char* end;
@@ -623,6 +627,10 @@ IfcUtil::ArgumentType TokenArgument::type() const {
623627
return IfcUtil::Argument_ENUMERATION;
624628
} else if (TokenFunc::isIdentifier(token)) {
625629
return IfcUtil::Argument_ENTITY;
630+
} else if (TokenFunc::isOperator(token, '$')) {
631+
return IfcUtil::Argument_NULL;
632+
} else if (TokenFunc::isOperator(token, '*')) {
633+
return IfcUtil::Argument_DERIVED;
626634
} else {
627635
return IfcUtil::Argument_UNKNOWN;
628636
}
@@ -991,7 +999,9 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
991999
entity_file_map.insert(entity_entity_map_t::value_type(*it, addEntity(*it)));
9921000
}
9931001
}
994-
} catch (...) {}
1002+
} catch (...) {
1003+
Logger::Message(Logger::LOG_ERROR, "Failed to visit forward references of", entity->entity);
1004+
}
9951005

9961006
// See whether the instance is already part of a file
9971007
if (entity->entity->file != 0) {
@@ -1020,12 +1030,16 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
10201030
Argument* attr = we->getArgument(i);
10211031
IfcUtil::ArgumentType attr_type = attr->type();
10221032
if (attr_type == IfcUtil::Argument_ENTITY) {
1023-
we->setArgument(i, entity_file_map[*attr]);
1033+
entity_entity_map_t::const_iterator eit = entity_file_map.find(*attr);
1034+
if (eit == entity_file_map.end()) throw IfcParse::IfcException("Unable to map instance to file");
1035+
we->setArgument(i, eit->second);
10241036
} else if (attr_type == IfcUtil::Argument_ENTITY_LIST) {
10251037
IfcEntityList::ptr instances = *attr;
10261038
IfcEntityList::ptr new_instances(new IfcEntityList);
10271039
for (IfcEntityList::it it = instances->begin(); it != instances->end(); ++it) {
1028-
new_instances->push(entity_file_map[*it]);
1040+
entity_entity_map_t::const_iterator eit = entity_file_map.find(*it);
1041+
if (eit == entity_file_map.end()) throw IfcParse::IfcException("Unable to map instance to file");
1042+
new_instances->push(eit->second);
10291043
}
10301044
we->setArgument(i, new_instances);
10311045
} else if (attr_type == IfcUtil::Argument_ENTITY_LIST_LIST) {
@@ -1034,7 +1048,9 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
10341048
for (IfcEntityListList::outer_it it = instances->begin(); it != instances->end(); ++it) {
10351049
std::vector<IfcUtil::IfcBaseClass*> list;
10361050
for (IfcEntityListList::inner_it jt = it->begin(); jt != it->end(); ++jt) {
1037-
list.push_back(entity_file_map[*jt]);
1051+
entity_entity_map_t::const_iterator eit = entity_file_map.find(*jt);
1052+
if (eit == entity_file_map.end()) throw IfcParse::IfcException("Unable to map instance to file");
1053+
list.push_back(eit->second);
10381054
}
10391055
new_instances->push(list);
10401056
}

src/ifcparse/IfcWritableEntity.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ namespace IfcWrite {
6161
unsigned int id();
6262
IfcWritableEntity* isWritable();
6363

64-
void setArgument(int i);
64+
void setArgument(int i);
65+
void setArgument(int i, Argument* a);
6566
void setArgumentDerived(int i);
6667
void setArgument(int i,bool v);
6768
void setArgument(int i,int v);

src/ifcparse/IfcWrite.cpp

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@
2626
#include "../ifcparse/IfcCharacterDecoder.h"
2727
#include "../ifcparse/IfcFile.h"
2828

29+
#ifdef USE_IFC4
30+
#include "../ifcparse/Ifc4-latebound.h"
31+
#else
32+
#include "../ifcparse/Ifc2x3-latebound.h"
33+
#endif
34+
2935
using namespace IfcWrite;
3036

3137
IfcWritableEntity::IfcWritableEntity(IfcSchema::Type::Enum t) {
@@ -56,8 +62,7 @@ IfcWritableEntity::IfcWritableEntity(IfcAbstractEntity* e)
5662

5763
const unsigned int count = e->getArgumentCount();
5864
for ( unsigned int i = 0; i < count; ++ i ) {
59-
args[i] = e->getArgument(i);
60-
writemask[i] = false;
65+
this->setArgument(i, e->getArgument(i));
6166
}
6267
}
6368

@@ -131,6 +136,76 @@ template <typename T> void IfcWritableEntity::_setArgument(int i, const T& t) {
131136
void IfcWritableEntity::setArgument(int i) {
132137
_setArgument(i, boost::none);
133138
}
139+
140+
void IfcWritableEntity::setArgument(int i, Argument* a) {
141+
IfcWrite::IfcWriteArgument* wa = new IfcWrite::IfcWriteArgument(this);
142+
IfcUtil::ArgumentType attr_type = a->type();
143+
switch(attr_type) {
144+
case IfcUtil::Argument_NULL:
145+
this->setArgument(i);
146+
break;
147+
case IfcUtil::Argument_DERIVED:
148+
this->setArgumentDerived(i);
149+
break;
150+
case IfcUtil::Argument_INT:
151+
this->setArgument(i, static_cast<int>(*a));
152+
break;
153+
case IfcUtil::Argument_BOOL:
154+
this->setArgument(i, static_cast<bool>(*a));
155+
break;
156+
case IfcUtil::Argument_DOUBLE:
157+
this->setArgument(i, static_cast<double>(*a));
158+
break;
159+
case IfcUtil::Argument_STRING:
160+
this->setArgument(i, static_cast<std::string>(*a));
161+
break;
162+
case IfcUtil::Argument_VECTOR_INT:
163+
this->setArgument(i, static_cast< std::vector<int> >(*a));
164+
break;
165+
case IfcUtil::Argument_VECTOR_DOUBLE:
166+
this->setArgument(i, static_cast< std::vector<double> >(*a));
167+
break;
168+
case IfcUtil::Argument_VECTOR_STRING:
169+
this->setArgument(i, static_cast< std::vector< std::string > >(*a));
170+
break;
171+
case IfcUtil::Argument_ENUMERATION: {
172+
IfcSchema::Type::Enum ty = IfcSchema::Type::GetAttributeEntity(_type, i);
173+
std::string enum_literal = a->toString();
174+
// Remove leading and trailing '.'
175+
enum_literal = enum_literal.substr(1, enum_literal.size() - 2);
176+
std::pair<const char*, int> enum_ref = IfcSchema::Type::GetEnumerationIndex(ty, enum_literal);
177+
this->setArgument(i, enum_ref.second, enum_ref.first); }
178+
break;
179+
case IfcUtil::Argument_ENTITY: {
180+
this->setArgument(i, static_cast<IfcUtil::IfcBaseClass*>(*a)); }
181+
break;
182+
case IfcUtil::Argument_ENTITY_LIST: {
183+
IfcEntityList::ptr instances = *a;
184+
IfcEntityList::ptr mapped_instances(new IfcEntityList);
185+
for (IfcEntityList::it it = instances->begin(); it != instances->end(); ++it) {
186+
mapped_instances->push(*it);
187+
}
188+
this->setArgument(i, mapped_instances); }
189+
break;
190+
case IfcUtil::Argument_ENTITY_LIST_LIST: {
191+
IfcEntityListList::ptr instances = *a;
192+
IfcEntityListList::ptr mapped_instances(new IfcEntityListList);
193+
for (IfcEntityListList::outer_it it = instances->begin(); it != instances->end(); ++it) {
194+
std::vector<IfcUtil::IfcBaseClass*> inner;
195+
for (IfcEntityListList::inner_it jt = it->begin(); jt != it->end(); ++jt) {
196+
inner.push_back(*jt);
197+
}
198+
mapped_instances->push(inner);
199+
}
200+
this->setArgument(i, mapped_instances); }
201+
break;
202+
case IfcUtil::Argument_UNKNOWN:
203+
throw IfcParse::IfcException("Unknown argument encountered");
204+
break;
205+
}
206+
}
207+
208+
134209
void IfcWritableEntity::setArgumentDerived(int i) {
135210
_setArgument(i, IfcWriteArgument::Derived());
136211
}

0 commit comments

Comments
 (0)