Files
IfcOpenShell/src/ifcparse/IfcWrite.cpp
T

364 lines
12 KiB
C++
Raw Normal View History

/********************************************************************************
2012-07-19 13:07:55 +00:00
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#include <iomanip>
#include <locale>
2014-06-11 10:24:11 +00:00
#include "../ifcparse/IfcParse.h"
#include "../ifcparse/IfcWrite.h"
#include "../ifcparse/IfcWritableEntity.h"
#include "../ifcparse/IfcCharacterDecoder.h"
#include "../ifcparse/IfcFile.h"
2012-07-19 13:07:55 +00:00
using namespace IfcWrite;
IfcWritableEntity::IfcWritableEntity(IfcSchema::Type::Enum t) {
2012-07-19 13:07:55 +00:00
_type = t;
_id = 0;
file = 0;
2012-07-19 13:07:55 +00:00
}
IfcWritableEntity::~IfcWritableEntity() {
delete _id;
}
2012-07-19 13:07:55 +00:00
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()));
}
}
2012-07-19 13:07:55 +00:00
}
IfcWritableEntity::IfcWritableEntity(IfcAbstractEntity* e)
{
file = e->file;
2012-07-19 13:07:55 +00:00
_type = e->type();
_id = new int(e->id());
const unsigned int count = e->getArgumentCount();
for ( unsigned int i = 0; i < count; ++ i ) {
args[i] = e->getArgument(i);
writemask[i] = false;
}
}
2015-01-10 22:13:52 +00:00
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");
2012-07-19 13:07:55 +00:00
}
}
std::string IfcWritableEntity::datatype() const { return IfcSchema::Type::ToString(_type); }
Argument* IfcWritableEntity::getArgument (unsigned int i) { if ( i >= getArgumentCount() ) throw IfcParse::IfcException("Argument not set"); return args[i]; }unsigned int IfcWritableEntity::getArgumentCount() const {return 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 {
2012-07-19 13:07:55 +00:00
std::stringstream ss;
2015-02-17 20:23:21 +00:00
ss.imbue(std::locale::classic());
2012-07-19 13:07:55 +00:00
std::string dt = datatype();
2015-01-25 10:50:12 +00:00
if (upper) {
2012-07-19 13:07:55 +00:00
for (std::string::iterator p = dt.begin(); p != dt.end(); ++p ) *p = toupper(*p);
}
2015-01-25 10:50:12 +00:00
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) {
2012-07-19 13:07:55 +00:00
if ( it != args.begin() ) ss << ",";
const Argument* a = it->second;
2012-07-19 13:07:55 +00:00
ss << it->second->toString(upper);
}
ss << ")";
2015-01-25 10:50:12 +00:00
2012-07-19 13:07:55 +00:00
return ss.str();
}
unsigned int IfcWritableEntity::id() {
if ( !_id ) {
_id = new int(file->FreshId());
}
return *_id;
}
IfcWritableEntity* IfcWritableEntity::isWritable() { return this; }
2012-07-19 13:07:55 +00:00
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(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) {
_setArgument(i, IfcWriteArgument::Derived());
}
2012-07-19 13:07:55 +00:00
void IfcWritableEntity::setArgument(int i,int v) {
_setArgument(i, v);
}
void IfcWritableEntity::setArgument(int i,bool v) {
_setArgument(i, v);
2012-07-19 13:07:55 +00:00
}
void IfcWritableEntity::setArgument(int i,int v, const char* c){
_setArgument(i, IfcWriteArgument::EnumerationReference(v, c));
2012-07-19 13:07:55 +00:00
}
void IfcWritableEntity::setArgument(int i,const std::string& v){
_setArgument(i, v);
2012-07-19 13:07:55 +00:00
}
void IfcWritableEntity::setArgument(int i,double v){
_setArgument(i, v);
2012-07-19 13:07:55 +00:00
}
void IfcWritableEntity::setArgument(int i,IfcUtil::IfcBaseClass* v){
if ( v ) {
_setArgument(i, v);
} else {
_setArgument(i, boost::none);
}
2012-07-19 13:07:55 +00:00
}
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);
}
2012-07-19 13:07:55 +00:00
}
void IfcWritableEntity::setArgument(int i,const std::vector<double>& v){
_setArgument(i, v);
2012-07-19 13:07:55 +00:00
}
void IfcWritableEntity::setArgument(int i,const std::vector<std::string>& v){
_setArgument(i, v);
2012-07-19 13:07:55 +00:00
}
void IfcWritableEntity::setArgument(int i,const std::vector<int>& v){
_setArgument(i, v);
2012-07-19 13:07:55 +00:00
}
class SizeVisitor : public boost::static_visitor<int> {
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<int>& i) const { return i.size(); }
int operator()(const std::vector<double>& i) const { return i.size(); }
int operator()(const std::vector<std::string>& i) const { return i.size(); }
int operator()(const IfcWriteArgument::EnumerationReference& i) const { return -1; }
int operator()(const IfcUtil::IfcBaseClass* const& i) const { return -1; }
2015-01-10 22:13:52 +00:00
int operator()(const IfcEntityList::ptr& i) const { return i->size(); }
int operator()(const IfcEntityListList::ptr& i) const { return i->size(); }
};
class StringBuilderVisitor : public boost::static_visitor<void> {
private:
std::ostringstream& data;
template <typename T> void serialize(const std::vector<T>& i) {
data << "(";
for (typename std::vector<T>::const_iterator it = i.begin(); it != i.end(); ++it) {
if (it != i.begin()) data << ",";
data << *it;
2012-07-19 13:07:55 +00:00
}
data << ")";
2012-07-19 13:07:55 +00:00
}
// 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.imbue(std::locale::classic());
oss << std::setprecision(15) << 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();
2012-07-19 13:07:55 +00:00
}
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;
2015-01-25 10:50:12 +00:00
if (upper) {
data << static_cast<std::string>(IfcCharacterEncoder(s));
} else {
data << '\'' << s << '\'';
}
}
2015-01-16 16:26:40 +00:00
void operator()(const std::vector<int>& i);
void operator()(const std::vector<double>& i);
void operator()(const std::vector<std::string>& i);
void operator()(const IfcWriteArgument::EnumerationReference& i) {
data << "." << i.enumeration_value << ".";
}
void operator()(const IfcUtil::IfcBaseClass* const& i) {
IfcAbstractEntity* e = i->entity;
if ( IfcSchema::Type::IsSimple(e->type()) ) {
data << e->toString(upper);
2012-07-19 13:07:55 +00:00
} else {
data << "#" << e->id();
}
2012-07-19 13:07:55 +00:00
}
void operator()(const IfcEntityList::ptr& i) {
data << "(";
for (IfcEntityList::it it = i->begin(); it != i->end(); ++it) {
if (it != i->begin()) data << ",";
(*this)(*it);
}
data << ")";
}
void operator()(const IfcEntityListList::ptr& i) {
data << "(";
for (IfcEntityListList::outer_it outer_it = i->begin(); outer_it != i->end(); ++outer_it) {
data << "(";
if (outer_it != i->begin()) data << ",";
for (IfcEntityListList::inner_it inner_it = outer_it->begin(); inner_it != outer_it->end(); ++inner_it) {
if (inner_it != outer_it->begin()) data << ",";
(*this)(*inner_it);
}
data << ")";
}
data << ")";
}
operator std::string() { return data.str(); }
};
2015-01-16 16:26:40 +00:00
template <>
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;
}
}
data << ")";
}
template <>
void StringBuilderVisitor::serialize(const std::vector<double>& i) {
data << "(";
for (std::vector<double>::const_iterator it = i.begin(); it != i.end(); ++it) {
if (it != i.begin()) data << ",";
data << format_double(*it);
}
data << ")";
}
void StringBuilderVisitor::operator()(const std::vector<int>& i) { serialize(i); }
void StringBuilderVisitor::operator()(const std::vector<double>& i) { serialize(i); }
void StringBuilderVisitor::operator()(const std::vector<std::string>& i) { serialize(i); }
IfcWriteArgument::operator int() const { return as<int>(); }
IfcWriteArgument::operator bool() const { return as<bool>(); }
IfcWriteArgument::operator double() const { return as<double>(); }
IfcWriteArgument::operator std::string() const { return as<std::string>(); }
IfcWriteArgument::operator std::vector<double>() const { return as<std::vector<double> >(); }
IfcWriteArgument::operator std::vector<int>() const { return as<std::vector<int> >(); }
IfcWriteArgument::operator std::vector<std::string>() const { return as<std::vector<std::string > >(); }
IfcWriteArgument::operator IfcUtil::IfcBaseClass*() const { return as<IfcUtil::IfcBaseClass*>(); }
IfcWriteArgument::operator IfcEntityList::ptr() const { return as<IfcEntityList::ptr>(); }
IfcWriteArgument::operator IfcEntityListList::ptr() const { throw; }
bool IfcWriteArgument::isNull() const { return type() == IfcUtil::Argument_NULL; }
Argument* IfcWriteArgument::operator [] (unsigned int i) const { throw IfcParse::IfcException("Invalid cast"); }
std::string IfcWriteArgument::toString(bool upper) const {
std::ostringstream str;
2015-02-17 20:23:21 +00:00
str.imbue(std::locale::classic());
StringBuilderVisitor v(str, upper);
container.apply_visitor(v);
return v;
}
2015-01-10 22:13:52 +00:00
unsigned int IfcWriteArgument::size() const {
SizeVisitor v;
const int size = container.apply_visitor(v);
if (size == -1) {
throw IfcParse::IfcException("Invalid cast");
} else {
return size;
}
}
2012-07-19 13:07:55 +00:00
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);
}
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);
}