mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-22 13:48:03 +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:
|
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);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -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_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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) {}
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user