Use naked pointer for attribute list and derive size from schema type to reduce mem usage

This commit is contained in:
Thomas Krijnen
2018-01-29 12:11:50 +01:00
parent a3b7a25866
commit af93f2a64d
6 changed files with 167 additions and 126 deletions
+17 -27
View File
@@ -39,41 +39,27 @@ public:
protected: protected:
unsigned id_; unsigned id_;
const IfcParse::declaration* type_; const IfcParse::declaration* type_;
mutable std::vector<Argument*> attributes_; mutable Argument** attributes_;
// To reduce memory footprint, these two could potentially be combined,
// e.g. initialized_ <-> offset_in_file_ == 0, but it would imply that
// instances cannot be located at the beginning of the file. Officially
// there should be a header anyways.
mutable bool initialized_;
unsigned offset_in_file_; unsigned offset_in_file_;
public: public:
IfcEntityInstanceData(const IfcParse::declaration* type, IfcParse::IfcFile* file_, unsigned id = 0, unsigned offset_in_file = 0) IfcEntityInstanceData(const IfcParse::declaration* type, IfcParse::IfcFile* file_, unsigned id = 0, unsigned offset_in_file = 0)
: file(file_), id_(id), type_(type), initialized_(false), offset_in_file_(offset_in_file) : file(file_), id_(id), type_(type), attributes_(0), offset_in_file_(offset_in_file)
{}
IfcEntityInstanceData(IfcParse::IfcFile* file_, size_t size)
: file(file_), id_(0), type_(0), attributes_(new Argument*[size]), offset_in_file_(0)
{} {}
IfcEntityInstanceData(const IfcParse::declaration* type) IfcEntityInstanceData(const IfcParse::declaration* type)
: file(0), id_(0), type_(type), initialized_(true) : file(0), id_(0), type_(type), attributes_(0)
{} {}
/*
IfcEntityInstanceData(IfcParse::IfcFile* file = 0, unsigned id = 0, IfcSchema::Type::Enum type = IfcSchema::Type::UNDEFINED, unsigned offset_in_file = 0, size_t n)
: file_(file), id_(0), type_(type), initialized_(false)
{
attributes_.reserve(n);
}
IfcEntityInstanceData(IfcParse::IfcFile* file = 0, unsigned id = 0, IfcSchema::Type::Enum type = IfcSchema::Type::UNDEFINED, const std::vector<Argument*>& attributes)
: file_(file), id_(0), type_(type), attributes_(attributes), initialized_(true)
{}
*/
void load() const; void load() const;
IfcEntityInstanceData(const IfcEntityInstanceData& e); IfcEntityInstanceData(const IfcEntityInstanceData& e);
~IfcEntityInstanceData(); virtual ~IfcEntityInstanceData();
boost::shared_ptr<IfcEntityList> getInverse(const IfcParse::declaration* type, int attribute_index); boost::shared_ptr<IfcEntityList> getInverse(const IfcParse::declaration* type, int attribute_index);
@@ -82,11 +68,15 @@ public:
// NB: This makes a copy of the argument // NB: This makes a copy of the argument
void setArgument(unsigned int i, Argument* a, IfcUtil::ArgumentType attr_type = IfcUtil::Argument_UNKNOWN); void setArgument(unsigned int i, Argument* a, IfcUtil::ArgumentType attr_type = IfcUtil::Argument_UNKNOWN);
unsigned int getArgumentCount() const { virtual unsigned int getArgumentCount() const {
if (!initialized_) { if (type_ == 0) {
load(); return 0;
}
if (type_->as_entity()) {
return type_->as_entity()->attribute_count();
} else {
return 1;
} }
return (unsigned int)attributes_.size();
} }
const IfcParse::declaration* type() const { const IfcParse::declaration* type() const {
@@ -99,7 +89,7 @@ public:
unsigned int offset_in_file() const { return offset_in_file_; } unsigned int offset_in_file() const { return offset_in_file_; }
// NB: const ommitted for lazy loading // NB: const ommitted for lazy loading
std::vector<Argument*>& attributes() const { return attributes_; } Argument**& attributes() const { return attributes_; }
unsigned set_id(boost::optional<unsigned> i = boost::none); unsigned set_id(boost::optional<unsigned> i = boost::none);
}; };
+1 -1
View File
@@ -181,7 +181,7 @@ public:
std::string createTimestamp() const; std::string createTimestamp() const;
void load(const IfcEntityInstanceData&); void load(const IfcEntityInstanceData&);
void load(unsigned entity_instance_name, std::vector<Argument*>& attributes); size_t load(unsigned entity_instance_name, Argument**& attributes, size_t num_attributes);
void register_inverse(unsigned, Token); void register_inverse(unsigned, Token);
void register_inverse(unsigned, IfcUtil::IfcBaseClass*); void register_inverse(unsigned, IfcUtil::IfcBaseClass*);
+128 -77
View File
@@ -604,12 +604,54 @@ EntityArgument::EntityArgument(const Token& t) {
entity = file->schema()->instantiate(data); entity = file->schema()->instantiate(data);
} }
namespace {
template <typename T>
class vector_or_array {
std::vector<T>* vector_;
T* array_;
size_t size_, index_;
public:
vector_or_array(std::vector<T>* vector)
: vector_(vector)
, array_(0)
, size_(0)
, index_(0)
{}
vector_or_array(Argument** arr, size_t size)
: vector_(0)
, array_(arr)
, size_(size)
, index_(0)
{}
void push_back(const T& t) {
if (array_ && index_ < size_) {
array_[index_++] = t;
} else if (vector_) {
vector_->push_back(t);
}
}
};
}
// //
// Reads the arguments from a list of token // Reads the arguments from a list of token
// Aditionally, registers the ids (i.e. #[\d]+) in the inverse map // Aditionally, registers the ids (i.e. #[\d]+) in the inverse map
// //
void IfcParse::IfcFile::load(unsigned entity_instance_name, std::vector<Argument*>& attributes) { size_t IfcParse::IfcFile::load(unsigned entity_instance_name, Argument**& attributes, size_t num_attributes) {
Token next = tokens->Next(); Token next = tokens->Next();
std::vector<Argument*>* vector = 0;
vector_or_array<Argument*> filler(attributes, num_attributes);
if (attributes == 0) {
vector = new std::vector<Argument*>();
filler = vector_or_array<Argument*>(vector);
}
size_t return_value = num_attributes;
while( next.startPos || next.lexer ) { while( next.startPos || next.lexer ) {
if ( TokenFunc::isOperator(next,',') ) { if ( TokenFunc::isOperator(next,',') ) {
// do nothing // do nothing
@@ -617,59 +659,64 @@ void IfcParse::IfcFile::load(unsigned entity_instance_name, std::vector<Argument
break; break;
} else if ( TokenFunc::isOperator(next,'(') ) { } else if ( TokenFunc::isOperator(next,'(') ) {
ArgumentList* alist = new ArgumentList(); ArgumentList* alist = new ArgumentList();
load(entity_instance_name, alist->arguments()); alist->size() = load(entity_instance_name, alist->arguments(), 0);
attributes.push_back(alist); filler.push_back(alist);
} else { } else {
if ( TokenFunc::isIdentifier(next) ) { if ( TokenFunc::isIdentifier(next) ) {
if (!parsing_complete_) { if (!parsing_complete_) {
register_inverse(entity_instance_name, next); register_inverse(entity_instance_name, next);
} }
} if ( TokenFunc::isKeyword(next) ) { } if ( TokenFunc::isKeyword(next) ) {
// tokens->Next();
try { try {
attributes.push_back(new EntityArgument(next)); filler.push_back(new EntityArgument(next));
} catch ( IfcException& e ) { } catch ( IfcException& e ) {
Logger::Message(Logger::LOG_ERROR, e.what()); Logger::Message(Logger::LOG_ERROR, e.what());
} }
} else { } else {
attributes.push_back(new TokenArgument(next)); filler.push_back(new TokenArgument(next));
} }
} }
next = tokens->Next(); next = tokens->Next();
} }
if (vector) {
attributes = new Argument*[vector->size()];
return_value = vector->size();
for (size_t i = 0; i < vector->size(); ++i) {
attributes[i] = vector->at(i);
}
}
delete vector;
return return_value;
} }
IfcUtil::ArgumentType ArgumentList::type() const { IfcUtil::ArgumentType ArgumentList::type() const {
if (list.empty()) { if (size_ == 0) {
return IfcUtil::Argument_EMPTY_AGGREGATE; return IfcUtil::Argument_EMPTY_AGGREGATE;
} }
const IfcUtil::ArgumentType elem_type = list[0]->type(); const IfcUtil::ArgumentType elem_type = list_[0]->type();
return IfcUtil::make_aggregate(elem_type); return IfcUtil::make_aggregate(elem_type);
} }
void ArgumentList::push(Argument* l) {
list.push_back(l);
}
// templated helper function for reading arguments into a list // templated helper function for reading arguments into a list
template<typename T> template<typename T>
std::vector<T> read_aggregate_as_vector(const std::vector<Argument*>& list) { std::vector<T> read_aggregate_as_vector(Argument** list, size_t size) {
std::vector<T> return_value; std::vector<T> return_value;
return_value.reserve(list.size()); return_value.reserve(size);
std::vector<Argument*>::const_iterator it = list.begin(); for (size_t i = 0; i < size; ++i) {
for (; it != list.end(); ++it) { return_value.push_back(*list[i]);
return_value.push_back(**it);
} }
return return_value; return return_value;
} }
template<typename T> template<typename T>
std::vector< std::vector<T> > read_aggregate_of_aggregate_as_vector2(const std::vector<Argument*>& list) { std::vector< std::vector<T> > read_aggregate_of_aggregate_as_vector2(Argument** list, size_t size) {
std::vector< std::vector<T> > return_value; std::vector< std::vector<T> > return_value;
return_value.reserve(list.size()); return_value.reserve(size);
std::vector<Argument*>::const_iterator it = list.begin(); for (size_t i = 0; i < size; ++i) {
for (; it != list.end(); ++it) { return_value.push_back(*list[i]);
return_value.push_back(**it);
} }
return return_value; return return_value;
} }
@@ -678,45 +725,43 @@ std::vector< std::vector<T> > read_aggregate_of_aggregate_as_vector2(const std::
// Functions for casting the ArgumentList to other types // Functions for casting the ArgumentList to other types
// //
ArgumentList::operator std::vector<double>() const { ArgumentList::operator std::vector<double>() const {
return read_aggregate_as_vector<double>(list); return read_aggregate_as_vector<double>(list_, size_);
} }
ArgumentList::operator std::vector<int>() const { ArgumentList::operator std::vector<int>() const {
return read_aggregate_as_vector<int>(list); return read_aggregate_as_vector<int>(list_, size_);
} }
ArgumentList::operator std::vector<std::string>() const { ArgumentList::operator std::vector<std::string>() const {
return read_aggregate_as_vector<std::string>(list); return read_aggregate_as_vector<std::string>(list_, size_);
} }
ArgumentList::operator std::vector<boost::dynamic_bitset<> >() const { ArgumentList::operator std::vector<boost::dynamic_bitset<> >() const {
return read_aggregate_as_vector<boost::dynamic_bitset<> >(list); return read_aggregate_as_vector<boost::dynamic_bitset<> >(list_, size_);
} }
ArgumentList::operator IfcEntityList::ptr() const { ArgumentList::operator IfcEntityList::ptr() const {
IfcEntityList::ptr l ( new IfcEntityList() ); IfcEntityList::ptr l ( new IfcEntityList() );
std::vector<Argument*>::const_iterator it; for (size_t i = 0; i < size_; ++i) {
for ( it = list.begin(); it != list.end(); ++ it ) {
// FIXME: account for $ // FIXME: account for $
IfcUtil::IfcBaseClass* entity = **it; IfcUtil::IfcBaseClass* entity = *list_[i];
l->push(entity); l->push(entity);
} }
return l; return l;
} }
ArgumentList::operator std::vector< std::vector<int> >() const { ArgumentList::operator std::vector< std::vector<int> >() const {
return read_aggregate_of_aggregate_as_vector2<int>(list); return read_aggregate_of_aggregate_as_vector2<int>(list_, size_);
} }
ArgumentList::operator std::vector< std::vector<double> >() const { ArgumentList::operator std::vector< std::vector<double> >() const {
return read_aggregate_of_aggregate_as_vector2<double>(list); return read_aggregate_of_aggregate_as_vector2<double>(list_, size_);
} }
ArgumentList::operator IfcEntityListList::ptr() const { ArgumentList::operator IfcEntityListList::ptr() const {
IfcEntityListList::ptr l ( new IfcEntityListList() ); IfcEntityListList::ptr l ( new IfcEntityListList() );
std::vector<Argument*>::const_iterator it; for (size_t i = 0; i < size_; ++i) {
for ( it = list.begin(); it != list.end(); ++ it ) { const Argument* arg = list_[i];
const Argument* arg = *it;
const ArgumentList* arg_list; const ArgumentList* arg_list;
if ((arg_list = dynamic_cast<const ArgumentList*>(arg)) != 0) { if ((arg_list = dynamic_cast<const ArgumentList*>(arg)) != 0) {
IfcEntityList::ptr e = *arg_list; IfcEntityList::ptr e = *arg_list;
@@ -726,15 +771,16 @@ ArgumentList::operator IfcEntityListList::ptr() const {
return l; return l;
} }
unsigned int ArgumentList::size() const { return (unsigned int) list.size(); } unsigned int ArgumentList::size() const { return (unsigned int)size_; }
Argument* ArgumentList::operator [] (unsigned int i) const { Argument* ArgumentList::operator [] (unsigned int i) const {
if ( i >= list.size() ) { if (i >= size_) {
throw IfcAttributeOutOfRangeException("Argument index out of range"); throw IfcAttributeOutOfRangeException("Argument index out of range");
} }
return list[i]; return list_[i];
} }
/*
void ArgumentList::set(unsigned int i, Argument* argument) { void ArgumentList::set(unsigned int i, Argument* argument) {
while (size() < i) { while (size() < i) {
push(new NullArgument()); push(new NullArgument());
@@ -746,13 +792,16 @@ void ArgumentList::set(unsigned int i, Argument* argument) {
list.push_back(argument); list.push_back(argument);
} }
} }
*/
std::string ArgumentList::toString(bool upper) const { std::string ArgumentList::toString(bool upper) const {
std::stringstream ss; std::stringstream ss;
ss << "("; ss << "(";
for( std::vector<Argument*>::const_iterator it = list.begin(); it != list.end(); it ++ ) { for (size_t i = 0; i < size_; ++i) {
if ( it != list.begin() ) ss << ","; if (i != 0) {
ss << (*it)->toString(upper); ss << ",";
}
ss << list_[i]->toString(upper);
} }
ss << ")"; ss << ")";
return ss.str(); return ss.str();
@@ -761,10 +810,10 @@ std::string ArgumentList::toString(bool upper) const {
bool ArgumentList::isNull() const { return false; } bool ArgumentList::isNull() const { return false; }
ArgumentList::~ArgumentList() { ArgumentList::~ArgumentList() {
for( std::vector<Argument*>::iterator it = list.begin(); it != list.end(); it ++ ) { for (size_t i = 0; i < size_; ++i) {
delete (*it); delete list_[i];
} }
list.clear(); delete[] list_;
} }
@@ -850,8 +899,7 @@ void IfcParse::IfcFile::load(const IfcEntityInstanceData& data) {
if (!TokenFunc::isKeyword(datatype)) throw IfcException("Unexpected token while parsing entity instance"); if (!TokenFunc::isKeyword(datatype)) throw IfcException("Unexpected token while parsing entity instance");
} }
tokens->Next(); tokens->Next();
// TODO: reserve based on number of schema attrs load(data.id(), data.attributes(), data.getArgumentCount());
load(data.id(), data.attributes());
unsigned int old_offset = tokens->stream->Tell(); unsigned int old_offset = tokens->stream->Tell();
Token semilocon = tokens->Next(); Token semilocon = tokens->Next();
if (!TokenFunc::isOperator(semilocon, ';')) { if (!TokenFunc::isOperator(semilocon, ';')) {
@@ -884,29 +932,36 @@ void IfcParse::IfcFile::unregister_inverse(unsigned id_from, IfcUtil::IfcBaseCla
// Note that this initializes the entity if it is not initialized // Note that this initializes the entity if it is not initialized
// //
std::string IfcEntityInstanceData::toString(bool upper) const { std::string IfcEntityInstanceData::toString(bool upper) const {
if (!initialized_) { if (attributes_ == 0) {
load(); load();
} }
std::stringstream ss; std::stringstream ss;
ss.imbue(std::locale::classic()); ss.imbue(std::locale::classic());
std::string dt = type()->name(); std::string dt;
if (upper) { if (type_) {
boost::to_upper(dt); dt = type()->name();
} if (upper) {
boost::to_upper(dt);
}
if (type()->as_entity() || id_ != 0) { if (type()->as_entity() || id_ != 0) {
ss << "#" << id_ << "="; ss << "#" << id_ << "=";
}
} }
ss << dt << "("; ss << dt << "(";
std::vector<Argument*>::const_iterator it = attributes_.begin();
for (; it != attributes_.end(); ++it) { for (size_t i = 0; i < getArgumentCount(); ++i) {
if (it != attributes_.begin()) { if (i != 0) {
ss << ","; ss << ",";
} }
ss << (*it)->toString(upper); if (attributes_[i] == 0) {
ss << "$";
} else {
ss << attributes_[i]->toString(upper);
}
} }
ss << ")"; ss << ")";
@@ -914,10 +969,10 @@ std::string IfcEntityInstanceData::toString(bool upper) const {
} }
IfcEntityInstanceData::~IfcEntityInstanceData() { IfcEntityInstanceData::~IfcEntityInstanceData() {
std::vector<Argument*>::const_iterator it = attributes_.begin(); for (size_t i = 0; i < getArgumentCount(); ++i) {
for (; it != attributes_.end(); ++it) { delete attributes_[i];
delete *it;
} }
delete[] attributes_;
} }
unsigned IfcEntityInstanceData::set_id(boost::optional<unsigned> i) { unsigned IfcEntityInstanceData::set_id(boost::optional<unsigned> i) {
@@ -936,8 +991,11 @@ IfcEntityList::ptr IfcEntityInstanceData::getInverse(const IfcParse::declaration
} }
void IfcEntityInstanceData::load() const { void IfcEntityInstanceData::load() const {
// type_ is 0 for header entities which have their size predetermined in code
if (type_ != 0) {
attributes_ = new Argument*[getArgumentCount()];
}
file->load(*this); file->load(*this);
initialized_ = true;
} }
IfcEntityInstanceData::IfcEntityInstanceData(const IfcEntityInstanceData& e) { IfcEntityInstanceData::IfcEntityInstanceData(const IfcEntityInstanceData& e) {
@@ -945,21 +1003,23 @@ IfcEntityInstanceData::IfcEntityInstanceData(const IfcEntityInstanceData& e) {
type_ = e.type_; type_ = e.type_;
id_ = 0; id_ = 0;
// In order not to have the instance read from file
initialized_ = true;
const unsigned int count = e.getArgumentCount(); const unsigned int count = e.getArgumentCount();
// In order not to have the instance read from file
attributes_ = new Argument*[count];
for (unsigned int i = 0; i < count; ++i) { for (unsigned int i = 0; i < count; ++i) {
attributes_[i] = 0;
this->setArgument(i, e.getArgument(i)); this->setArgument(i, e.getArgument(i));
} }
} }
Argument* IfcEntityInstanceData::getArgument(unsigned int i) const { Argument* IfcEntityInstanceData::getArgument(unsigned int i) const {
if (!initialized_) { if (attributes_ == 0) {
load(); load();
} }
if (i < attributes_.size()) { if (i < getArgumentCount()) {
return attributes_[i]; return attributes_[i];
} else { } else {
throw IfcParse::IfcException("Attribute index out of range"); throw IfcParse::IfcException("Attribute index out of range");
@@ -1058,14 +1118,10 @@ public:
}; };
void IfcEntityInstanceData::setArgument(unsigned int i, Argument* a, IfcUtil::ArgumentType attr_type) { void IfcEntityInstanceData::setArgument(unsigned int i, Argument* a, IfcUtil::ArgumentType attr_type) {
if (!initialized_) { if (attributes_ == 0) {
load(); load();
} }
while (attributes_.size() < i) {
attributes_.push_back(new NullArgument());
}
if (attr_type == IfcUtil::Argument_UNKNOWN) { if (attr_type == IfcUtil::Argument_UNKNOWN) {
attr_type = a->type(); attr_type = a->type();
} }
@@ -1178,7 +1234,7 @@ void IfcEntityInstanceData::setArgument(unsigned int i, Argument* a, IfcUtil::Ar
return; return;
} }
if (i < attributes_.size()) { if (attributes_[i] != 0) {
Argument* current_attribute = attributes_[i]; Argument* current_attribute = attributes_[i];
if (this->file) { if (this->file) {
unregister_inverse_visitor visitor(*this->file, *this); unregister_inverse_visitor visitor(*this->file, *this);
@@ -1192,12 +1248,7 @@ void IfcEntityInstanceData::setArgument(unsigned int i, Argument* a, IfcUtil::Ar
apply_individual_instance_visitor(copy).apply(visitor); apply_individual_instance_visitor(copy).apply(visitor);
} }
if (i < attributes_.size()) { attributes_[i] = copy;
attributes_[i] = copy;
} else {
// We have asserted above that the size is at least i
attributes_.push_back(copy);
}
} }
// //
+6 -4
View File
@@ -160,9 +160,11 @@ namespace IfcParse {
/// ========== /// ==========
class IFC_PARSE_API ArgumentList: public Argument { class IFC_PARSE_API ArgumentList: public Argument {
private: private:
std::vector<Argument*> list; size_t size_;
void push(Argument* l); Argument** list_;
public: public:
ArgumentList() : size_(0), list_(0) {}
~ArgumentList(); ~ArgumentList();
void read(IfcSpfLexer* t, std::vector<unsigned int>& ids); void read(IfcSpfLexer* t, std::vector<unsigned int>& ids);
@@ -183,11 +185,11 @@ namespace IfcParse {
unsigned int size() const; unsigned int size() const;
Argument* operator [] (unsigned int i) const; Argument* operator [] (unsigned int i) const;
void set(unsigned int i, Argument*);
std::string toString(bool upper=false) const; std::string toString(bool upper=false) const;
std::vector<Argument*>& arguments() { return list; } Argument**& arguments() { return list_; }
size_t& size() { return size_; }
}; };
+9 -6
View File
@@ -35,14 +35,17 @@ static const char * const DATA = "DATA";
using namespace IfcParse; using namespace IfcParse;
HeaderEntity::HeaderEntity(const char * const datatype, IfcFile* file) HeaderEntity::HeaderEntity(const char * const datatype, size_t size, IfcFile* file)
: IfcEntityInstanceData(0, file), _datatype(datatype) : IfcEntityInstanceData(file, size), size_(size), _datatype(datatype)
{ {
if (file) { if (file) {
offset_in_file_ = file->stream->Tell(); offset_in_file_ = file->stream->Tell();
load(); load();
} else { } else {
initialized_ = true; // attributes_ = new Argument*[size];
for (size_t i = 0; i < size; ++i) {
attributes_[i] = 0;
}
} }
} }
@@ -168,6 +171,6 @@ FileSchema& IfcSpfHeader::file_schema() {
} }
} }
FileDescription::FileDescription(IfcFile* file) : HeaderEntity(FILE_DESCRIPTION, file) {} FileDescription::FileDescription(IfcFile* file) : HeaderEntity(FILE_DESCRIPTION, 2, file) {}
FileName::FileName(IfcFile* file) : HeaderEntity(FILE_NAME, file) {} FileName::FileName(IfcFile* file) : HeaderEntity(FILE_NAME, 7, file) {}
FileSchema::FileSchema(IfcFile* file) : HeaderEntity(FILE_SCHEMA, file) {} FileSchema::FileSchema(IfcFile* file) : HeaderEntity(FILE_SCHEMA, 1, file) {}
+6 -11
View File
@@ -30,11 +30,12 @@ namespace IfcParse {
class IFC_PARSE_API HeaderEntity : public IfcEntityInstanceData { class IFC_PARSE_API HeaderEntity : public IfcEntityInstanceData {
private: private:
const char * const _datatype; const char * const _datatype;
size_t size_;
HeaderEntity(const HeaderEntity&); //N/A HeaderEntity(const HeaderEntity&); //N/A
HeaderEntity& operator =(const HeaderEntity&); //N/A HeaderEntity& operator =(const HeaderEntity&); //N/A
protected: protected:
HeaderEntity(const char * const datatype, IfcParse::IfcFile* file); HeaderEntity(const char * const datatype, size_t size, IfcParse::IfcFile* file);
void setValue(unsigned int i, const std::string& s) { void setValue(unsigned int i, const std::string& s) {
IfcWrite::IfcWriteArgument* argument = new IfcWrite::IfcWriteArgument; IfcWrite::IfcWriteArgument* argument = new IfcWrite::IfcWriteArgument;
@@ -49,19 +50,13 @@ protected:
} }
public: public:
virtual unsigned int getArgumentCount() const {
return size_;
}
std::string toString(bool upper=false) const { std::string toString(bool upper=false) const {
std::stringstream ss; std::stringstream ss;
// Unfortunately this is duplicated from IfcEntityInstanceData::toString() ss << _datatype << IfcEntityInstanceData::toString(upper);
ss << _datatype << "(";
std::vector<Argument*>::const_iterator it = attributes_.begin();
for (; it != attributes_.end(); ++it) {
if (it != attributes_.begin()) {
ss << ",";
}
ss << (*it)->toString(upper);
}
ss << ")";
return ss.str(); return ss.str();
} }
}; };