From 27962701b93c336e643678850160b91500920654 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 4 Aug 2013 04:49:08 +0000 Subject: [PATCH] Use boost::variant for writable arguments in the IFC serializer --- src/ifcconvert/ColladaSerializer.h | 16 +- src/ifcparse/IfcWritableEntity.h | 2 + src/ifcparse/IfcWrite.cpp | 412 ++++++++++++----------------- src/ifcparse/IfcWrite.h | 190 ++++++------- 4 files changed, 252 insertions(+), 368 deletions(-) diff --git a/src/ifcconvert/ColladaSerializer.h b/src/ifcconvert/ColladaSerializer.h index a7813234ea..6e0e6e88c0 100644 --- a/src/ifcconvert/ColladaSerializer.h +++ b/src/ifcconvert/ColladaSerializer.h @@ -92,15 +92,15 @@ private: }; class DeferredObject { public: - const std::string guid, name, type; + std::string guid, name, type; int obj_id; - const std::vector matrix; - const std::vector vertices; - const std::vector normals; - const std::vector indices; - const std::vector material_ids; - const std::vector materials; - const std::vector material_references; + std::vector matrix; + std::vector vertices; + std::vector normals; + std::vector indices; + std::vector material_ids; + std::vector materials; + std::vector material_references; DeferredObject(const std::string& guid, const std::string& name, const std::string& type, int obj_id, const std::vector& matrix, const std::vector& vertices, const std::vector& normals, const std::vector& indices, const std::vector& material_ids, const std::vector& materials, const std::vector& material_references) diff --git a/src/ifcparse/IfcWritableEntity.h b/src/ifcparse/IfcWritableEntity.h index b1886fd9d7..41cb051f4a 100644 --- a/src/ifcparse/IfcWritableEntity.h +++ b/src/ifcparse/IfcWritableEntity.h @@ -44,8 +44,10 @@ namespace IfcWrite { int* _id; bool arg_writable(int i); void arg_writable(int i, bool b); + template void _setArgument(int i, const T&); public: IfcWritableEntity(Ifc2x3::Type::Enum t); + ~IfcWritableEntity(); int setId(int i=-1); IfcWritableEntity(IfcAbstractEntity* e); IfcEntities getInverse(Ifc2x3::Type::Enum c = Ifc2x3::Type::ALL); diff --git a/src/ifcparse/IfcWrite.cpp b/src/ifcparse/IfcWrite.cpp index 8a6ffcc70b..87685dd1e6 100644 --- a/src/ifcparse/IfcWrite.cpp +++ b/src/ifcparse/IfcWrite.cpp @@ -29,6 +29,9 @@ IfcWritableEntity::IfcWritableEntity(Ifc2x3::Type::Enum t) { _id = 0; file = 0; } +IfcWritableEntity::~IfcWritableEntity() { + delete _id; +} int IfcWritableEntity::setId(int i) { return *(_id = new int(i > 0 ? i : file->FreshId())); } @@ -36,6 +39,7 @@ IfcWritableEntity::IfcWritableEntity(IfcAbstractEntity* e) { file = e->file; _type = e->type(); + delete _id; _id = new int(e->id()); const unsigned int count = e->getArgumentCount(); @@ -90,7 +94,12 @@ std::string IfcWritableEntity::toString(bool upper) { ss << ")"; return ss.str(); } -unsigned int IfcWritableEntity::id() { if ( !_id ) _id = new int(file->FreshId()); return *_id; } +unsigned int IfcWritableEntity::id() { + if ( !_id ) { + _id = new int(file->FreshId()); + } + return *_id; +} bool IfcWritableEntity::isWritable() { return true; } bool IfcWritableEntity::arg_writable(int i) { std::map::const_iterator it = writemask.find(i); @@ -100,285 +109,185 @@ bool IfcWritableEntity::arg_writable(int i) { void IfcWritableEntity::arg_writable(int i, bool b) { writemask[i] = b; } -void IfcWritableEntity::setArgument(int i) { + +template void IfcWritableEntity::_setArgument(int i, const T& t) { if ( arg_writable(i) ) delete args[i]; - args[i] = new IfcWriteNullArgument(this); + IfcWriteArgument* arg = new IfcWriteArgument(this); + args[i] = arg; + arg->set(t); arg_writable(i,true); } + +void IfcWritableEntity::setArgument(int i) { + _setArgument(i, boost::none); +} void IfcWritableEntity::setArgumentDerived(int i) { - if ( arg_writable(i) ) delete args[i]; - args[i] = new IfcWriteDerivedArgument(this); - arg_writable(i,true); + _setArgument(i, IfcWriteArgument::Derived()); } void IfcWritableEntity::setArgument(int i,int v) { - if ( arg_writable(i) ) delete args[i]; - args[i] = new IfcWriteIntegralArgument(this,v); - arg_writable(i,true); + _setArgument(i, v); } void IfcWritableEntity::setArgument(int i,bool v) { - if ( arg_writable(i) ) delete args[i]; - args[i] = new IfcWriteIntegralArgument(this,v); - arg_writable(i,true); + _setArgument(i, v); } void IfcWritableEntity::setArgument(int i,int v, const char* c){ - if ( arg_writable(i) ) delete args[i]; - args[i] = new IfcWriteEnumerationArgument(this,v,c); - arg_writable(i,true); + _setArgument(i, IfcWriteArgument::EnumerationReference(v, c)); } void IfcWritableEntity::setArgument(int i,const std::string& v){ - if ( arg_writable(i) ) delete args[i]; - args[i] = new IfcWriteIntegralArgument(this,v); - arg_writable(i,true); + _setArgument(i, v); } void IfcWritableEntity::setArgument(int i,double v){ - if ( arg_writable(i) ) delete args[i]; - args[i] = new IfcWriteIntegralArgument(this,v); - arg_writable(i,true); + _setArgument(i, v); } void IfcWritableEntity::setArgument(int i,IfcUtil::IfcSchemaEntity v){ - if ( arg_writable(i) ) delete args[i]; - if ( v ) args[i] = new IfcWriteIntegralArgument(this,v); - else args[i] = new IfcWriteNullArgument(this); - arg_writable(i,true); + if ( v ) { + _setArgument(i, v); + } else { + _setArgument(i, boost::none); + } } void IfcWritableEntity::setArgument(int i,IfcEntities v){ - if ( arg_writable(i) ) delete args[i]; - if ( v.get() ) args[i] = new IfcWriteEntityListArgument(this,v); - else args[i] = new IfcWriteNullArgument(this); - arg_writable(i,true); + if ( v.get() ) { + _setArgument(i, v); + } else { + _setArgument(i, boost::none); + } } void IfcWritableEntity::setArgument(int i,const std::vector& v){ - if ( arg_writable(i) ) delete args[i]; - args[i] = new IfcWriteIntegralArgument(this,v); - arg_writable(i,true); + _setArgument(i, v); } void IfcWritableEntity::setArgument(int i,const std::vector& v){ - if ( arg_writable(i) ) delete args[i]; - args[i] = new IfcWriteIntegralArgument(this,v); - arg_writable(i,true); + _setArgument(i, v); } void IfcWritableEntity::setArgument(int i,const std::vector& v){ - if ( arg_writable(i) ) delete args[i]; - args[i] = new IfcWriteIntegralArgument(this,v); - arg_writable(i,true); + _setArgument(i, v); } -IfcWriteNullArgument::operator int() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteNullArgument::operator bool() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteNullArgument::operator double() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteNullArgument::operator std::string() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteNullArgument::operator std::vector() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteNullArgument::operator std::vector() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteNullArgument::operator std::vector() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteNullArgument::operator IfcUtil::IfcSchemaEntity() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteNullArgument::operator IfcEntities() const { throw IfcParse::IfcException("Invalid cast"); } -bool IfcWriteNullArgument::isNull() const { return true; } -ArgumentPtr IfcWriteNullArgument::operator [] (unsigned int i) const { throw IfcParse::IfcException("Invalid cast"); } -std::string IfcWriteNullArgument::toString(bool upper) const { return "$"; } -unsigned int IfcWriteNullArgument::Size() const { throw IfcParse::IfcException("Invalid cast"); } +class SizeVisitor : public boost::static_visitor { +public: + int operator()(const boost::none_t& i) const { return -1; } + int operator()(const IfcWriteArgument::Derived& i) const { return -1; } + int operator()(const int& i) const { return -1; } + int operator()(const bool& i) const { return -1; } + int operator()(const double& i) const { return -1; } + int operator()(const std::string& i) const { return i.size(); } + int operator()(const std::vector& i) const { return i.size(); } + int operator()(const std::vector& i) const { return i.size(); } + int operator()(const std::vector& i) const { return i.size(); } + int operator()(const IfcWriteArgument::EnumerationReference& i) const { return -1; } + int operator()(const IfcUtil::IfcSchemaEntity& i) const { return -1; } + int operator()(const IfcEntities& i) const { return i->Size(); } +}; -IfcWriteDerivedArgument::operator int() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteDerivedArgument::operator bool() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteDerivedArgument::operator double() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteDerivedArgument::operator std::string() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteDerivedArgument::operator std::vector() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteDerivedArgument::operator std::vector() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteDerivedArgument::operator std::vector() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteDerivedArgument::operator IfcUtil::IfcSchemaEntity() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteDerivedArgument::operator IfcEntities() const { throw IfcParse::IfcException("Invalid cast"); } -bool IfcWriteDerivedArgument::isNull() const { throw IfcParse::IfcException("Invalid cast"); } -ArgumentPtr IfcWriteDerivedArgument::operator [] (unsigned int i) const { throw IfcParse::IfcException("Invalid cast"); } -std::string IfcWriteDerivedArgument::toString(bool upper) const { return "*"; } -unsigned int IfcWriteDerivedArgument::Size() const { throw IfcParse::IfcException("Invalid cast"); } - -IfcWriteEntityListArgument::IfcWriteEntityListArgument(IfcAbstractEntity* e, const IfcEntities& v) : IfcWriteArgument(e) { value = v; } -IfcWriteEntityListArgument::operator int() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteEntityListArgument::operator bool() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteEntityListArgument::operator double() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteEntityListArgument::operator std::string() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteEntityListArgument::operator std::vector() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteEntityListArgument::operator std::vector() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteEntityListArgument::operator std::vector() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteEntityListArgument::operator IfcUtil::IfcSchemaEntity() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteEntityListArgument::operator IfcEntities() const { return value; } -bool IfcWriteEntityListArgument::isNull() const { return false; } -unsigned int IfcWriteEntityListArgument::Size() const { return value->Size(); } -ArgumentPtr IfcWriteEntityListArgument::operator [] (unsigned int i) const { throw IfcParse::IfcException("Invalid cast"); } -std::string IfcWriteEntityListArgument::toString(bool upper) const { - std::ostringstream ss; - ss << "("; - for ( IfcEntityList::it it = value->begin(); it != value->end(); ++ it ) { - if ( it != value->begin() ) ss << ","; - IfcAbstractEntity* e = (*it)->entity; +class StringBuilderVisitor : public boost::static_visitor { +private: + std::ostringstream& data; + template void serialize(const std::vector& i) { + data << "("; + for (typename std::vector::const_iterator it = i.begin(); it != i.end(); ++it) { + if (it != i.begin()) data << ","; + data << *it; + } + data << ")"; + } + // The REAL token definition from the IFC SPF standard does not necessarily match + // the output of the C++ ostream formatting operation. + // REAL = [ SIGN ] DIGIT { DIGIT } "." { DIGIT } [ "E" [ SIGN ] DIGIT { DIGIT } ] . + std::string format_double(const double& d) { + std::ostringstream oss; + oss << d; + const std::string str = oss.str(); + oss.str(""); + std::string::size_type e = str.find('e'); + if (e == std::string::npos) { + e = str.find('E'); + } + const std::string mantissa = str.substr(0,e); + oss << mantissa; + if (mantissa.find('.') == std::string::npos) { + oss << "."; + } + if (e != std::string::npos) { + oss << "E"; + oss << str.substr(e+1); + } + return oss.str(); + } + void serialize_double(const std::vector& i) { + data << "("; + for (std::vector::const_iterator it = i.begin(); it != i.end(); ++it) { + if (it != i.begin()) data << ","; + data << format_double(*it); + } + data << ")"; + } + bool upper; +public: + StringBuilderVisitor(std::ostringstream& stream, bool upper = false) + : data(stream), upper(upper) {} + void operator()(const boost::none_t& i) { data << "$"; } + void operator()(const IfcWriteArgument::Derived& i) { data << "*"; } + void operator()(const int& i) { data << i; } + void operator()(const bool& i) { data << (i ? ".T." : ".F."); } + void operator()(const double& i) { data << format_double(i); } + void operator()(const std::string& i) { + std::string s = i; + if (upper) s = IfcCharacterEncoder(s); + data << s; + } + void operator()(const std::vector& i) { serialize(i); } + void operator()(const std::vector& i) { serialize_double(i); } + void operator()(const std::vector& i) { serialize(i); } + void operator()(const IfcWriteArgument::EnumerationReference& i) { + data << "." << i.enumeration_value << "."; + } + void operator()(const IfcUtil::IfcSchemaEntity& i) { + IfcAbstractEntity* e = i->entity; if ( Ifc2x3::Type::IsSimple(e->type()) ) { - ss << e->toString(upper); + data << e->toString(upper); } else { - if (!e->file) e->file = entity->file; - ss << "#" << e->id(); + data << "#" << e->id(); } } - ss << ")"; - return ss.str(); -} - -IfcWriteEnumerationArgument::IfcWriteEnumerationArgument(IfcAbstractEntity* e, int v, const char* c) : IfcWriteArgument(e) {data=v; enumeration_value = c;} -IfcWriteEnumerationArgument::operator int() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteEnumerationArgument::operator bool() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteEnumerationArgument::operator double() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteEnumerationArgument::operator std::string() const { return std::string(enumeration_value); } -IfcWriteEnumerationArgument::operator std::vector() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteEnumerationArgument::operator std::vector() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteEnumerationArgument::operator std::vector() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteEnumerationArgument::operator IfcUtil::IfcSchemaEntity() const { throw IfcParse::IfcException("Invalid cast"); } -IfcWriteEnumerationArgument::operator IfcEntities() const { throw IfcParse::IfcException("Invalid cast"); } -bool IfcWriteEnumerationArgument::isNull() const { return false; } -ArgumentPtr IfcWriteEnumerationArgument::operator [] (unsigned int i) const { throw IfcParse::IfcException("Invalid cast"); } -std::string IfcWriteEnumerationArgument::toString(bool upper) const { return std::string(".") + enumeration_value + '.';} -unsigned int IfcWriteEnumerationArgument::Size() const { throw IfcParse::IfcException("Invalid cast"); } - -IfcWriteIntegralArgument::IfcWriteIntegralArgument(IfcAbstractEntity* e, int v) : IfcWriteArgument(e) {data=new int(v); type = Argument_INT;} -IfcWriteIntegralArgument::IfcWriteIntegralArgument(IfcAbstractEntity* e, bool v) : IfcWriteArgument(e) {data=new bool(v); type = Argument_BOOL;} -IfcWriteIntegralArgument::IfcWriteIntegralArgument(IfcAbstractEntity* e, double v) : IfcWriteArgument(e) {data=new double(v); type = Argument_DOUBLE;} -IfcWriteIntegralArgument::IfcWriteIntegralArgument(IfcAbstractEntity* e, const std::string& v) : IfcWriteArgument(e) {data=new std::string(v); type = Argument_STRING;} -IfcWriteIntegralArgument::IfcWriteIntegralArgument(IfcAbstractEntity* e, const std::vector v) : IfcWriteArgument(e) {data=new std::vector(v); type = Argument_VECTOR_INT;} -IfcWriteIntegralArgument::IfcWriteIntegralArgument(IfcAbstractEntity* e, const std::vector v) : IfcWriteArgument(e) {data=new std::vector(v); type = Argument_VECTOR_DOUBLE;} -IfcWriteIntegralArgument::IfcWriteIntegralArgument(IfcAbstractEntity* e, const std::vector v) : IfcWriteArgument(e) {data=new std::vector(v); type = Argument_VECTOR_STRING;} -IfcWriteIntegralArgument::IfcWriteIntegralArgument(IfcAbstractEntity* e, IfcUtil::IfcSchemaEntity v) : IfcWriteArgument(e) {data=v; type = Argument_ENTITY;} -IfcWriteIntegralArgument::~IfcWriteIntegralArgument() { - switch ( type ) { - case Argument_INT: - delete (int*) data; - break; - case Argument_BOOL: - delete (bool*) data; - break; - case Argument_DOUBLE: - delete (double*) data; - break; - case Argument_STRING: - delete (std::string*) data; - break; - case Argument_VECTOR_INT: - delete (std::vector*) data; - break; - case Argument_VECTOR_DOUBLE: - delete (std::vector*) data; - break; - case Argument_VECTOR_STRING: - delete (std::vector*) data; - break; - case Argument_ENTITY: - break; + void operator()(const IfcEntities& i) { + data << "("; + for (IfcEntityList::it it = i->begin(); it != i->end(); ++it) { + if (it != i->begin()) data << ","; + (*this)(*it); + } + data << ")"; } + operator std::string() { return data.str(); } +}; + +IfcWriteArgument::operator int() const { return as(); } +IfcWriteArgument::operator bool() const { return as(); } +IfcWriteArgument::operator double() const { return as(); } +IfcWriteArgument::operator std::string() const { return as(); } +IfcWriteArgument::operator std::vector() const { return as >(); } +IfcWriteArgument::operator std::vector() const { return as >(); } +IfcWriteArgument::operator std::vector() const { return as >(); } +IfcWriteArgument::operator IfcUtil::IfcSchemaEntity() const { return as(); } +IfcWriteArgument::operator IfcEntities() const { return as(); } +bool IfcWriteArgument::isNull() const { return argumentType() == argument_type_null; } +ArgumentPtr IfcWriteArgument::operator [] (unsigned int i) const { throw IfcParse::IfcException("Invalid cast"); } +std::string IfcWriteArgument::toString(bool upper) const { + std::ostringstream str; + StringBuilderVisitor v(str, upper); + container.apply_visitor(v); + return v; } -IfcWriteIntegralArgument::operator int() const { if ( type != Argument_INT ) throw IfcParse::IfcException("Invalid cast"); return *(int*)data; } -IfcWriteIntegralArgument::operator bool() const { if ( type != Argument_BOOL ) throw IfcParse::IfcException("Invalid cast"); return *(bool*)data; } -IfcWriteIntegralArgument::operator double() const { if ( type != Argument_DOUBLE ) throw IfcParse::IfcException("Invalid cast"); return *(double*)data; } -IfcWriteIntegralArgument::operator std::string() const { if ( type != Argument_STRING ) throw IfcParse::IfcException("Invalid cast"); return *(std::string*)data; } -IfcWriteIntegralArgument::operator std::vector() const { if ( type != Argument_VECTOR_DOUBLE ) throw IfcParse::IfcException("Invalid cast"); return *(std::vector*)data; } -IfcWriteIntegralArgument::operator std::vector() const { if ( type != Argument_VECTOR_INT ) throw IfcParse::IfcException("Invalid cast"); return *(std::vector*)data; } -IfcWriteIntegralArgument::operator std::vector() const { if ( type != Argument_VECTOR_STRING ) throw IfcParse::IfcException("Invalid cast"); return *(std::vector*)data; } -IfcWriteIntegralArgument::operator IfcUtil::IfcSchemaEntity() const { if ( type != Argument_ENTITY ) throw IfcParse::IfcException("Invalid cast"); return (IfcUtil::IfcSchemaEntity)data; } -IfcWriteIntegralArgument::operator IfcEntities() const { throw IfcParse::IfcException("Invalid cast"); } -bool IfcWriteIntegralArgument::isNull() const { return false; } -unsigned int IfcWriteIntegralArgument::Size() const { - switch ( type ) { - case Argument_VECTOR_INT: - return ((std::vector*) data)->size(); - break; - case Argument_VECTOR_DOUBLE: - return ((std::vector*) data)->size(); - break; - case Argument_VECTOR_STRING: - return ((std::vector*) data)->size(); - break; - default: +unsigned int IfcWriteArgument::Size() const { + SizeVisitor v; + const int size = container.apply_visitor(v); + if (size == -1) { throw IfcParse::IfcException("Invalid cast"); - break; + } else { + return size; } } - -// The REAL token definition from the IFC SPF standard does not necessarily match -// the output of the C++ ostream formatting operation. -// REAL = [ SIGN ] DIGIT { DIGIT } "." { DIGIT } [ "E" [ SIGN ] DIGIT { DIGIT } ] . -std::string format_double(const double& d) { - std::ostringstream oss; - oss << d; - const std::string str = oss.str(); - oss.str(""); - std::string::size_type e = str.find('e'); - if (e == std::string::npos) { - e = str.find('E'); - } - const std::string mantissa = str.substr(0,e); - oss << mantissa; - if (mantissa.find('.') == std::string::npos) { - oss << "."; - } - if (e != std::string::npos) { - oss << "E"; - oss << str.substr(e+1); - } - return oss.str(); -} - -ArgumentPtr IfcWriteIntegralArgument::operator [] (unsigned int i) const { throw IfcParse::IfcException("Invalid cast"); } -std::string IfcWriteIntegralArgument::toString(bool upper) const { - std::ostringstream ss; - switch ( type ) { - case Argument_INT: - ss << *(int*)data; - break; - case Argument_BOOL: - ss << ((*(bool*) data) ? ".T." : ".F."); - break; - case Argument_DOUBLE: - ss << format_double(*(double*) data); - break; - case Argument_STRING: { - std::string d = *(std::string*) data; - if ( upper ) d = IfcCharacterEncoder(d); - ss << d; - break; - } case Argument_VECTOR_INT: - ss << "("; - {const std::vector& v = *(std::vector*) data; - for ( std::vector::const_iterator it = v.begin(); it != v.end(); ++ it ) { - if ( it != v.begin() ) ss << ","; - ss << *it; - }} - ss << ")"; - break; - case Argument_VECTOR_DOUBLE: - ss << "("; - {const std::vector& v = *(std::vector*) data; - for ( std::vector::const_iterator it = v.begin(); it != v.end(); ++ it ) { - if ( it != v.begin() ) ss << ","; - ss << format_double(*it); - }} - ss << ")"; - break; - case Argument_VECTOR_STRING: - ss << "("; - {const std::vector& v = *(std::vector*) data; - for ( std::vector::const_iterator it = v.begin(); it != v.end(); ++ it ) { - if ( it != v.begin() ) ss << ","; - ss << '\'' << *it << '\''; - }} - ss << ")"; - break; - case Argument_ENTITY: - {IfcAbstractEntity* e = ((IfcUtil::IfcSchemaEntity)data)->entity; - if ( Ifc2x3::Type::IsSimple(e->type()) ) { - ss << e->toString(upper); - } else { - if (!e->file) e->file = entity->file; - ss << "#" << e->id(); - }} - break; - default: throw IfcParse::IfcException("Invalid cast"); - } - return ss.str(); +IfcWriteArgument::argument_type IfcWriteArgument::argumentType() const { + return static_cast(container.which()); } IfcEntities IfcSelectHelperEntity::getInverse(Ifc2x3::Type::Enum,int,const std::string &) {throw IfcParse::IfcException("Invalid cast");} @@ -404,23 +313,28 @@ unsigned int IfcSelectHelperEntity::id() { throw IfcParse::IfcException("Invalid bool IfcSelectHelperEntity::isWritable() { throw IfcParse::IfcException("Invalid cast"); } IfcSelectHelper::IfcSelectHelper(const std::string& v, Ifc2x3::Type::Enum t) { - IfcWriteArgument* a = new IfcWriteIntegralArgument(0,v); + IfcWriteArgument* a = new IfcWriteArgument(0); + a->set(v); this->entity = new IfcSelectHelperEntity(t,a); } IfcSelectHelper::IfcSelectHelper(const char* const v, Ifc2x3::Type::Enum t) { - IfcWriteArgument* a = new IfcWriteIntegralArgument(0,std::string(v)); + IfcWriteArgument* a = new IfcWriteArgument(0); + a->set(v); this->entity = new IfcSelectHelperEntity(t,a); } IfcSelectHelper::IfcSelectHelper(int v, Ifc2x3::Type::Enum t) { - IfcWriteArgument* a = new IfcWriteIntegralArgument(0,v); + IfcWriteArgument* a = new IfcWriteArgument(0); + a->set(v); this->entity = new IfcSelectHelperEntity(t,a); } IfcSelectHelper::IfcSelectHelper(double v, Ifc2x3::Type::Enum t) { - IfcWriteArgument* a = new IfcWriteIntegralArgument(0,v); + IfcWriteArgument* a = new IfcWriteArgument(0); + a->set(v); this->entity = new IfcSelectHelperEntity(t,a); } IfcSelectHelper::IfcSelectHelper(bool v, Ifc2x3::Type::Enum t) { - IfcWriteArgument* a = new IfcWriteIntegralArgument(0,v); + IfcWriteArgument* a = new IfcWriteArgument(0); + a->set(v); this->entity = new IfcSelectHelperEntity(t,a); } bool IfcSelectHelper::is(Ifc2x3::Type::Enum t) const { return entity->is(t); } diff --git a/src/ifcparse/IfcWrite.h b/src/ifcparse/IfcWrite.h index 27801abb9a..edc5f68dc3 100644 --- a/src/ifcparse/IfcWrite.h +++ b/src/ifcparse/IfcWrite.h @@ -28,22 +28,92 @@ #ifndef IFCWRITE_H #define IFCWRITE_H +#include +#include + #include "../ifcparse/IfcUtil.h" #include "../ifcparse/IfcParse.h" namespace IfcWrite { - /// A placeholder class for grouping functionality geared towards writing IFC files + /// This class is a writable container for attributes. A fundamental + /// difference with the attribute types counterparts defined in the + /// IfcParse namespace is that this class has a Boost.Variant member + /// for storing its value, whereas the IfcParse classes only contain + /// lazy references to byte offsets in the IFC-SPF file. class IfcWriteArgument : public Argument { - protected: + public: + class EnumerationReference { + public: + int data; + const char* enumeration_value; + EnumerationReference(int data, const char* enumeration_value) + : data(data), enumeration_value(enumeration_value) {} + }; + class Derived {}; + private: IfcAbstractEntity* entity; + boost::variant< + // A null argument, it will always serialize to $ + boost::none_t, + // A derived argument, it will always serialize to * + Derived, + // An integer argument, e.g. 123 + int, + // A boolean argument, it will serialize to either .T. or .F. + bool, + // A floating point argument, e.g. 12.3 + double, + // A character string argument, e.g. 'IfcOpenShell' + std::string, + // A list of integers, e.g. (1,2,3) + std::vector, + // A list of floats, e.g. (12.3,4.) + std::vector, + // A list of strings, e.g. ('Ifc','Open','Shell') + std::vector, + // An enumeration argument, e.g. .USERDEFINED. + // To initialize the argument a string representation + // has to be explicitely passed of the enumeration value + // which is stored internally as an integer. The argument + // itself does not keep track of what schema enumeration + // type is represented. + EnumerationReference, + // An entity instance argument. It will either serialize to + // e.g. #123 or datatype identifier for simple types, e.g. + // IFCREAL(12.3) + IfcUtil::IfcSchemaEntity, + // An entity list argument. It will either serialize to + // e.g. (#1,#2,#3) or datatype identifier for simple types, + // e.g. (IFCREAL(1.2),IFCINTEGER(3.)) + IfcEntities + > container; + public: + enum argument_type { + argument_type_null, + argument_type_derived, + argument_type_int, + argument_type_bool, + argument_type_double, + argument_type_string, + argument_type_vector_int, + argument_type_vector_double, + argument_type_vector_string, + argument_type_enumeration, + argument_type_schema_entity, + argument_type_entities + }; IfcWriteArgument(IfcAbstractEntity* e) : entity(e) {} - }; - - /// A null argument. It will always serialize to $ - class IfcWriteNullArgument : public IfcWriteArgument { - public: - IfcWriteNullArgument(IfcAbstractEntity* e) : IfcWriteArgument(e) {}; + template const T& as() const { + if (const T* val = boost::get(&container)) { + return *val; + } else { + throw IfcParse::IfcException("Invalid cast"); + } + } + template void set(const T& t) { + container = t; + } operator int() const; operator bool() const; operator double() const; @@ -57,107 +127,7 @@ namespace IfcWrite { ArgumentPtr operator [] (unsigned int i) const; std::string toString(bool upper=false) const; unsigned int Size() const; - }; - - /// A derived argument. It will always serialize to * - class IfcWriteDerivedArgument : public IfcWriteArgument { - public: - IfcWriteDerivedArgument(IfcAbstractEntity* e) : IfcWriteArgument(e) {}; - operator int() const; - operator bool() const; - operator double() const; - operator std::string() const; - operator std::vector() const; - operator std::vector() const; - operator std::vector() const; - operator IfcUtil::IfcSchemaEntity() const; - operator IfcEntities() const; - bool isNull() const; - ArgumentPtr operator [] (unsigned int i) const; - std::string toString(bool upper=false) const; - unsigned int Size() const; - }; - - /// An entity list argument. It will serialize to (#1,#2,#3) - /// with possibly a datatype identifier for SELECT types, e.g: - /// (IFCREAL(1.0),IFCINTEGER(1)) - class IfcWriteEntityListArgument : public IfcWriteArgument { - private: - IfcEntities value; - public: - IfcWriteEntityListArgument(IfcAbstractEntity* e, const IfcEntities& v); - operator int() const; - operator bool() const; - operator double() const; - operator std::string() const; - operator std::vector() const; - operator std::vector() const; - operator std::vector() const; - operator IfcUtil::IfcSchemaEntity() const; - operator IfcEntities() const; - bool isNull() const; - unsigned int Size() const; - ArgumentPtr operator [] (unsigned int i) const; - std::string toString(bool upper=false) const; - }; - - /// An enumeration argument. It will serialize to e.g: - /// .USERDEFINED. To initialize the argument a string representation - /// has to be explicitely passed of the enumeration value which - /// is stored internally as an integer. The argument itself - /// does not keep track of what schema enumeration type is - /// represented. - class IfcWriteEnumerationArgument : public IfcWriteArgument { - private: - int data; - const char* enumeration_value; - public: - IfcWriteEnumerationArgument(IfcAbstractEntity* e, int v, const char* c); - operator int() const; - operator bool() const; - operator double() const; - operator std::string() const; - operator std::vector() const; - operator std::vector() const; - operator std::vector() const; - operator IfcUtil::IfcSchemaEntity() const; - operator IfcEntities() const; - bool isNull() const; - ArgumentPtr operator [] (unsigned int i) const; - std::string toString(bool upper=false) const; - unsigned int Size() const; - }; - - /// An argument for all remaining types of arguments. For example: - /// #123 | 1 | 'Value' | (1.0,2.0,3.0). All data is casted to a - /// void pointer. - class IfcWriteIntegralArgument : public IfcWriteArgument { - private: - void* data; - IfcUtil::ArgumentType type; - public: - IfcWriteIntegralArgument(IfcAbstractEntity* e, int v); - IfcWriteIntegralArgument(IfcAbstractEntity* e, bool v); - IfcWriteIntegralArgument(IfcAbstractEntity* e, double v); - IfcWriteIntegralArgument(IfcAbstractEntity* e, const std::string& v); - IfcWriteIntegralArgument(IfcAbstractEntity* e, const std::vector v); - IfcWriteIntegralArgument(IfcAbstractEntity* e, const std::vector v); - IfcWriteIntegralArgument(IfcAbstractEntity* e, const std::vector v); - IfcWriteIntegralArgument(IfcAbstractEntity* e, IfcUtil::IfcSchemaEntity v); - ~IfcWriteIntegralArgument(); - operator int() const; - operator bool() const; - operator double() const; - operator std::string() const; - operator std::vector() const; - operator std::vector() const; - operator std::vector() const; - operator IfcUtil::IfcSchemaEntity() const; - operator IfcEntities() const; - bool isNull() const; - unsigned int Size() const; - ArgumentPtr operator [] (unsigned int i) const; - std::string toString(bool upper=false) const; + argument_type argumentType() const; }; /// An entity to help with passing of SELECT arguments that @@ -199,8 +169,6 @@ namespace IfcWrite { }; /// A helper class for the creation of IFC GlobalIds. - /// At this moment an actual UUID is not generated according to - /// the ISO standard, but merely a sequence of random characters. class IfcGuidHelper { private: std::string data;