mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
Use naked pointer for attribute list and derive size from schema type to reduce mem usage
This commit is contained in:
@@ -39,41 +39,27 @@ public:
|
||||
protected:
|
||||
unsigned id_;
|
||||
const IfcParse::declaration* type_;
|
||||
mutable std::vector<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_;
|
||||
mutable Argument** attributes_;
|
||||
unsigned offset_in_file_;
|
||||
|
||||
public:
|
||||
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)
|
||||
: 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;
|
||||
|
||||
IfcEntityInstanceData(const IfcEntityInstanceData& e);
|
||||
|
||||
~IfcEntityInstanceData();
|
||||
virtual ~IfcEntityInstanceData();
|
||||
|
||||
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
|
||||
void setArgument(unsigned int i, Argument* a, IfcUtil::ArgumentType attr_type = IfcUtil::Argument_UNKNOWN);
|
||||
|
||||
unsigned int getArgumentCount() const {
|
||||
if (!initialized_) {
|
||||
load();
|
||||
virtual unsigned int getArgumentCount() const {
|
||||
if (type_ == 0) {
|
||||
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 {
|
||||
@@ -99,7 +89,7 @@ public:
|
||||
unsigned int offset_in_file() const { return offset_in_file_; }
|
||||
|
||||
// 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);
|
||||
};
|
||||
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
std::string createTimestamp() const;
|
||||
|
||||
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, IfcUtil::IfcBaseClass*);
|
||||
|
||||
+128
-77
@@ -604,12 +604,54 @@ EntityArgument::EntityArgument(const Token& t) {
|
||||
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
|
||||
// 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();
|
||||
|
||||
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 ) {
|
||||
if ( TokenFunc::isOperator(next,',') ) {
|
||||
// do nothing
|
||||
@@ -617,59 +659,64 @@ void IfcParse::IfcFile::load(unsigned entity_instance_name, std::vector<Argument
|
||||
break;
|
||||
} else if ( TokenFunc::isOperator(next,'(') ) {
|
||||
ArgumentList* alist = new ArgumentList();
|
||||
load(entity_instance_name, alist->arguments());
|
||||
attributes.push_back(alist);
|
||||
alist->size() = load(entity_instance_name, alist->arguments(), 0);
|
||||
filler.push_back(alist);
|
||||
} else {
|
||||
if ( TokenFunc::isIdentifier(next) ) {
|
||||
if (!parsing_complete_) {
|
||||
register_inverse(entity_instance_name, next);
|
||||
}
|
||||
} if ( TokenFunc::isKeyword(next) ) {
|
||||
// tokens->Next();
|
||||
try {
|
||||
attributes.push_back(new EntityArgument(next));
|
||||
filler.push_back(new EntityArgument(next));
|
||||
} catch ( IfcException& e ) {
|
||||
Logger::Message(Logger::LOG_ERROR, e.what());
|
||||
}
|
||||
} else {
|
||||
attributes.push_back(new TokenArgument(next));
|
||||
filler.push_back(new TokenArgument(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 {
|
||||
if (list.empty()) {
|
||||
if (size_ == 0) {
|
||||
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);
|
||||
}
|
||||
|
||||
void ArgumentList::push(Argument* l) {
|
||||
list.push_back(l);
|
||||
}
|
||||
|
||||
// templated helper function for reading arguments into a list
|
||||
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;
|
||||
return_value.reserve(list.size());
|
||||
std::vector<Argument*>::const_iterator it = list.begin();
|
||||
for (; it != list.end(); ++it) {
|
||||
return_value.push_back(**it);
|
||||
return_value.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
return_value.push_back(*list[i]);
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
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;
|
||||
return_value.reserve(list.size());
|
||||
std::vector<Argument*>::const_iterator it = list.begin();
|
||||
for (; it != list.end(); ++it) {
|
||||
return_value.push_back(**it);
|
||||
return_value.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
return_value.push_back(*list[i]);
|
||||
}
|
||||
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
|
||||
//
|
||||
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 {
|
||||
return read_aggregate_as_vector<int>(list);
|
||||
return read_aggregate_as_vector<int>(list_, size_);
|
||||
}
|
||||
|
||||
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 {
|
||||
return read_aggregate_as_vector<boost::dynamic_bitset<> >(list);
|
||||
return read_aggregate_as_vector<boost::dynamic_bitset<> >(list_, size_);
|
||||
}
|
||||
|
||||
ArgumentList::operator IfcEntityList::ptr() const {
|
||||
IfcEntityList::ptr l ( new IfcEntityList() );
|
||||
std::vector<Argument*>::const_iterator it;
|
||||
for ( it = list.begin(); it != list.end(); ++ it ) {
|
||||
for (size_t i = 0; i < size_; ++i) {
|
||||
// FIXME: account for $
|
||||
IfcUtil::IfcBaseClass* entity = **it;
|
||||
IfcUtil::IfcBaseClass* entity = *list_[i];
|
||||
l->push(entity);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
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 {
|
||||
return read_aggregate_of_aggregate_as_vector2<double>(list);
|
||||
return read_aggregate_of_aggregate_as_vector2<double>(list_, size_);
|
||||
}
|
||||
|
||||
ArgumentList::operator IfcEntityListList::ptr() const {
|
||||
IfcEntityListList::ptr l ( new IfcEntityListList() );
|
||||
std::vector<Argument*>::const_iterator it;
|
||||
for ( it = list.begin(); it != list.end(); ++ it ) {
|
||||
const Argument* arg = *it;
|
||||
for (size_t i = 0; i < size_; ++i) {
|
||||
const Argument* arg = list_[i];
|
||||
const ArgumentList* arg_list;
|
||||
if ((arg_list = dynamic_cast<const ArgumentList*>(arg)) != 0) {
|
||||
IfcEntityList::ptr e = *arg_list;
|
||||
@@ -726,15 +771,16 @@ ArgumentList::operator IfcEntityListList::ptr() const {
|
||||
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 {
|
||||
if ( i >= list.size() ) {
|
||||
if (i >= size_) {
|
||||
throw IfcAttributeOutOfRangeException("Argument index out of range");
|
||||
}
|
||||
return list[i];
|
||||
return list_[i];
|
||||
}
|
||||
|
||||
/*
|
||||
void ArgumentList::set(unsigned int i, Argument* argument) {
|
||||
while (size() < i) {
|
||||
push(new NullArgument());
|
||||
@@ -746,13 +792,16 @@ void ArgumentList::set(unsigned int i, Argument* argument) {
|
||||
list.push_back(argument);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
std::string ArgumentList::toString(bool upper) const {
|
||||
std::stringstream ss;
|
||||
ss << "(";
|
||||
for( std::vector<Argument*>::const_iterator it = list.begin(); it != list.end(); it ++ ) {
|
||||
if ( it != list.begin() ) ss << ",";
|
||||
ss << (*it)->toString(upper);
|
||||
for (size_t i = 0; i < size_; ++i) {
|
||||
if (i != 0) {
|
||||
ss << ",";
|
||||
}
|
||||
ss << list_[i]->toString(upper);
|
||||
}
|
||||
ss << ")";
|
||||
return ss.str();
|
||||
@@ -761,10 +810,10 @@ std::string ArgumentList::toString(bool upper) const {
|
||||
bool ArgumentList::isNull() const { return false; }
|
||||
|
||||
ArgumentList::~ArgumentList() {
|
||||
for( std::vector<Argument*>::iterator it = list.begin(); it != list.end(); it ++ ) {
|
||||
delete (*it);
|
||||
for (size_t i = 0; i < size_; ++i) {
|
||||
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");
|
||||
}
|
||||
tokens->Next();
|
||||
// TODO: reserve based on number of schema attrs
|
||||
load(data.id(), data.attributes());
|
||||
load(data.id(), data.attributes(), data.getArgumentCount());
|
||||
unsigned int old_offset = tokens->stream->Tell();
|
||||
Token semilocon = tokens->Next();
|
||||
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
|
||||
//
|
||||
std::string IfcEntityInstanceData::toString(bool upper) const {
|
||||
if (!initialized_) {
|
||||
if (attributes_ == 0) {
|
||||
load();
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
|
||||
std::string dt = type()->name();
|
||||
if (upper) {
|
||||
boost::to_upper(dt);
|
||||
}
|
||||
std::string dt;
|
||||
if (type_) {
|
||||
dt = type()->name();
|
||||
if (upper) {
|
||||
boost::to_upper(dt);
|
||||
}
|
||||
|
||||
if (type()->as_entity() || id_ != 0) {
|
||||
ss << "#" << id_ << "=";
|
||||
if (type()->as_entity() || id_ != 0) {
|
||||
ss << "#" << id_ << "=";
|
||||
}
|
||||
}
|
||||
|
||||
ss << dt << "(";
|
||||
std::vector<Argument*>::const_iterator it = attributes_.begin();
|
||||
for (; it != attributes_.end(); ++it) {
|
||||
if (it != attributes_.begin()) {
|
||||
|
||||
for (size_t i = 0; i < getArgumentCount(); ++i) {
|
||||
if (i != 0) {
|
||||
ss << ",";
|
||||
}
|
||||
ss << (*it)->toString(upper);
|
||||
if (attributes_[i] == 0) {
|
||||
ss << "$";
|
||||
} else {
|
||||
ss << attributes_[i]->toString(upper);
|
||||
}
|
||||
}
|
||||
ss << ")";
|
||||
|
||||
@@ -914,10 +969,10 @@ std::string IfcEntityInstanceData::toString(bool upper) const {
|
||||
}
|
||||
|
||||
IfcEntityInstanceData::~IfcEntityInstanceData() {
|
||||
std::vector<Argument*>::const_iterator it = attributes_.begin();
|
||||
for (; it != attributes_.end(); ++it) {
|
||||
delete *it;
|
||||
for (size_t i = 0; i < getArgumentCount(); ++i) {
|
||||
delete attributes_[i];
|
||||
}
|
||||
delete[] attributes_;
|
||||
}
|
||||
|
||||
unsigned IfcEntityInstanceData::set_id(boost::optional<unsigned> i) {
|
||||
@@ -936,8 +991,11 @@ IfcEntityList::ptr IfcEntityInstanceData::getInverse(const IfcParse::declaration
|
||||
}
|
||||
|
||||
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);
|
||||
initialized_ = true;
|
||||
}
|
||||
|
||||
IfcEntityInstanceData::IfcEntityInstanceData(const IfcEntityInstanceData& e) {
|
||||
@@ -945,21 +1003,23 @@ IfcEntityInstanceData::IfcEntityInstanceData(const IfcEntityInstanceData& e) {
|
||||
type_ = e.type_;
|
||||
id_ = 0;
|
||||
|
||||
// In order not to have the instance read from file
|
||||
initialized_ = true;
|
||||
|
||||
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) {
|
||||
attributes_[i] = 0;
|
||||
this->setArgument(i, e.getArgument(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Argument* IfcEntityInstanceData::getArgument(unsigned int i) const {
|
||||
if (!initialized_) {
|
||||
if (attributes_ == 0) {
|
||||
load();
|
||||
}
|
||||
if (i < attributes_.size()) {
|
||||
if (i < getArgumentCount()) {
|
||||
return attributes_[i];
|
||||
} else {
|
||||
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) {
|
||||
if (!initialized_) {
|
||||
if (attributes_ == 0) {
|
||||
load();
|
||||
}
|
||||
|
||||
while (attributes_.size() < i) {
|
||||
attributes_.push_back(new NullArgument());
|
||||
}
|
||||
|
||||
if (attr_type == IfcUtil::Argument_UNKNOWN) {
|
||||
attr_type = a->type();
|
||||
}
|
||||
@@ -1178,7 +1234,7 @@ void IfcEntityInstanceData::setArgument(unsigned int i, Argument* a, IfcUtil::Ar
|
||||
return;
|
||||
}
|
||||
|
||||
if (i < attributes_.size()) {
|
||||
if (attributes_[i] != 0) {
|
||||
Argument* current_attribute = attributes_[i];
|
||||
if (this->file) {
|
||||
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);
|
||||
}
|
||||
|
||||
if (i < attributes_.size()) {
|
||||
attributes_[i] = copy;
|
||||
} else {
|
||||
// We have asserted above that the size is at least i
|
||||
attributes_.push_back(copy);
|
||||
}
|
||||
attributes_[i] = copy;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -160,9 +160,11 @@ namespace IfcParse {
|
||||
/// ==========
|
||||
class IFC_PARSE_API ArgumentList: public Argument {
|
||||
private:
|
||||
std::vector<Argument*> list;
|
||||
void push(Argument* l);
|
||||
size_t size_;
|
||||
Argument** list_;
|
||||
|
||||
public:
|
||||
ArgumentList() : size_(0), list_(0) {}
|
||||
~ArgumentList();
|
||||
|
||||
void read(IfcSpfLexer* t, std::vector<unsigned int>& ids);
|
||||
@@ -183,11 +185,11 @@ namespace IfcParse {
|
||||
unsigned int size() const;
|
||||
|
||||
Argument* operator [] (unsigned int i) const;
|
||||
void set(unsigned int i, Argument*);
|
||||
|
||||
std::string toString(bool upper=false) const;
|
||||
|
||||
std::vector<Argument*>& arguments() { return list; }
|
||||
Argument**& arguments() { return list_; }
|
||||
size_t& size() { return size_; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -35,14 +35,17 @@ static const char * const DATA = "DATA";
|
||||
|
||||
using namespace IfcParse;
|
||||
|
||||
HeaderEntity::HeaderEntity(const char * const datatype, IfcFile* file)
|
||||
: IfcEntityInstanceData(0, file), _datatype(datatype)
|
||||
HeaderEntity::HeaderEntity(const char * const datatype, size_t size, IfcFile* file)
|
||||
: IfcEntityInstanceData(file, size), size_(size), _datatype(datatype)
|
||||
{
|
||||
if (file) {
|
||||
offset_in_file_ = file->stream->Tell();
|
||||
load();
|
||||
} 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) {}
|
||||
FileName::FileName(IfcFile* file) : HeaderEntity(FILE_NAME, file) {}
|
||||
FileSchema::FileSchema(IfcFile* file) : HeaderEntity(FILE_SCHEMA, file) {}
|
||||
FileDescription::FileDescription(IfcFile* file) : HeaderEntity(FILE_DESCRIPTION, 2, file) {}
|
||||
FileName::FileName(IfcFile* file) : HeaderEntity(FILE_NAME, 7, file) {}
|
||||
FileSchema::FileSchema(IfcFile* file) : HeaderEntity(FILE_SCHEMA, 1, file) {}
|
||||
@@ -30,11 +30,12 @@ namespace IfcParse {
|
||||
class IFC_PARSE_API HeaderEntity : public IfcEntityInstanceData {
|
||||
private:
|
||||
const char * const _datatype;
|
||||
size_t size_;
|
||||
|
||||
HeaderEntity(const HeaderEntity&); //N/A
|
||||
HeaderEntity& operator =(const HeaderEntity&); //N/A
|
||||
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) {
|
||||
IfcWrite::IfcWriteArgument* argument = new IfcWrite::IfcWriteArgument;
|
||||
@@ -49,19 +50,13 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
virtual unsigned int getArgumentCount() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
std::string toString(bool upper=false) const {
|
||||
std::stringstream ss;
|
||||
// Unfortunately this is duplicated from IfcEntityInstanceData::toString()
|
||||
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 << ")";
|
||||
ss << _datatype << IfcEntityInstanceData::toString(upper);
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user