mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
ifcparse refactoring (#190)
Unify attribute containers, provide latebound attribute access on IfcBaseEntity, more basic tests on Travis
This commit is contained in:
+26
-284
@@ -25,7 +25,6 @@
|
||||
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
#include "../ifcparse/IfcWrite.h"
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
#include "../ifcparse/IfcCharacterDecoder.h"
|
||||
#include "../ifcparse/IfcFile.h"
|
||||
|
||||
@@ -37,268 +36,6 @@
|
||||
|
||||
using namespace IfcWrite;
|
||||
|
||||
IfcWritableEntity::IfcWritableEntity(IfcSchema::Type::Enum t) {
|
||||
_type = t;
|
||||
_id = 0;
|
||||
file = 0;
|
||||
}
|
||||
IfcWritableEntity::~IfcWritableEntity() {
|
||||
delete _id;
|
||||
for (std::map<int,Argument*>::iterator it = args.begin(); it != args.end(); ++it)
|
||||
delete it->second;
|
||||
}
|
||||
int IfcWritableEntity::setId(int i) {
|
||||
if (i > 0) {
|
||||
delete _id;
|
||||
return *(_id = new int(i));
|
||||
} else {
|
||||
if (_id) { return *_id; }
|
||||
else {
|
||||
delete _id;
|
||||
return *(_id = new int(file->FreshId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
IfcWritableEntity::IfcWritableEntity(IfcAbstractEntity* e)
|
||||
{
|
||||
file = e->file;
|
||||
_type = e->type();
|
||||
_id = new int(e->id());
|
||||
|
||||
const unsigned int count = e->getArgumentCount();
|
||||
for ( unsigned int i = 0; i < count; ++ i ) {
|
||||
this->setArgument(i, e->getArgument(i));
|
||||
}
|
||||
}
|
||||
|
||||
IfcEntityList::ptr IfcWritableEntity::getInverse(IfcSchema::Type::Enum type, int attribute_index) {
|
||||
if (file) {
|
||||
int id = _id ? *_id : setId();
|
||||
return file->getInverse(id, type, attribute_index);
|
||||
} else {
|
||||
throw IfcParse::IfcException("Instance not part of a file");
|
||||
}
|
||||
}
|
||||
|
||||
std::string IfcWritableEntity::datatype() const { return IfcSchema::Type::ToString(_type); }
|
||||
Argument* IfcWritableEntity::getArgument (unsigned int i) {
|
||||
if (args[i] == 0) {
|
||||
_setArgument(i, boost::blank());
|
||||
}
|
||||
return args[i];
|
||||
}
|
||||
unsigned int IfcWritableEntity::getArgumentCount() const { return (unsigned)args.size(); }
|
||||
IfcSchema::Type::Enum IfcWritableEntity::type() const { return _type; }
|
||||
bool IfcWritableEntity::is(IfcSchema::Type::Enum v) const { return _type == v; }
|
||||
std::string IfcWritableEntity::toString(bool upper) const {
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
|
||||
std::string dt = datatype();
|
||||
if (upper) {
|
||||
boost::to_upper(dt);
|
||||
}
|
||||
|
||||
if (_id && !IfcSchema::Type::IsSimple(type())) {
|
||||
ss << "#" << *_id;
|
||||
ss << "=";
|
||||
}
|
||||
|
||||
ss << dt << "(";
|
||||
for (std::map<int,Argument*>::const_iterator it = args.begin(); it != args.end(); ++ it) {
|
||||
if ( it != args.begin() ) ss << ",";
|
||||
ss << it->second->toString(upper);
|
||||
}
|
||||
ss << ")";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
unsigned int IfcWritableEntity::id() {
|
||||
if (!file) {
|
||||
return 0;
|
||||
}
|
||||
if ( !_id ) {
|
||||
_id = new int(file->FreshId());
|
||||
}
|
||||
return *_id;
|
||||
}
|
||||
IfcWritableEntity* IfcWritableEntity::isWritable() { return this; }
|
||||
bool IfcWritableEntity::arg_writable(int i) {
|
||||
std::map<int,bool>::const_iterator it = writemask.find(i);
|
||||
if ( it == writemask.end() ) return false;
|
||||
else return it->second;
|
||||
}
|
||||
void IfcWritableEntity::arg_writable(int i, bool b) {
|
||||
writemask[i] = b;
|
||||
}
|
||||
|
||||
template <typename T> void IfcWritableEntity::_setArgument(int i, const T& t) {
|
||||
if ( arg_writable(i) ) delete args[i];
|
||||
IfcWriteArgument* arg = new IfcWriteArgument;
|
||||
args[i] = arg;
|
||||
arg->set(t);
|
||||
arg_writable(i,true);
|
||||
}
|
||||
|
||||
void IfcWritableEntity::setArgument(int i) {
|
||||
_setArgument(i, boost::none);
|
||||
}
|
||||
|
||||
void IfcWritableEntity::setArgument(int i, Argument* a, IfcUtil::ArgumentType attr_type) {
|
||||
if (attr_type == IfcUtil::Argument_UNKNOWN) {
|
||||
attr_type = a->type();
|
||||
}
|
||||
switch(attr_type) {
|
||||
case IfcUtil::Argument_NULL:
|
||||
this->setArgument(i);
|
||||
break;
|
||||
case IfcUtil::Argument_DERIVED:
|
||||
this->setArgumentDerived(i);
|
||||
break;
|
||||
case IfcUtil::Argument_INT:
|
||||
this->setArgument(i, static_cast<int>(*a));
|
||||
break;
|
||||
case IfcUtil::Argument_BOOL:
|
||||
this->setArgument(i, static_cast<bool>(*a));
|
||||
break;
|
||||
case IfcUtil::Argument_DOUBLE:
|
||||
this->setArgument(i, static_cast<double>(*a));
|
||||
break;
|
||||
case IfcUtil::Argument_STRING:
|
||||
this->setArgument(i, static_cast<std::string>(*a));
|
||||
break;
|
||||
case IfcUtil::Argument_BINARY: {
|
||||
boost::dynamic_bitset<> attr_value = *a;
|
||||
this->setArgument(i, attr_value); }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_INT: {
|
||||
std::vector<int> attr_value = *a;
|
||||
this->setArgument(i, attr_value); }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_DOUBLE: {
|
||||
std::vector<double> attr_value = *a;
|
||||
this->setArgument(i, attr_value); }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_STRING: {
|
||||
std::vector<std::string> attr_value = *a;
|
||||
this->setArgument(i, attr_value); }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_BINARY: {
|
||||
std::vector< boost::dynamic_bitset<> > attr_value = *a;
|
||||
this->setArgument(i, attr_value); }
|
||||
break;
|
||||
case IfcUtil::Argument_ENUMERATION: {
|
||||
IfcSchema::Type::Enum ty = IfcSchema::Type::GetAttributeEntity(_type, (unsigned char)i);
|
||||
std::string enum_literal = a->toString();
|
||||
// Remove leading and trailing '.'
|
||||
enum_literal = enum_literal.substr(1, enum_literal.size() - 2);
|
||||
std::pair<const char*, int> enum_ref = IfcSchema::Type::GetEnumerationIndex(ty, enum_literal);
|
||||
this->setArgument(i, enum_ref.second, enum_ref.first); }
|
||||
break;
|
||||
case IfcUtil::Argument_ENTITY_INSTANCE: {
|
||||
this->setArgument(i, static_cast<IfcUtil::IfcBaseClass*>(*a)); }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: {
|
||||
IfcEntityList::ptr instances = *a;
|
||||
IfcEntityList::ptr mapped_instances(new IfcEntityList);
|
||||
for (IfcEntityList::it it = instances->begin(); it != instances->end(); ++it) {
|
||||
mapped_instances->push(*it);
|
||||
}
|
||||
this->setArgument(i, mapped_instances); }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT: {
|
||||
std::vector< std::vector<int> > attr_value = *a;
|
||||
this->setArgument(i, attr_value); }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE: {
|
||||
std::vector< std::vector<double> > attr_value = *a;
|
||||
this->setArgument(i, attr_value); }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE: {
|
||||
IfcEntityListList::ptr instances = *a;
|
||||
IfcEntityListList::ptr mapped_instances(new IfcEntityListList);
|
||||
for (IfcEntityListList::outer_it it = instances->begin(); it != instances->end(); ++it) {
|
||||
std::vector<IfcUtil::IfcBaseClass*> inner;
|
||||
for (IfcEntityListList::inner_it jt = it->begin(); jt != it->end(); ++jt) {
|
||||
inner.push_back(*jt);
|
||||
}
|
||||
mapped_instances->push(inner);
|
||||
}
|
||||
this->setArgument(i, mapped_instances); }
|
||||
break;
|
||||
case IfcUtil::Argument_EMPTY_AGGREGATE:
|
||||
case IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE: {
|
||||
IfcUtil::ArgumentType t2 = IfcSchema::Type::GetAttributeType(type(), (unsigned char) i);
|
||||
this->setArgument(i, a, t2); }
|
||||
break;
|
||||
default:
|
||||
case IfcUtil::Argument_UNKNOWN:
|
||||
throw IfcParse::IfcException(std::string("Unknown attribute encountered: '") + a->toString() + "' at index '" + boost::lexical_cast<std::string>(i) + "'");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void IfcWritableEntity::setArgumentDerived(int i) {
|
||||
_setArgument(i, IfcWriteArgument::Derived());
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,int v) {
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,bool v) {
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,int v, const char* c){
|
||||
_setArgument(i, IfcWriteArgument::EnumerationReference(v, c));
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::string& v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const boost::dynamic_bitset<>& v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,double v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,IfcUtil::IfcBaseClass* v){
|
||||
if ( v ) {
|
||||
_setArgument(i, v);
|
||||
} else {
|
||||
_setArgument(i, boost::none);
|
||||
}
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,IfcEntityList::ptr v){
|
||||
if ( v.get() ) {
|
||||
_setArgument(i, v);
|
||||
} else {
|
||||
_setArgument(i, boost::none);
|
||||
}
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,IfcEntityListList::ptr v){
|
||||
if ( v.get() ) {
|
||||
_setArgument(i, v);
|
||||
} else {
|
||||
_setArgument(i, boost::none);
|
||||
}
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::vector<double>& v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::vector< std::vector<double> >& v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::vector<std::string>& v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::vector<int>& v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::vector< std::vector<int> >& v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::vector< boost::dynamic_bitset<> >& v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
|
||||
class SizeVisitor : public boost::static_visitor<int> {
|
||||
public:
|
||||
int operator()(const boost::blank& /*i*/) const { return -1; }
|
||||
@@ -407,7 +144,7 @@ public:
|
||||
data << "." << i.enumeration_value << ".";
|
||||
}
|
||||
void operator()(const IfcUtil::IfcBaseClass* const& i) {
|
||||
IfcAbstractEntity* e = i->entity;
|
||||
IfcEntityInstanceData* e = i->entity;
|
||||
if ( IfcSchema::Type::IsSimple(e->type()) ) {
|
||||
data << e->toString(upper);
|
||||
} else {
|
||||
@@ -447,12 +184,8 @@ void StringBuilderVisitor::serialize(const std::vector<std::string>& i) {
|
||||
data << "(";
|
||||
for (std::vector<std::string>::const_iterator it = i.begin(); it != i.end(); ++it) {
|
||||
if (it != i.begin()) data << ",";
|
||||
if (upper) {
|
||||
std::string s = IfcCharacterEncoder(*it);
|
||||
data << s;
|
||||
} else {
|
||||
data << *it;
|
||||
}
|
||||
std::string s = IfcCharacterEncoder(*it);
|
||||
data << s;
|
||||
}
|
||||
data << ")";
|
||||
}
|
||||
@@ -540,20 +273,29 @@ IfcUtil::ArgumentType IfcWriteArgument::type() const {
|
||||
return static_cast<IfcUtil::ArgumentType>(container.which());
|
||||
}
|
||||
|
||||
EntityBuffer* EntityBuffer::i = 0;
|
||||
EntityBuffer* EntityBuffer::instance() {
|
||||
if ( ! i ) {
|
||||
i = new EntityBuffer();
|
||||
i->buffer = IfcEntityList::ptr(new IfcEntityList);
|
||||
// Overload to detect null values
|
||||
void IfcWriteArgument::set(const IfcEntityList::ptr& v) {
|
||||
if (v) {
|
||||
container = v;
|
||||
} else {
|
||||
container = boost::blank();
|
||||
}
|
||||
return i;
|
||||
}
|
||||
IfcEntityList::ptr EntityBuffer::Get() {
|
||||
return instance()->buffer;
|
||||
}
|
||||
void EntityBuffer::Clear() {
|
||||
instance()->buffer = IfcEntityList::ptr(new IfcEntityList);
|
||||
}
|
||||
void EntityBuffer::Add(IfcUtil::IfcBaseClass* e) {
|
||||
instance()->buffer->push(e);
|
||||
|
||||
// Overload to detect null values
|
||||
void IfcWriteArgument::set(const IfcEntityListList::ptr& v) {
|
||||
if (v) {
|
||||
container = v;
|
||||
} else {
|
||||
container = boost::blank();
|
||||
}
|
||||
}
|
||||
|
||||
// Overload to detect null values
|
||||
void IfcWriteArgument::set(IfcUtil::IfcBaseClass*const& v) {
|
||||
if (v) {
|
||||
container = v;
|
||||
} else {
|
||||
container = boost::blank();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user