diff --git a/src/ifcparse/Argument.h b/src/ifcparse/Argument.h index e67a5b9bd3..0b60c9b312 100644 --- a/src/ifcparse/Argument.h +++ b/src/ifcparse/Argument.h @@ -20,59 +20,58 @@ #ifndef ARGUMENT_H #define ARGUMENT_H -#include -#include -#include -#include -#include - -#include "ifc_parse_api.h" #include "ArgumentType.h" +#include "ifc_parse_api.h" -#include +#include #include #include +#include +#include +#include +#include +#include class aggregate_of_instance; class aggregate_of_aggregate_of_instance; namespace IfcUtil { - class IfcBaseClass; +class IfcBaseClass; - IFC_PARSE_API const char* ArgumentTypeToString(ArgumentType argument_type); +IFC_PARSE_API const char* ArgumentTypeToString(ArgumentType argument_type); - /// Returns false when the string `s` contains character outside of {'0', '1'} - IFC_PARSE_API bool valid_binary_string(const std::string& s); -} +/// Returns false when the string `s` contains character outside of {'0', '1'} +IFC_PARSE_API bool valid_binary_string(const std::string& s); +} // namespace IfcUtil class IFC_PARSE_API Argument { -public: - virtual operator int() const; - virtual operator bool() const; - virtual operator boost::logic::tribool() const; - virtual operator double() const; - virtual operator std::string() const; - virtual operator boost::dynamic_bitset<>() const; - virtual operator IfcUtil::IfcBaseClass*() const; + public: + virtual operator int() const; + virtual operator bool() const; + virtual operator boost::logic::tribool() const; + virtual operator double() const; + virtual operator std::string() const; + virtual operator boost::dynamic_bitset<>() const; + virtual operator IfcUtil::IfcBaseClass*() const; - virtual operator std::vector() const; - virtual operator std::vector() const; - virtual operator std::vector() const; - virtual operator std::vector >() const; - virtual operator boost::shared_ptr() const; + virtual operator std::vector() const; + virtual operator std::vector() const; + virtual operator std::vector() const; + virtual operator std::vector>() const; + virtual operator boost::shared_ptr() const; - virtual operator std::vector< std::vector >() const; - virtual operator std::vector< std::vector >() const; - virtual operator boost::shared_ptr() const; + virtual operator std::vector>() const; + virtual operator std::vector>() const; + virtual operator boost::shared_ptr() const; - virtual bool isNull() const = 0; - virtual unsigned int size() const = 0; + virtual bool isNull() const = 0; + virtual unsigned int size() const = 0; - virtual IfcUtil::ArgumentType type() const = 0; - virtual Argument* operator [] (unsigned int i) const = 0; - virtual std::string toString(bool upper=false) const = 0; - - virtual ~Argument() {}; + virtual IfcUtil::ArgumentType type() const = 0; + virtual Argument* operator[](unsigned int i) const = 0; + virtual std::string toString(bool upper = false) const = 0; + + virtual ~Argument(){}; }; #endif diff --git a/src/ifcparse/ArgumentType.h b/src/ifcparse/ArgumentType.h index 48d9063c9f..51a5bf65b8 100644 --- a/src/ifcparse/ArgumentType.h +++ b/src/ifcparse/ArgumentType.h @@ -17,44 +17,43 @@ * * ********************************************************************************/ -#include "../ifcparse/IfcSchema.h" - -#include "ifc_parse_api.h" - #ifndef ARGUMENTTYPE_H #define ARGUMENTTYPE_H +#include "ifc_parse_api.h" +#include "IfcSchema.h" + namespace IfcUtil { - enum ArgumentType { - Argument_NULL, - Argument_DERIVED, - Argument_INT, - Argument_BOOL, - Argument_LOGICAL, - Argument_DOUBLE, - Argument_STRING, - Argument_BINARY, - Argument_ENUMERATION, - Argument_ENTITY_INSTANCE, +enum ArgumentType { + Argument_NULL, + Argument_DERIVED, + Argument_INT, + Argument_BOOL, + Argument_LOGICAL, + Argument_DOUBLE, + Argument_STRING, + Argument_BINARY, + Argument_ENUMERATION, + Argument_ENTITY_INSTANCE, - Argument_EMPTY_AGGREGATE, - Argument_AGGREGATE_OF_INT, - Argument_AGGREGATE_OF_DOUBLE, - Argument_AGGREGATE_OF_STRING, - Argument_AGGREGATE_OF_BINARY, - Argument_AGGREGATE_OF_ENTITY_INSTANCE, + Argument_EMPTY_AGGREGATE, + Argument_AGGREGATE_OF_INT, + Argument_AGGREGATE_OF_DOUBLE, + Argument_AGGREGATE_OF_STRING, + Argument_AGGREGATE_OF_BINARY, + Argument_AGGREGATE_OF_ENTITY_INSTANCE, - Argument_AGGREGATE_OF_EMPTY_AGGREGATE, - Argument_AGGREGATE_OF_AGGREGATE_OF_INT, - Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE, - Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE, + Argument_AGGREGATE_OF_EMPTY_AGGREGATE, + Argument_AGGREGATE_OF_AGGREGATE_OF_INT, + Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE, + Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE, - Argument_UNKNOWN - }; + Argument_UNKNOWN +}; - IFC_PARSE_API ArgumentType from_parameter_type(const IfcParse::parameter_type*); - IFC_PARSE_API ArgumentType make_aggregate(ArgumentType elem_type); -} +IFC_PARSE_API ArgumentType from_parameter_type(const IfcParse::parameter_type*); +IFC_PARSE_API ArgumentType make_aggregate(ArgumentType elem_type); +} // namespace IfcUtil #endif diff --git a/src/ifcparse/IfcBaseClass.h b/src/ifcparse/IfcBaseClass.h index 34d8c11bfa..1a796db5bb 100644 --- a/src/ifcparse/IfcBaseClass.h +++ b/src/ifcparse/IfcBaseClass.h @@ -20,151 +20,152 @@ #ifndef IFCBASECLASS_H #define IFCBASECLASS_H +#include "Argument.h" #include "ifc_parse_api.h" - -#include "../ifcparse/IfcEntityInstanceData.h" -#include "../ifcparse/IfcSchema.h" -#include "../ifcparse/utils.h" - -#include +#include "IfcEntityInstanceData.h" +#include "IfcSchema.h" +#include "utils.h" #include +#include class Argument; class aggregate_of_instance; namespace IfcUtil { - class IFC_PARSE_API IfcBaseInterface { - protected: - static bool is_null(const IfcBaseInterface* not_this) { - return !not_this; - } +class IFC_PARSE_API IfcBaseInterface { + protected: + static bool is_null(const IfcBaseInterface* not_this) { + return !not_this; + } - template - std::enable_if_t::value && !std::is_same::value && !std::is_same::value> raise_error_on_concrete_class() const { - throw IfcParse::IfcException("Instance of type " + this->declaration().name() + " cannot be cast to " + T::Class().name()); - } + template + std::enable_if_t::value && !std::is_same::value && !std::is_same::value> raise_error_on_concrete_class() const { + throw IfcParse::IfcException("Instance of type " + this->declaration().name() + " cannot be cast to " + T::Class().name()); + } - template - std::enable_if_t::value || std::is_same::value || std::is_same::value> raise_error_on_concrete_class() const { - throw IfcParse::IfcException("Instance of type " + this->declaration().name() + " cannot be cast to base class"); - } + template + std::enable_if_t::value || std::is_same::value || std::is_same::value> raise_error_on_concrete_class() const { + throw IfcParse::IfcException("Instance of type " + this->declaration().name() + " cannot be cast to base class"); + } - public: - virtual const IfcEntityInstanceData& data() const = 0; - virtual IfcEntityInstanceData& data() = 0; - virtual const IfcParse::declaration& declaration() const = 0; + public: + virtual const IfcEntityInstanceData& data() const = 0; + virtual IfcEntityInstanceData& data() = 0; + virtual const IfcParse::declaration& declaration() const = 0; - template - T* as(bool do_throw = false) { - // @todo: do not allow this to be null in the first place - if (is_null(this)) { - return static_cast(0); - } - auto t = dynamic_cast(this); - if (do_throw && !t) { - raise_error_on_concrete_class(); - } - return t; - } + template + T* as(bool do_throw = false) { + // @todo: do not allow this to be null in the first place + if (is_null(this)) { + return static_cast(0); + } + auto t = dynamic_cast(this); + if (do_throw && !t) { + raise_error_on_concrete_class(); + } + return t; + } - template - const T* as(bool do_throw = false) const { - if (is_null(this)) { - return static_cast(0); - } - auto t = dynamic_cast(this); - if (do_throw && !t) { - raise_error_on_concrete_class(); - } - return t; - } - }; + template + const T* as(bool do_throw = false) const { + if (is_null(this)) { + return static_cast(0); + } + auto t = dynamic_cast(this); + if (do_throw && !t) { + raise_error_on_concrete_class(); + } + return t; + } +}; - class IFC_PARSE_API IfcBaseClass : public virtual IfcBaseInterface { - private: - uint32_t identity_; - static std::atomic_uint32_t counter_; +class IFC_PARSE_API IfcBaseClass : public virtual IfcBaseInterface { + private: + uint32_t identity_; + static std::atomic_uint32_t counter_; - protected: - IfcEntityInstanceData* data_; + protected: + IfcEntityInstanceData* data_; - static bool is_null(const IfcBaseClass* not_this) { - return !not_this; - } - public: - IfcBaseClass() : identity_(counter_++), data_(0) {} - IfcBaseClass(IfcEntityInstanceData* d) : identity_(counter_++), data_(d) {} - virtual ~IfcBaseClass() { delete data_; } - - const IfcEntityInstanceData& data() const { return *data_; } - IfcEntityInstanceData& data() { return *data_; } - void data(IfcEntityInstanceData* d); - - virtual const IfcParse::declaration& declaration() const = 0; + static bool is_null(const IfcBaseClass* not_this) { + return !not_this; + } - uint32_t identity() const { return identity_; } - }; + public: + IfcBaseClass() : identity_(counter_++), + data_(0) {} + IfcBaseClass(IfcEntityInstanceData* d) : identity_(counter_++), + data_(d) {} + virtual ~IfcBaseClass() { delete data_; } - class IFC_PARSE_API IfcLateBoundEntity : public IfcBaseClass { - private: - const IfcParse::declaration* decl_; + const IfcEntityInstanceData& data() const { return *data_; } + IfcEntityInstanceData& data() { return *data_; } + void data(IfcEntityInstanceData* d); - public: - IfcLateBoundEntity(const IfcParse::declaration* decl, IfcEntityInstanceData* data) : IfcBaseClass(data), decl_(decl) {} + virtual const IfcParse::declaration& declaration() const = 0; - virtual const IfcParse::declaration& declaration() const { - return *decl_; - } - }; + uint32_t identity() const { return identity_; } +}; - class IFC_PARSE_API IfcBaseEntity : public IfcBaseClass { - public: - IfcBaseEntity() : IfcBaseClass() {} - IfcBaseEntity(IfcEntityInstanceData* d) : IfcBaseClass(d) {} +class IFC_PARSE_API IfcLateBoundEntity : public IfcBaseClass { + private: + const IfcParse::declaration* decl_; - virtual const IfcParse::entity& declaration() const = 0; + public: + IfcLateBoundEntity(const IfcParse::declaration* decl, IfcEntityInstanceData* data) : IfcBaseClass(data), + decl_(decl) {} - Argument* get(const std::string& name) const; - - template - T get_value(const std::string& name) const; - - template - T get_value(const std::string& name, const T& default_value) const; + virtual const IfcParse::declaration& declaration() const { + return *decl_; + } +}; - boost::shared_ptr get_inverse(const std::string& a) const; - }; +class IFC_PARSE_API IfcBaseEntity : public IfcBaseClass { + public: + IfcBaseEntity() : IfcBaseClass() {} + IfcBaseEntity(IfcEntityInstanceData* d) : IfcBaseClass(d) {} - // TODO: Investigate whether these should be template classes instead - class IFC_PARSE_API IfcBaseType : public IfcBaseClass { - public: - IfcBaseType() : IfcBaseClass() {} - IfcBaseType(IfcEntityInstanceData* d) : IfcBaseClass(d) {} + virtual const IfcParse::entity& declaration() const = 0; - virtual const IfcParse::declaration& declaration() const = 0; - }; + Argument* get(const std::string& name) const; -} + template + T get_value(const std::string& name) const; -#include "../ifcparse/Argument.h" + template + T get_value(const std::string& name, const T& default_value) const; + + boost::shared_ptr get_inverse(const std::string& a) const; +}; + +// TODO: Investigate whether these should be template classes instead +class IFC_PARSE_API IfcBaseType : public IfcBaseClass { + public: + IfcBaseType() : IfcBaseClass() {} + IfcBaseType(IfcEntityInstanceData* d) : IfcBaseClass(d) {} + + virtual const IfcParse::declaration& declaration() const = 0; +}; + +} // namespace IfcUtil namespace IfcUtil { - template - T IfcBaseEntity::get_value(const std::string& name) const { - auto attr = get(name); - return (T)*attr; - } - - template - T IfcBaseEntity::get_value(const std::string& name, const T& default_value) const { - auto attr = get(name); - if (attr->isNull()) { - return default_value; - } - return (T)*attr; - } +template +T IfcBaseEntity::get_value(const std::string& name) const { + auto attr = get(name); + return (T)*attr; } +template +T IfcBaseEntity::get_value(const std::string& name, const T& default_value) const { + auto attr = get(name); + if (attr->isNull()) { + return default_value; + } + return (T)*attr; +} +} // namespace IfcUtil + #endif diff --git a/src/ifcparse/IfcCharacterDecoder.cpp b/src/ifcparse/IfcCharacterDecoder.cpp index 4ccd2ee465..ec9ad2db4c 100644 --- a/src/ifcparse/IfcCharacterDecoder.cpp +++ b/src/ifcparse/IfcCharacterDecoder.cpp @@ -16,337 +16,352 @@ * along with this program. If not, see . * * * ********************************************************************************/ - - /******************************************************************************** + +/******************************************************************************** * * * Implementation of character decoding as described in ISO 10303-21 table 2 and * * table 4 * * * ********************************************************************************/ -#include -#include -#include +#include "IfcCharacterDecoder.h" + +#include "IfcException.h" +#include "IfcSpfStream.h" + #include +#include +#include +#include -#include "../ifcparse/IfcCharacterDecoder.h" -#include "../ifcparse/IfcException.h" -#include "../ifcparse/IfcSpfStream.h" - -#define FIRST_SOLIDUS (1 << 1) -#define PAGE (1 << 2) -#define ALPHABET (1 << 3) -#define SECOND_SOLIDUS (1 << 4) -#define ALPHABET_DEFINITION (1 << 5) -#define APOSTROPHE (1 << 6) -#define ARBITRARY (1 << 7) -#define EXTENDED2 (1 << 8) -#define EXTENDED4 (1 << 9) -#define HEX(N) (1 << (9+N)) -#define THIRD_SOLIDUS (1 << 18) -#define ENDEXTENDED_X (1 << 19) -#define ENDEXTENDED_0 (1 << 20) -#define IGNORED_DIRECTIVE (1 << 22) -#define ENCOUNTERED_HEX (1 << 23) +#define FIRST_SOLIDUS (1 << 1) +#define PAGE (1 << 2) +#define ALPHABET (1 << 3) +#define SECOND_SOLIDUS (1 << 4) +#define ALPHABET_DEFINITION (1 << 5) +#define APOSTROPHE (1 << 6) +#define ARBITRARY (1 << 7) +#define EXTENDED2 (1 << 8) +#define EXTENDED4 (1 << 9) +#define HEX(N) (1 << (9 + N)) +#define THIRD_SOLIDUS (1 << 18) +#define ENDEXTENDED_X (1 << 19) +#define ENDEXTENDED_0 (1 << 20) +#define IGNORED_DIRECTIVE (1 << 22) +#define ENCOUNTERED_HEX (1 << 23) // FIXME: These probably need to be less forgiving in terms of wrongly defined sequences -#define EXPECTS_ALPHABET(S) (S & FIRST_SOLIDUS) -#define EXPECTS_PAGE(S) (S & FIRST_SOLIDUS) -#define EXPECTS_ARBITRARY(S) (S & FIRST_SOLIDUS) -#define EXPECTS_N_OR_F(S) (S & FIRST_SOLIDUS && !(S & ARBITRARY) ) -#define EXPECTS_ARBITRARY2(S) (S & ARBITRARY && !(S & SECOND_SOLIDUS)) -#define EXPECTS_ALPHABET_DEFINITION(S) (S & FIRST_SOLIDUS && S & ALPHABET) -#define EXPECTS_SOLIDUS(S) (S & ALPHABET_DEFINITION || S & PAGE || S & ARBITRARY || S & EXTENDED2 || S & EXTENDED4 || S & ENDEXTENDED_0 || S & IGNORED_DIRECTIVE || (S & EXTENDED4 && S & HEX(8)) || (S & EXTENDED2 && S & HEX(4))) -#define EXPECTS_CHARACTER(S) (S & PAGE && S & SECOND_SOLIDUS) -#define EXPECTS_HEX(S) (S & HEX(1) || S & HEX(3) || S & HEX(5) || S & HEX(6) || S & HEX(7) || (S & ARBITRARY && S & SECOND_SOLIDUS) || (S & EXTENDED2 && S & HEX(2)) || (S & EXTENDED4 && S & HEX(4)) ) -#define EXPECTS_ENDEXTENDED_X(S) (S & THIRD_SOLIDUS) -#define EXPECTS_ENDEXTENDED_0(S) (S & ENDEXTENDED_X) +#define EXPECTS_ALPHABET(S) (S & FIRST_SOLIDUS) +#define EXPECTS_PAGE(S) (S & FIRST_SOLIDUS) +#define EXPECTS_ARBITRARY(S) (S & FIRST_SOLIDUS) +#define EXPECTS_N_OR_F(S) (S & FIRST_SOLIDUS && !(S & ARBITRARY)) +#define EXPECTS_ARBITRARY2(S) (S & ARBITRARY && !(S & SECOND_SOLIDUS)) +#define EXPECTS_ALPHABET_DEFINITION(S) (S & FIRST_SOLIDUS && S & ALPHABET) +#define EXPECTS_SOLIDUS(S) (S & ALPHABET_DEFINITION || S & PAGE || S & ARBITRARY || S & EXTENDED2 || S & EXTENDED4 || S & ENDEXTENDED_0 || S & IGNORED_DIRECTIVE || (S & EXTENDED4 && S & HEX(8)) || (S & EXTENDED2 && S & HEX(4))) +#define EXPECTS_CHARACTER(S) (S & PAGE && S & SECOND_SOLIDUS) +#define EXPECTS_HEX(S) (S & HEX(1) || S & HEX(3) || S & HEX(5) || S & HEX(6) || S & HEX(7) || (S & ARBITRARY && S & SECOND_SOLIDUS) || (S & EXTENDED2 && S & HEX(2)) || (S & EXTENDED4 && S & HEX(4))) +#define EXPECTS_ENDEXTENDED_X(S) (S & THIRD_SOLIDUS) +#define EXPECTS_ENDEXTENDED_0(S) (S & ENDEXTENDED_X) -#define IS_VALID_ALPHABET_DEFINITION(C) (C >= 0x41 && C <= 0x49) -#define IS_HEXADECIMAL(C) ((C >= 0x30 && C <= 0x39 ) || (C >= 0x41 && C <= 0x46 )) -#define HEX_TO_INT(C) ((C >= 0x30 && C <= 0x39 ) ? C - 0x30 : (C+10) - 0x41) -#define CLEAR_HEX(C) (C &= ~(HEX(1)|HEX(2)|HEX(3)|HEX(4)|HEX(5)|HEX(6)|HEX(7)|HEX(8))) +#define IS_VALID_ALPHABET_DEFINITION(C) (C >= 0x41 && C <= 0x49) +#define IS_HEXADECIMAL(C) ((C >= 0x30 && C <= 0x39) || (C >= 0x41 && C <= 0x46)) +#define HEX_TO_INT(C) ((C >= 0x30 && C <= 0x39) ? C - 0x30 : (C + 10) - 0x41) +#define CLEAR_HEX(C) (C &= ~(HEX(1) | HEX(2) | HEX(3) | HEX(4) | HEX(5) | HEX(6) | HEX(7) | HEX(8))) using namespace IfcParse; using namespace IfcWrite; IfcCharacterDecoder::IfcCharacterDecoder(IfcParse::IfcSpfStream* f) { - file = f; - codepage_ = 0; + file = f; + codepage_ = 0; } IfcCharacterDecoder::~IfcCharacterDecoder() { } namespace { - static unsigned int reference_helper = 0; +static unsigned int reference_helper = 0; - class pure_impure_helper { - private: - bool pure_; - IfcParse::IfcSpfStream* stream_; - unsigned int& pointer_; - std::wstring builder_; +class pure_impure_helper { + private: + bool pure_; + IfcParse::IfcSpfStream* stream_; + unsigned int& pointer_; + std::wstring builder_; - char peek() { - if (pure_) { - return stream_->peek_at(pointer_); - } else { - return stream_->Peek(); - } - } + char peek() { + if (pure_) { + return stream_->peek_at(pointer_); + } else { + return stream_->Peek(); + } + } - unsigned int tell() { - if (pure_) { - return pointer_; - } else { - return stream_->Tell(); - } - } + unsigned int tell() { + if (pure_) { + return pointer_; + } else { + return stream_->Tell(); + } + } - void increment() { - if (pure_) { - stream_->increment_at(pointer_); - } else { - stream_->Inc(); - } - } + void increment() { + if (pure_) { + stream_->increment_at(pointer_); + } else { + stream_->Inc(); + } + } - public: - pure_impure_helper(IfcParse::IfcSpfStream* stream) - : pure_(false), stream_(stream), pointer_(reference_helper) - {} + public: + pure_impure_helper(IfcParse::IfcSpfStream* stream) + : pure_(false), + stream_(stream), + pointer_(reference_helper) {} - pure_impure_helper(IfcParse::IfcSpfStream* stream, unsigned int& pointer) - : pure_(true), stream_(stream), pointer_(pointer) - {} + pure_impure_helper(IfcParse::IfcSpfStream* stream, unsigned int& pointer) + : pure_(true), + stream_(stream), + pointer_(pointer) {} - std::string get(IfcParse::IfcCharacterDecoder::ConversionMode mode, char substitution_character) { - unsigned int parse_state = 0; - builder_.clear(); - builder_.push_back('\''); - char current_char; - int codepage = 1; - unsigned int hex = 0; - unsigned int hex_count = 0; + std::string get(IfcParse::IfcCharacterDecoder::ConversionMode mode, char substitution_character) { + unsigned int parse_state = 0; + builder_.clear(); + builder_.push_back('\''); + char current_char; + int codepage = 1; + unsigned int hex = 0; + unsigned int hex_count = 0; - while ((current_char = peek()) != 0) { - if (EXPECTS_CHARACTER(parse_state)) { - builder_.push_back(IfcUtil::convert_codepage(codepage, current_char + 0x80)); - parse_state = 0; - } else if (current_char == '\'' && !parse_state) { - parse_state = APOSTROPHE; - } else if (current_char == '\\' && !parse_state) { - parse_state = FIRST_SOLIDUS; - } else if (current_char == '\\' && EXPECTS_SOLIDUS(parse_state)) { - if (parse_state & ALPHABET_DEFINITION || - parse_state & IGNORED_DIRECTIVE || - parse_state & ENDEXTENDED_0) parse_state = hex = hex_count = 0; - else if (parse_state & ENCOUNTERED_HEX) { - parse_state += THIRD_SOLIDUS; - parse_state -= ENCOUNTERED_HEX; - } else parse_state += SECOND_SOLIDUS; - } else if (current_char == 'X' && EXPECTS_ENDEXTENDED_X(parse_state)) { - parse_state += ENDEXTENDED_X; - } else if (current_char == '0' && EXPECTS_ENDEXTENDED_0(parse_state)) { - parse_state += ENDEXTENDED_0; - } else if (current_char == 'X' && EXPECTS_ARBITRARY(parse_state)) { - parse_state += ARBITRARY; - } else if (current_char == '2' && EXPECTS_ARBITRARY2(parse_state)) { - parse_state += EXTENDED2; - } else if (current_char == '4' && EXPECTS_ARBITRARY2(parse_state)) { - parse_state += EXTENDED2 + EXTENDED4; - } else if (current_char == 'P' && EXPECTS_ALPHABET(parse_state)) { - parse_state += ALPHABET; - } else if ((current_char == 'N' || current_char == 'F') && EXPECTS_N_OR_F(parse_state)) { - parse_state += IGNORED_DIRECTIVE; - } else if (IS_VALID_ALPHABET_DEFINITION(current_char) && EXPECTS_ALPHABET_DEFINITION(parse_state)) { - codepage = current_char - 0x40; - parse_state += ALPHABET_DEFINITION; - } else if (current_char == 'S' && EXPECTS_PAGE(parse_state)) { - parse_state += PAGE; - } else if (IS_HEXADECIMAL(current_char) && EXPECTS_HEX(parse_state)) { - hex <<= 4; - parse_state += HEX((++hex_count)); - hex += HEX_TO_INT(current_char); - if ((hex_count == 2 && !(parse_state & EXTENDED2)) || - (hex_count == 4 && !(parse_state & EXTENDED4)) || - (hex_count == 8)) { - builder_.push_back(hex); - if (hex_count == 2) parse_state = 0; - else { - CLEAR_HEX(parse_state); - parse_state |= ENCOUNTERED_HEX; - } - hex = hex_count = 0; - } - } else if (parse_state && !( - (current_char == '\\' && parse_state == FIRST_SOLIDUS) || - (current_char == '\'' && parse_state == APOSTROPHE) - )) { - if (parse_state == APOSTROPHE && current_char != '\'') break; - throw IfcInvalidTokenException(tell(), current_char); - } else { - parse_state = hex = hex_count = 0; - builder_.push_back(current_char); - } - increment(); - } - builder_.push_back('\''); + while ((current_char = peek()) != 0) { + if (EXPECTS_CHARACTER(parse_state)) { + builder_.push_back(IfcUtil::convert_codepage(codepage, current_char + 0x80)); + parse_state = 0; + } else if (current_char == '\'' && !parse_state) { + parse_state = APOSTROPHE; + } else if (current_char == '\\' && !parse_state) { + parse_state = FIRST_SOLIDUS; + } else if (current_char == '\\' && EXPECTS_SOLIDUS(parse_state)) { + if (parse_state & ALPHABET_DEFINITION || + parse_state & IGNORED_DIRECTIVE || + parse_state & ENDEXTENDED_0) { + parse_state = hex = hex_count = 0; + } else if (parse_state & ENCOUNTERED_HEX) { + parse_state += THIRD_SOLIDUS; + parse_state -= ENCOUNTERED_HEX; + } else { + parse_state += SECOND_SOLIDUS; + } + } else if (current_char == 'X' && EXPECTS_ENDEXTENDED_X(parse_state)) { + parse_state += ENDEXTENDED_X; + } else if (current_char == '0' && EXPECTS_ENDEXTENDED_0(parse_state)) { + parse_state += ENDEXTENDED_0; + } else if (current_char == 'X' && EXPECTS_ARBITRARY(parse_state)) { + parse_state += ARBITRARY; + } else if (current_char == '2' && EXPECTS_ARBITRARY2(parse_state)) { + parse_state += EXTENDED2; + } else if (current_char == '4' && EXPECTS_ARBITRARY2(parse_state)) { + parse_state += EXTENDED2 + EXTENDED4; + } else if (current_char == 'P' && EXPECTS_ALPHABET(parse_state)) { + parse_state += ALPHABET; + } else if ((current_char == 'N' || current_char == 'F') && EXPECTS_N_OR_F(parse_state)) { + parse_state += IGNORED_DIRECTIVE; + } else if (IS_VALID_ALPHABET_DEFINITION(current_char) && EXPECTS_ALPHABET_DEFINITION(parse_state)) { + codepage = current_char - 0x40; + parse_state += ALPHABET_DEFINITION; + } else if (current_char == 'S' && EXPECTS_PAGE(parse_state)) { + parse_state += PAGE; + } else if (IS_HEXADECIMAL(current_char) && EXPECTS_HEX(parse_state)) { + hex <<= 4; + parse_state += HEX((++hex_count)); + hex += HEX_TO_INT(current_char); + if ((hex_count == 2 && !(parse_state & EXTENDED2)) || + (hex_count == 4 && !(parse_state & EXTENDED4)) || + (hex_count == 8)) { + builder_.push_back(hex); + if (hex_count == 2) { + parse_state = 0; + } else { + CLEAR_HEX(parse_state); + parse_state |= ENCOUNTERED_HEX; + } + hex = hex_count = 0; + } + } else if (parse_state && !( + (current_char == '\\' && parse_state == FIRST_SOLIDUS) || + (current_char == '\'' && parse_state == APOSTROPHE))) { + if (parse_state == APOSTROPHE && current_char != '\'') { + break; + } + throw IfcInvalidTokenException(tell(), current_char); + } else { + parse_state = hex = hex_count = 0; + builder_.push_back(current_char); + } + increment(); + } + builder_.push_back('\''); - if (mode == IfcParse::IfcCharacterDecoder::UTF8) { - if (builder_.empty()) { - static std::string empty; - return empty; - } else { - auto it = std::max_element(builder_.begin(), builder_.end()); - if (*it <= 0x7e) { - std::string r(builder_.begin(), builder_.end()); - return r; - } else { - return IfcUtil::convert_utf8(builder_); - } - } - } else if (mode == IfcParse::IfcCharacterDecoder::SUBSTITUTE) { - std::string r; - r.reserve(builder_.size()); - std::transform(builder_.begin(), builder_.end(), std::back_inserter(r), [&substitution_character](wchar_t c) { - if (c >= 0x20 && c <= 0x7e) { - return (char)c; - } else { - return substitution_character; - } - }); - return r; - } else if (mode == IfcParse::IfcCharacterDecoder::ESCAPE) { - std::stringstream str; - str << std::hex << std::setw(4) << std::setfill('0'); - std::for_each(builder_.begin(), builder_.end(), [&str](wchar_t c) { - if (c >= 0x20 && c <= 0x7e) { - str.put((char)c); - } else { - str << "\\u" << c; - } - }); - return str.str(); - } else { - throw IfcParse::IfcException("Invalid conversion mode"); - } - } - }; -} + if (mode == IfcParse::IfcCharacterDecoder::UTF8) { + if (builder_.empty()) { + static std::string empty; + return empty; + } else { + auto it = std::max_element(builder_.begin(), builder_.end()); + if (*it <= 0x7e) { + std::string r(builder_.begin(), builder_.end()); + return r; + } else { + return IfcUtil::convert_utf8(builder_); + } + } + } else if (mode == IfcParse::IfcCharacterDecoder::SUBSTITUTE) { + std::string r; + r.reserve(builder_.size()); + std::transform(builder_.begin(), builder_.end(), std::back_inserter(r), [&substitution_character](wchar_t c) { + if (c >= 0x20 && c <= 0x7e) { + return (char)c; + } else { + return substitution_character; + } + }); + return r; + } else if (mode == IfcParse::IfcCharacterDecoder::ESCAPE) { + std::stringstream str; + str << std::hex << std::setw(4) << std::setfill('0'); + std::for_each(builder_.begin(), builder_.end(), [&str](wchar_t c) { + if (c >= 0x20 && c <= 0x7e) { + str.put((char)c); + } else { + str << "\\u" << c; + } + }); + return str.str(); + } else { + throw IfcParse::IfcException("Invalid conversion mode"); + } + } +}; +} // namespace IfcCharacterDecoder::operator std::string() { - return pure_impure_helper(file).get(mode, substitution_character); + return pure_impure_helper(file).get(mode, substitution_character); } std::string IfcCharacterDecoder::get(unsigned int& ptr) { - return pure_impure_helper(file, ptr).get(mode, substitution_character); + return pure_impure_helper(file, ptr).get(mode, substitution_character); } void IfcCharacterDecoder::skip() { - unsigned int parse_state = 0; - char current_char; - unsigned int hex_count = 0; - while ((current_char = file->Peek()) != 0) { - if ( EXPECTS_CHARACTER(parse_state) ) { - parse_state = 0; - } else if ( current_char == '\'' && ! parse_state ) { - parse_state = APOSTROPHE; - } else if ( current_char == '\\' && ! parse_state ) { - parse_state = FIRST_SOLIDUS; - } else if ( current_char == '\\' && EXPECTS_SOLIDUS(parse_state) ) { - if ( parse_state & ALPHABET_DEFINITION || - parse_state & IGNORED_DIRECTIVE || - parse_state & ENDEXTENDED_0 ) parse_state = hex_count = 0; - else if ( parse_state & ENCOUNTERED_HEX ) { - parse_state += THIRD_SOLIDUS; - parse_state -= ENCOUNTERED_HEX; - } - else parse_state += SECOND_SOLIDUS; - } else if ( current_char == 'X' && EXPECTS_ENDEXTENDED_X(parse_state) ) { - parse_state += ENDEXTENDED_X; - } else if ( current_char == '0' && EXPECTS_ENDEXTENDED_0(parse_state) ) { - parse_state += ENDEXTENDED_0; - } else if ( current_char == 'X' && EXPECTS_ARBITRARY(parse_state) ) { - parse_state += ARBITRARY; - } else if ( current_char == '2' && EXPECTS_ARBITRARY2(parse_state) ) { - parse_state += EXTENDED2; - } else if ( current_char == '4' && EXPECTS_ARBITRARY2(parse_state) ) { - parse_state += EXTENDED2 + EXTENDED4; - } else if ( current_char == 'P' && EXPECTS_ALPHABET(parse_state) ) { - parse_state += ALPHABET; - } else if ( (current_char == 'N' || current_char == 'F') && EXPECTS_N_OR_F(parse_state) ) { - parse_state += IGNORED_DIRECTIVE; - } else if ( IS_VALID_ALPHABET_DEFINITION(current_char) && EXPECTS_ALPHABET_DEFINITION(parse_state) ) { - parse_state += ALPHABET_DEFINITION; - } else if ( current_char == 'S' && EXPECTS_PAGE(parse_state) ) { - parse_state += PAGE; - } else if ( IS_HEXADECIMAL(current_char) && EXPECTS_HEX(parse_state) ) { - parse_state += HEX((++hex_count)); - if ( (hex_count == 2 && !(parse_state & EXTENDED2)) || - (hex_count == 4 && !(parse_state & EXTENDED4)) || - (hex_count == 8) ) { - if ( hex_count == 2 ) parse_state = 0; - else { - CLEAR_HEX(parse_state); - parse_state |= ENCOUNTERED_HEX; - } - hex_count = 0; - } - } else if ( parse_state && !( - (current_char == '\\' && parse_state == FIRST_SOLIDUS) || - (current_char == '\'' && parse_state == APOSTROPHE) - ) ) { - if ( parse_state == APOSTROPHE && current_char != '\'' ) break; - throw IfcInvalidTokenException(file->Tell(), current_char); - } else { - parse_state = hex_count = 0; - } - file->Inc(); - } + unsigned int parse_state = 0; + char current_char; + unsigned int hex_count = 0; + while ((current_char = file->Peek()) != 0) { + if (EXPECTS_CHARACTER(parse_state)) { + parse_state = 0; + } else if (current_char == '\'' && !parse_state) { + parse_state = APOSTROPHE; + } else if (current_char == '\\' && !parse_state) { + parse_state = FIRST_SOLIDUS; + } else if (current_char == '\\' && EXPECTS_SOLIDUS(parse_state)) { + if (parse_state & ALPHABET_DEFINITION || + parse_state & IGNORED_DIRECTIVE || + parse_state & ENDEXTENDED_0) { + parse_state = hex_count = 0; + } else if (parse_state & ENCOUNTERED_HEX) { + parse_state += THIRD_SOLIDUS; + parse_state -= ENCOUNTERED_HEX; + } else { + parse_state += SECOND_SOLIDUS; + } + } else if (current_char == 'X' && EXPECTS_ENDEXTENDED_X(parse_state)) { + parse_state += ENDEXTENDED_X; + } else if (current_char == '0' && EXPECTS_ENDEXTENDED_0(parse_state)) { + parse_state += ENDEXTENDED_0; + } else if (current_char == 'X' && EXPECTS_ARBITRARY(parse_state)) { + parse_state += ARBITRARY; + } else if (current_char == '2' && EXPECTS_ARBITRARY2(parse_state)) { + parse_state += EXTENDED2; + } else if (current_char == '4' && EXPECTS_ARBITRARY2(parse_state)) { + parse_state += EXTENDED2 + EXTENDED4; + } else if (current_char == 'P' && EXPECTS_ALPHABET(parse_state)) { + parse_state += ALPHABET; + } else if ((current_char == 'N' || current_char == 'F') && EXPECTS_N_OR_F(parse_state)) { + parse_state += IGNORED_DIRECTIVE; + } else if (IS_VALID_ALPHABET_DEFINITION(current_char) && EXPECTS_ALPHABET_DEFINITION(parse_state)) { + parse_state += ALPHABET_DEFINITION; + } else if (current_char == 'S' && EXPECTS_PAGE(parse_state)) { + parse_state += PAGE; + } else if (IS_HEXADECIMAL(current_char) && EXPECTS_HEX(parse_state)) { + parse_state += HEX((++hex_count)); + if ((hex_count == 2 && !(parse_state & EXTENDED2)) || + (hex_count == 4 && !(parse_state & EXTENDED4)) || + (hex_count == 8)) { + if (hex_count == 2) { + parse_state = 0; + } else { + CLEAR_HEX(parse_state); + parse_state |= ENCOUNTERED_HEX; + } + hex_count = 0; + } + } else if (parse_state && !( + (current_char == '\\' && parse_state == FIRST_SOLIDUS) || + (current_char == '\'' && parse_state == APOSTROPHE))) { + if (parse_state == APOSTROPHE && current_char != '\'') { + break; + } + throw IfcInvalidTokenException(file->Tell(), current_char); + } else { + parse_state = hex_count = 0; + } + file->Inc(); + } } - IfcCharacterDecoder::ConversionMode IfcCharacterDecoder::mode = IfcCharacterDecoder::UTF8; char IfcCharacterDecoder::substitution_character = '_'; IfcCharacterEncoder::IfcCharacterEncoder(const std::string& input) - : str(IfcUtil::convert_utf8_to_utf32(input)) {} - + : str(IfcUtil::convert_utf8_to_utf32(input)) {} + IfcCharacterEncoder::operator std::string() { - std::ostringstream oss; - oss.put('\''); + std::ostringstream oss; + oss.put('\''); - // Either 2 or 4 to uses \X2 or \X4 respectively. - // Currently hardcoded to 4, but \X2 might be - // sufficient for nearly all purposes. - const int num_bytes = (str.empty() || (*std::max_element(str.begin(), str.end()) > 0xffff)) ? 4 : 2; - const std::string num_bytes_str = std::string(1,num_bytes + 0x30); - - bool in_extended = false; + // Either 2 or 4 to uses \X2 or \X4 respectively. + // Currently hardcoded to 4, but \X2 might be + // sufficient for nearly all purposes. + const int num_bytes = (str.empty() || (*std::max_element(str.begin(), str.end()) > 0xffff)) ? 4 : 2; + const std::string num_bytes_str = std::string(1, num_bytes + 0x30); - for (auto it = str.begin(); it != str.end(); ++it) { - auto ch = *it; - const bool within_spf_range = ch >= 0x20 && ch <= 0x7e; - if ( in_extended && within_spf_range ) { - oss << "\\X0\\"; - } else if ( !in_extended && !within_spf_range ) { - oss << "\\X" << num_bytes_str << "\\"; - } - if ( within_spf_range ) { - oss.put((char)ch); - if ( ch == '\\' || ch == '\'' ) oss.put((char)ch); - } else { - oss << std::hex << std::setw(num_bytes*2) << std::uppercase << std::setfill('0') << (int) ch; - } - in_extended = !within_spf_range; - } + bool in_extended = false; - if ( in_extended ) oss << "\\X0\\"; + for (auto it = str.begin(); it != str.end(); ++it) { + auto ch = *it; + const bool within_spf_range = ch >= 0x20 && ch <= 0x7e; + if (in_extended && within_spf_range) { + oss << "\\X0\\"; + } else if (!in_extended && !within_spf_range) { + oss << "\\X" << num_bytes_str << "\\"; + } + if (within_spf_range) { + oss.put((char)ch); + if (ch == '\\' || ch == '\'') { + oss.put((char)ch); + } + } else { + oss << std::hex << std::setw(num_bytes * 2) << std::uppercase << std::setfill('0') << (int)ch; + } + in_extended = !within_spf_range; + } - oss.put('\''); - return oss.str(); + if (in_extended) { + oss << "\\X0\\"; + } + + oss.put('\''); + return oss.str(); } /* @@ -364,43 +379,41 @@ def _(): "{%s}" % ",".join(_()) */ std::wstring::value_type IfcUtil::convert_codepage(int codepage, int c) { - if (codepage < 1 || codepage > 16 || codepage == 12) { - throw IfcParse::IfcException("Invalid codepage"); - } - if (c < 0 || c > 255) { - throw IfcParse::IfcException("Invalid character ordinal"); - } - static std::array, 16> codepage_data = { { - {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255}}, - {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 260, 728, 321, 164, 317, 346, 167, 168, 352, 350, 356, 377, 173, 381, 379, 176, 261, 731, 322, 180, 318, 347, 711, 184, 353, 351, 357, 378, 733, 382, 380, 340, 193, 194, 258, 196, 313, 262, 199, 268, 201, 280, 203, 282, 205, 206, 270, 272, 323, 327, 211, 212, 336, 214, 215, 344, 366, 218, 368, 220, 221, 354, 223, 341, 225, 226, 259, 228, 314, 263, 231, 269, 233, 281, 235, 283, 237, 238, 271, 273, 324, 328, 243, 244, 337, 246, 247, 345, 367, 250, 369, 252, 253, 355, 729}}, - {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 294, 728, 163, 164, 0, 292, 167, 168, 304, 350, 286, 308, 173, 0, 379, 176, 295, 178, 179, 180, 181, 293, 183, 184, 305, 351, 287, 309, 189, 0, 380, 192, 193, 194, 0, 196, 266, 264, 199, 200, 201, 202, 203, 204, 205, 206, 207, 0, 209, 210, 211, 212, 288, 214, 215, 284, 217, 218, 219, 220, 364, 348, 223, 224, 225, 226, 0, 228, 267, 265, 231, 232, 233, 234, 235, 236, 237, 238, 239, 0, 241, 242, 243, 244, 289, 246, 247, 285, 249, 250, 251, 252, 365, 349, 729}}, - {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 260, 312, 342, 164, 296, 315, 167, 168, 352, 274, 290, 358, 173, 381, 175, 176, 261, 731, 343, 180, 297, 316, 711, 184, 353, 275, 291, 359, 330, 382, 331, 256, 193, 194, 195, 196, 197, 198, 302, 268, 201, 280, 203, 278, 205, 206, 298, 272, 325, 332, 310, 212, 213, 214, 215, 216, 370, 218, 219, 220, 360, 362, 223, 257, 225, 226, 227, 228, 229, 230, 303, 269, 233, 281, 235, 279, 237, 238, 299, 273, 326, 333, 311, 244, 245, 246, 247, 248, 371, 250, 251, 252, 361, 363, 729}}, - {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 173, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 8470, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 167, 1118, 1119}}, - {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 0, 1548, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1563, 0, 0, 0, 1567, 0, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 0, 0, 0, 0, 0, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 8216, 8217, 163, 8364, 8367, 166, 167, 168, 169, 890, 171, 172, 173, 0, 8213, 176, 177, 178, 179, 900, 901, 902, 183, 904, 905, 906, 187, 908, 189, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 0, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 0}}, - {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 0, 162, 163, 164, 165, 166, 167, 168, 169, 215, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 247, 187, 188, 189, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8215, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 0, 0, 8206, 8207, 0}}, - {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 286, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 304, 350, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 287, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 305, 351, 255}}, - {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 260, 274, 290, 298, 296, 310, 167, 315, 272, 352, 358, 381, 173, 362, 330, 176, 261, 275, 291, 299, 297, 311, 183, 316, 273, 353, 359, 382, 8213, 363, 331, 256, 193, 194, 195, 196, 197, 198, 302, 268, 201, 280, 203, 278, 205, 206, 207, 208, 325, 332, 211, 212, 213, 214, 360, 216, 370, 218, 219, 220, 221, 222, 223, 257, 225, 226, 227, 228, 229, 230, 303, 269, 233, 281, 235, 279, 237, 238, 239, 240, 326, 333, 243, 244, 245, 246, 361, 248, 371, 250, 251, 252, 253, 254, 312}}, - {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 3585, 3586, 3587, 3588, 3589, 3590, 3591, 3592, 3593, 3594, 3595, 3596, 3597, 3598, 3599, 3600, 3601, 3602, 3603, 3604, 3605, 3606, 3607, 3608, 3609, 3610, 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, 3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, 0, 0, 0, 0, 3647, 3648, 3649, 3650, 3651, 3652, 3653, 3654, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, 3674, 3675, 0, 0, 0, 0}}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 8221, 162, 163, 164, 8222, 166, 167, 216, 169, 342, 171, 172, 173, 174, 198, 176, 177, 178, 179, 8220, 181, 182, 183, 248, 185, 343, 187, 188, 189, 190, 230, 260, 302, 256, 262, 196, 197, 280, 274, 268, 201, 377, 278, 290, 310, 298, 315, 352, 323, 325, 211, 332, 213, 214, 215, 370, 321, 346, 362, 220, 379, 381, 223, 261, 303, 257, 263, 228, 229, 281, 275, 269, 233, 378, 279, 291, 311, 299, 316, 353, 324, 326, 243, 333, 245, 246, 247, 371, 322, 347, 363, 252, 380, 382, 8217}}, - {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 7682, 7683, 163, 266, 267, 7690, 167, 7808, 169, 7810, 7691, 7922, 173, 174, 376, 7710, 7711, 288, 289, 7744, 7745, 182, 7766, 7809, 7767, 7811, 7776, 7923, 7812, 7813, 7777, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 372, 209, 210, 211, 212, 213, 214, 7786, 216, 217, 218, 219, 220, 221, 374, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 373, 241, 242, 243, 244, 245, 246, 7787, 248, 249, 250, 251, 252, 253, 375, 255}}, - {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 8364, 165, 352, 167, 353, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 381, 181, 182, 183, 382, 185, 186, 187, 338, 339, 376, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255}}, - {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 260, 261, 321, 8364, 8222, 352, 167, 353, 169, 536, 171, 377, 173, 378, 379, 176, 177, 268, 322, 381, 8221, 182, 183, 382, 269, 537, 187, 338, 339, 376, 380, 192, 193, 194, 258, 196, 262, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 272, 323, 210, 211, 212, 336, 214, 346, 368, 217, 218, 219, 220, 280, 538, 223, 224, 225, 226, 259, 228, 263, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 273, 324, 242, 243, 244, 337, 246, 347, 369, 249, 250, 251, 252, 281, 539, 255}} - }}; - auto r = codepage_data[codepage - 1][c]; - if (r == 0) { - throw IfcParse::IfcException("Character not defined"); - } - return r; + if (codepage < 1 || codepage > 16 || codepage == 12) { + throw IfcParse::IfcException("Invalid codepage"); + } + if (c < 0 || c > 255) { + throw IfcParse::IfcException("Invalid character ordinal"); + } + static std::array, 16> codepage_data = {{{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255}}, + {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 260, 728, 321, 164, 317, 346, 167, 168, 352, 350, 356, 377, 173, 381, 379, 176, 261, 731, 322, 180, 318, 347, 711, 184, 353, 351, 357, 378, 733, 382, 380, 340, 193, 194, 258, 196, 313, 262, 199, 268, 201, 280, 203, 282, 205, 206, 270, 272, 323, 327, 211, 212, 336, 214, 215, 344, 366, 218, 368, 220, 221, 354, 223, 341, 225, 226, 259, 228, 314, 263, 231, 269, 233, 281, 235, 283, 237, 238, 271, 273, 324, 328, 243, 244, 337, 246, 247, 345, 367, 250, 369, 252, 253, 355, 729}}, + {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 294, 728, 163, 164, 0, 292, 167, 168, 304, 350, 286, 308, 173, 0, 379, 176, 295, 178, 179, 180, 181, 293, 183, 184, 305, 351, 287, 309, 189, 0, 380, 192, 193, 194, 0, 196, 266, 264, 199, 200, 201, 202, 203, 204, 205, 206, 207, 0, 209, 210, 211, 212, 288, 214, 215, 284, 217, 218, 219, 220, 364, 348, 223, 224, 225, 226, 0, 228, 267, 265, 231, 232, 233, 234, 235, 236, 237, 238, 239, 0, 241, 242, 243, 244, 289, 246, 247, 285, 249, 250, 251, 252, 365, 349, 729}}, + {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 260, 312, 342, 164, 296, 315, 167, 168, 352, 274, 290, 358, 173, 381, 175, 176, 261, 731, 343, 180, 297, 316, 711, 184, 353, 275, 291, 359, 330, 382, 331, 256, 193, 194, 195, 196, 197, 198, 302, 268, 201, 280, 203, 278, 205, 206, 298, 272, 325, 332, 310, 212, 213, 214, 215, 216, 370, 218, 219, 220, 360, 362, 223, 257, 225, 226, 227, 228, 229, 230, 303, 269, 233, 281, 235, 279, 237, 238, 299, 273, 326, 333, 311, 244, 245, 246, 247, 248, 371, 250, 251, 252, 361, 363, 729}}, + {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 173, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 8470, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 167, 1118, 1119}}, + {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 0, 1548, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1563, 0, 0, 0, 1567, 0, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 0, 0, 0, 0, 0, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 8216, 8217, 163, 8364, 8367, 166, 167, 168, 169, 890, 171, 172, 173, 0, 8213, 176, 177, 178, 179, 900, 901, 902, 183, 904, 905, 906, 187, 908, 189, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 0, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 0}}, + {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 0, 162, 163, 164, 165, 166, 167, 168, 169, 215, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 247, 187, 188, 189, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8215, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 0, 0, 8206, 8207, 0}}, + {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 286, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 304, 350, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 287, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 305, 351, 255}}, + {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 260, 274, 290, 298, 296, 310, 167, 315, 272, 352, 358, 381, 173, 362, 330, 176, 261, 275, 291, 299, 297, 311, 183, 316, 273, 353, 359, 382, 8213, 363, 331, 256, 193, 194, 195, 196, 197, 198, 302, 268, 201, 280, 203, 278, 205, 206, 207, 208, 325, 332, 211, 212, 213, 214, 360, 216, 370, 218, 219, 220, 221, 222, 223, 257, 225, 226, 227, 228, 229, 230, 303, 269, 233, 281, 235, 279, 237, 238, 239, 240, 326, 333, 243, 244, 245, 246, 361, 248, 371, 250, 251, 252, 253, 254, 312}}, + {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 3585, 3586, 3587, 3588, 3589, 3590, 3591, 3592, 3593, 3594, 3595, 3596, 3597, 3598, 3599, 3600, 3601, 3602, 3603, 3604, 3605, 3606, 3607, 3608, 3609, 3610, 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, 3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, 0, 0, 0, 0, 3647, 3648, 3649, 3650, 3651, 3652, 3653, 3654, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, 3674, 3675, 0, 0, 0, 0}}, + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 8221, 162, 163, 164, 8222, 166, 167, 216, 169, 342, 171, 172, 173, 174, 198, 176, 177, 178, 179, 8220, 181, 182, 183, 248, 185, 343, 187, 188, 189, 190, 230, 260, 302, 256, 262, 196, 197, 280, 274, 268, 201, 377, 278, 290, 310, 298, 315, 352, 323, 325, 211, 332, 213, 214, 215, 370, 321, 346, 362, 220, 379, 381, 223, 261, 303, 257, 263, 228, 229, 281, 275, 269, 233, 378, 279, 291, 311, 299, 316, 353, 324, 326, 243, 333, 245, 246, 247, 371, 322, 347, 363, 252, 380, 382, 8217}}, + {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 7682, 7683, 163, 266, 267, 7690, 167, 7808, 169, 7810, 7691, 7922, 173, 174, 376, 7710, 7711, 288, 289, 7744, 7745, 182, 7766, 7809, 7767, 7811, 7776, 7923, 7812, 7813, 7777, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 372, 209, 210, 211, 212, 213, 214, 7786, 216, 217, 218, 219, 220, 221, 374, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 373, 241, 242, 243, 244, 245, 246, 7787, 248, 249, 250, 251, 252, 253, 375, 255}}, + {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 8364, 165, 352, 167, 353, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 381, 181, 182, 183, 382, 185, 186, 187, 338, 339, 376, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255}}, + {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 260, 261, 321, 8364, 8222, 352, 167, 353, 169, 536, 171, 377, 173, 378, 379, 176, 177, 268, 322, 381, 8221, 182, 183, 382, 269, 537, 187, 338, 339, 376, 380, 192, 193, 194, 258, 196, 262, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 272, 323, 210, 211, 212, 336, 214, 346, 368, 217, 218, 219, 220, 280, 538, 223, 224, 225, 226, 259, 228, 263, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 273, 324, 242, 243, 244, 337, 246, 347, 369, 249, 250, 251, 252, 281, 539, 255}}}}; + auto r = codepage_data[codepage - 1][c]; + if (r == 0) { + throw IfcParse::IfcException("Character not defined"); + } + return r; } std::string IfcUtil::convert_utf8(const std::wstring& s) { - return std::wstring_convert>().to_bytes(s); + return std::wstring_convert>().to_bytes(s); } std::wstring IfcUtil::convert_utf8(const std::string& s) { - return std::wstring_convert>().from_bytes(s); + return std::wstring_convert>().from_bytes(s); } #ifdef _MSC_VER @@ -408,14 +421,14 @@ std::wstring IfcUtil::convert_utf8(const std::string& s) { // bug in msvc 2015 and 2017, unsure if fixed in later versions std::u32string IfcUtil::convert_utf8_to_utf32(const std::string& s) { - auto converted = std::wstring_convert, int32_t>().from_bytes(s); - return std::u32string(reinterpret_cast(converted.data())); + auto converted = std::wstring_convert, int32_t>().from_bytes(s); + return std::u32string(reinterpret_cast(converted.data())); } #else std::u32string IfcUtil::convert_utf8_to_utf32(const std::string& s) { - return std::wstring_convert, std::u32string::value_type>().from_bytes(s); + return std::wstring_convert, std::u32string::value_type>().from_bytes(s); } -#endif \ No newline at end of file +#endif diff --git a/src/ifcparse/IfcCharacterDecoder.h b/src/ifcparse/IfcCharacterDecoder.h index 198b2fe9af..c0cfcca8ac 100644 --- a/src/ifcparse/IfcCharacterDecoder.h +++ b/src/ifcparse/IfcCharacterDecoder.h @@ -27,53 +27,59 @@ #ifndef IFCCHARACTERDECODER_H #define IFCCHARACTERDECODER_H -#include -#include +#include "IfcSpfStream.h" -#include "../ifcparse/IfcSpfStream.h" +#include +#include namespace IfcUtil { - std::wstring::value_type convert_codepage(int codepage, int c); - std::string convert_utf8(const std::wstring& s); - std::wstring convert_utf8(const std::string& s); - std::u32string convert_utf8_to_utf32(const std::string& s); -} +std::wstring::value_type convert_codepage(int codepage, int c); +std::string convert_utf8(const std::wstring& s); +std::wstring convert_utf8(const std::string& s); +std::u32string convert_utf8_to_utf32(const std::string& s); +} // namespace IfcUtil namespace IfcParse { - class IFC_PARSE_API IfcCharacterDecoder { - private: - IfcParse::IfcSpfStream* file; - int codepage_; - public: - enum ConversionMode {SUBSTITUTE, UTF8, ESCAPE}; - static ConversionMode mode; - static char substitution_character; - IfcCharacterDecoder(IfcParse::IfcSpfStream* file); - ~IfcCharacterDecoder(); - // Only advances the underlying token stream read pointer - // to the next token. - void skip(); - // Gets a decoded string representation at the token stream - // read pointer and advances the underlying token stream. - operator std::string(); - // Gets a decoded string representation at the offset provided, - // does not mutate the underlying token stream read pointer. - std::string get(unsigned int&); - }; +class IFC_PARSE_API IfcCharacterDecoder { + private: + IfcParse::IfcSpfStream* file; + int codepage_; -} + public: + enum ConversionMode { + SUBSTITUTE, + UTF8, + ESCAPE + }; + static ConversionMode mode; + static char substitution_character; + IfcCharacterDecoder(IfcParse::IfcSpfStream* file); + ~IfcCharacterDecoder(); + // Only advances the underlying token stream read pointer + // to the next token. + void skip(); + // Gets a decoded string representation at the token stream + // read pointer and advances the underlying token stream. + operator std::string(); + // Gets a decoded string representation at the offset provided, + // does not mutate the underlying token stream read pointer. + std::string get(unsigned int&); +}; + +} // namespace IfcParse namespace IfcWrite { - class IFC_PARSE_API IfcCharacterEncoder { - private: - std::u32string str; - public: - IfcCharacterEncoder(const std::string& input); - operator std::string(); - }; +class IFC_PARSE_API IfcCharacterEncoder { + private: + std::u32string str; -} + public: + IfcCharacterEncoder(const std::string& input); + operator std::string(); +}; + +} // namespace IfcWrite #endif diff --git a/src/ifcparse/IfcEntityInstanceData.h b/src/ifcparse/IfcEntityInstanceData.h index e8b62b172b..ffd1fbf888 100644 --- a/src/ifcparse/IfcEntityInstanceData.h +++ b/src/ifcparse/IfcEntityInstanceData.h @@ -20,81 +20,90 @@ #ifndef IFCENTITYINSTANCEDATA_H #define IFCENTITYINSTANCEDATA_H -#include "../ifcparse/ArgumentType.h" +#include "ArgumentType.h" #include #include - #include class Argument; class aggregate_of_instance; namespace IfcParse { - class IfcFile; +class IfcFile; } class IFC_PARSE_API IfcEntityInstanceData { -public: - // Public for backwards compatibility - IfcParse::IfcFile* file; -protected: - unsigned id_; - const IfcParse::declaration* type_; - mutable Argument** attributes_; - unsigned offset_in_file_; + public: + // Public for backwards compatibility + IfcParse::IfcFile* file; -public: - IfcEntityInstanceData(const IfcParse::declaration* type, IfcParse::IfcFile* file_, unsigned id = 0, unsigned offset_in_file = 0) - : file(file_), id_(id), type_(type), attributes_(0), offset_in_file_(offset_in_file) - {} + protected: + unsigned id_; + const IfcParse::declaration* type_; + mutable Argument** attributes_; + unsigned offset_in_file_; - IfcEntityInstanceData(IfcParse::IfcFile* file_, size_t size) - : file(file_), id_(0), type_(0), attributes_(new Argument*[size] {0}), offset_in_file_(0) - {} + public: + IfcEntityInstanceData(const IfcParse::declaration* type, IfcParse::IfcFile* file_, unsigned id = 0, unsigned offset_in_file = 0) + : file(file_), + id_(id), + type_(type), + attributes_(0), + offset_in_file_(offset_in_file) {} - IfcEntityInstanceData(const IfcParse::declaration* type) - : file(0), id_(0), type_(type), attributes_(new Argument*[getArgumentCount()]{ 0 }), offset_in_file_(0) - {} + IfcEntityInstanceData(IfcParse::IfcFile* file_, size_t size) + : file(file_), + id_(0), + type_(0), + attributes_(new Argument* [size] { 0 }), + offset_in_file_(0) {} - void load() const; + IfcEntityInstanceData(const IfcParse::declaration* type) + : file(0), + id_(0), + type_(type), + attributes_(new Argument* [getArgumentCount()] { 0 }), + offset_in_file_(0) {} - IfcEntityInstanceData(const IfcEntityInstanceData& e); + void load() const; - virtual ~IfcEntityInstanceData(); + IfcEntityInstanceData(const IfcEntityInstanceData& e); - boost::shared_ptr getInverse (const IfcParse::declaration* type, int attribute_index) const; + virtual ~IfcEntityInstanceData(); - Argument* getArgument(size_t i) const; + boost::shared_ptr getInverse(const IfcParse::declaration* type, int attribute_index) const; - // NB: This makes a copy of the argument if make_copy is set - void setArgument(size_t i, Argument* a, IfcUtil::ArgumentType attr_type = IfcUtil::Argument_UNKNOWN, bool make_copy = false); + Argument* getArgument(size_t i) const; - virtual size_t getArgumentCount() const { - if (type_ == 0) { - return 0; - } - if (type_->as_entity()) { - return type_->as_entity()->attribute_count(); - } else { - return 1; - } - } + // NB: This makes a copy of the argument if make_copy is set + void setArgument(size_t i, Argument* a, IfcUtil::ArgumentType attr_type = IfcUtil::Argument_UNKNOWN, bool make_copy = false); - void clearArguments(); + virtual size_t getArgumentCount() const { + if (type_ == 0) { + return 0; + } + if (type_->as_entity()) { + return type_->as_entity()->attribute_count(); + } else { + return 1; + } + } - const IfcParse::declaration* type() const { - return type_; - } + void clearArguments(); - std::string toString(bool upper = false) const; + const IfcParse::declaration* type() const { + return type_; + } - unsigned int id() const { return id_; } - unsigned int offset_in_file() const { return offset_in_file_; } + std::string toString(bool upper = false) const; - // NB: const ommitted for lazy loading - Argument**& attributes() const { return attributes_; } + unsigned int id() const { return id_; } + unsigned int offset_in_file() const { return offset_in_file_; } - unsigned set_id(boost::optional i = boost::none); + // NB: const ommitted for lazy loading + Argument**& attributes() const { return attributes_; } + + unsigned set_id(boost::optional i = boost::none); }; #endif diff --git a/src/ifcparse/IfcException.h b/src/ifcparse/IfcException.h index 72b9348d70..93e27eaa3c 100644 --- a/src/ifcparse/IfcException.h +++ b/src/ifcparse/IfcException.h @@ -23,7 +23,6 @@ #include "ifc_parse_api.h" #include - #include #include @@ -35,51 +34,46 @@ #endif namespace IfcParse { - class IFC_PARSE_API IfcException : public std::exception { - private: - std::string message; - public: - IfcException(const std::string& m) - : message(m) {} - virtual ~IfcException () throw () {} - virtual const char* what() const throw() { - return message.c_str(); - } - }; +class IFC_PARSE_API IfcException : public std::exception { + private: + std::string message; - class IFC_PARSE_API IfcAttributeOutOfRangeException : public IfcException { - public: - IfcAttributeOutOfRangeException(const std::string& e) - : IfcException(e) {} - ~IfcAttributeOutOfRangeException () throw () {} - }; + public: + IfcException(const std::string& m) + : message(m) {} + virtual ~IfcException() throw() {} + virtual const char* what() const throw() { + return message.c_str(); + } +}; - class IFC_PARSE_API IfcInvalidTokenException : public IfcException { - public: - IfcInvalidTokenException( - int token_start, - const std::string& token_string, - const std::string& expected_type - ) - : IfcException( - std::string("Token ") + token_string + " at offset " + - boost::lexical_cast(token_start) + - " invalid " + expected_type - ) - {} - IfcInvalidTokenException( - int token_start, - char c - ) - : IfcException( - std::string("Unexpected '") + std::string(1, c) + "' at offset " + - boost::lexical_cast(token_start) - ) - {} - ~IfcInvalidTokenException() throw () {} - }; +class IFC_PARSE_API IfcAttributeOutOfRangeException : public IfcException { + public: + IfcAttributeOutOfRangeException(const std::string& e) + : IfcException(e) {} + ~IfcAttributeOutOfRangeException() throw() {} +}; -} +class IFC_PARSE_API IfcInvalidTokenException : public IfcException { + public: + IfcInvalidTokenException( + int token_start, + const std::string& token_string, + const std::string& expected_type) + : IfcException( + std::string("Token ") + token_string + " at offset " + + boost::lexical_cast(token_start) + + " invalid " + expected_type) {} + IfcInvalidTokenException( + int token_start, + char c) + : IfcException( + std::string("Unexpected '") + std::string(1, c) + "' at offset " + + boost::lexical_cast(token_start)) {} + ~IfcInvalidTokenException() throw() {} +}; + +} // namespace IfcParse #ifdef _MSC_VER #pragma warning(pop) diff --git a/src/ifcparse/IfcFile.h b/src/ifcparse/IfcFile.h index 88bed3c065..679bce3f35 100644 --- a/src/ifcparse/IfcFile.h +++ b/src/ifcparse/IfcFile.h @@ -20,319 +20,323 @@ #ifndef IFCFILE_H #define IFCFILE_H -#include -#include -#include +#include "ifc_parse_api.h" +#include "IfcParse.h" +#include "IfcSchema.h" +#include "IfcSpfHeader.h" -#include -#include -#include #include #include - -#include "ifc_parse_api.h" - -#include "../ifcparse/IfcParse.h" -#include "../ifcparse/IfcSpfHeader.h" -#include "../ifcparse/IfcSchema.h" +#include +#include +#include +#include +#include +#include namespace IfcParse { class IFC_PARSE_API file_open_status { -public: - enum file_open_enum { - SUCCESS, - READ_ERROR, - NO_HEADER, - UNSUPPORTED_SCHEMA - }; + public: + enum file_open_enum { + SUCCESS, + READ_ERROR, + NO_HEADER, + UNSUPPORTED_SCHEMA + }; -private: - file_open_enum error_; + private: + file_open_enum error_; -public: - file_open_status(file_open_enum error) - : error_(error) - {} + public: + file_open_status(file_open_enum error) + : error_(error) {} - operator file_open_enum() const { - return error_; - } + operator file_open_enum() const { + return error_; + } - file_open_enum value() const { - return error_; - } + file_open_enum value() const { + return error_; + } - operator bool() const { - return error_ == SUCCESS; - } + operator bool() const { + return error_ == SUCCESS; + } }; /// This class provides several static convenience functions and variables /// and provide access to the entities in an IFC file class IFC_PARSE_API IfcFile { -public: - typedef std::map entities_by_type_t; - typedef boost::unordered_map entity_by_id_t; - typedef boost::unordered_map entity_by_iden_t; - typedef std::map entity_by_guid_t; - typedef std::tuple inverse_attr_record; - enum INVERSE_ATTR { INSTANCE_ID, INSTANCE_TYPE, ATTRIBUTE_INDEX }; - typedef std::map > entities_by_ref_t; - typedef std::map > entities_by_ref_excl_t; - typedef std::map ref_map_t; - typedef entity_by_id_t::const_iterator const_iterator; + public: + typedef std::map entities_by_type_t; + typedef boost::unordered_map entity_by_id_t; + typedef boost::unordered_map entity_by_iden_t; + typedef std::map entity_by_guid_t; + typedef std::tuple inverse_attr_record; + enum INVERSE_ATTR { + INSTANCE_ID, + INSTANCE_TYPE, + ATTRIBUTE_INDEX + }; + typedef std::map> entities_by_ref_t; + typedef std::map> entities_by_ref_excl_t; + typedef std::map ref_map_t; + typedef entity_by_id_t::const_iterator const_iterator; - class type_iterator : private entities_by_type_t::const_iterator { - public: - type_iterator() : entities_by_type_t::const_iterator() {}; + class type_iterator : private entities_by_type_t::const_iterator { + public: + type_iterator() : entities_by_type_t::const_iterator(){}; - type_iterator(const entities_by_type_t::const_iterator& it) - : entities_by_type_t::const_iterator(it) - {}; + type_iterator(const entities_by_type_t::const_iterator& it) + : entities_by_type_t::const_iterator(it){}; - entities_by_type_t::key_type const * operator->() const { - return &entities_by_type_t::const_iterator::operator->()->first; - } + entities_by_type_t::key_type const* operator->() const { + return &entities_by_type_t::const_iterator::operator->()->first; + } - entities_by_type_t::key_type const & operator*() const { - return entities_by_type_t::const_iterator::operator*().first; - } + entities_by_type_t::key_type const& operator*() const { + return entities_by_type_t::const_iterator::operator*().first; + } - type_iterator& operator++() { - entities_by_type_t::const_iterator::operator++(); return *this; - } + type_iterator& operator++() { + entities_by_type_t::const_iterator::operator++(); + return *this; + } - type_iterator operator++(int) { - type_iterator tmp(*this); operator++(); return tmp; - } + type_iterator operator++(int) { + type_iterator tmp(*this); + operator++(); + return tmp; + } - bool operator!=(const type_iterator& other) const { - const entities_by_type_t::const_iterator& self_ = *this; - const entities_by_type_t::const_iterator& other_ = other; - return self_ != other_; - } - }; + bool operator!=(const type_iterator& other) const { + const entities_by_type_t::const_iterator& self_ = *this; + const entities_by_type_t::const_iterator& other_ = other; + return self_ != other_; + } + }; - static bool lazy_load_; - static bool lazy_load() { return lazy_load_; } - static void lazy_load(bool b) { lazy_load_ = b; } + static bool lazy_load_; + static bool lazy_load() { return lazy_load_; } + static void lazy_load(bool b) { lazy_load_ = b; } - static bool guid_map_; - static bool guid_map() { return guid_map_; } - static void guid_map(bool b) { guid_map_ = b; } + static bool guid_map_; + static bool guid_map() { return guid_map_; } + static void guid_map(bool b) { guid_map_ = b; } -private: - typedef std::map entity_entity_map_t; + private: + typedef std::map entity_entity_map_t; - bool parsing_complete_; - file_open_status good_ = file_open_status::SUCCESS; + bool parsing_complete_; + file_open_status good_ = file_open_status::SUCCESS; - const IfcParse::schema_definition* schema_; - const IfcParse::declaration* ifcroot_type_; + const IfcParse::schema_definition* schema_; + const IfcParse::declaration* ifcroot_type_; - std::vector internal_attribute_vector_, internal_attribute_vector_simple_type_; + std::vector internal_attribute_vector_, internal_attribute_vector_simple_type_; - entity_by_id_t byid; - // this is for simple types - entity_by_iden_t byidentity; - entities_by_type_t bytype; - entities_by_type_t bytype_excl; - entities_by_ref_t byref; - entities_by_ref_excl_t byref_excl; - entity_by_guid_t byguid; - entity_entity_map_t entity_file_map; + entity_by_id_t byid; + // this is for simple types + entity_by_iden_t byidentity; + entities_by_type_t bytype; + entities_by_type_t bytype_excl; + entities_by_ref_t byref; + entities_by_ref_excl_t byref_excl; + entity_by_guid_t byguid; + entity_entity_map_t entity_file_map; - unsigned int MaxId; + unsigned int MaxId; - IfcSpfHeader _header; + IfcSpfHeader _header; - void setDefaultHeaderValues(); + void setDefaultHeaderValues(); - void initialize_(IfcParse::IfcSpfStream* f); + void initialize_(IfcParse::IfcSpfStream* f); - void build_inverses_(IfcUtil::IfcBaseClass*); + void build_inverses_(IfcUtil::IfcBaseClass*); - typedef boost::multi_index_container< - int, - boost::multi_index::indexed_by< - boost::multi_index::sequenced<>, - boost::multi_index::ordered_unique< - boost::multi_index::identity - > - > - > batch_deletion_ids_t; - batch_deletion_ids_t batch_deletion_ids_; - bool batch_mode_ = false; - void process_deletion_(); + typedef boost::multi_index_container< + int, + boost::multi_index::indexed_by< + boost::multi_index::sequenced<>, + boost::multi_index::ordered_unique< + boost::multi_index::identity>>> + batch_deletion_ids_t; + batch_deletion_ids_t batch_deletion_ids_; + bool batch_mode_ = false; + void process_deletion_(); + + public: + IfcParse::IfcSpfLexer* tokens; + IfcParse::IfcSpfStream* stream; -public: - IfcParse::IfcSpfLexer* tokens; - IfcParse::IfcSpfStream* stream; - #ifdef USE_MMAP - IfcFile(const std::string& fn, bool mmap = false); + IfcFile(const std::string& fn, bool mmap = false); #else - IfcFile(const std::string& fn); + IfcFile(const std::string& fn); #endif - IfcFile(std::istream& fn, int len); - IfcFile(void* data, int len); - IfcFile(IfcParse::IfcSpfStream* f); - IfcFile(const IfcParse::schema_definition* schema = IfcParse::schema_by_name("IFC4")); + IfcFile(std::istream& fn, int len); + IfcFile(void* data, int len); + IfcFile(IfcParse::IfcSpfStream* f); + IfcFile(const IfcParse::schema_definition* schema = IfcParse::schema_by_name("IFC4")); - /// Deleting the file will also delete all new instances that were added to the file (via memory allocation) - virtual ~IfcFile(); + /// Deleting the file will also delete all new instances that were added to the file (via memory allocation) + virtual ~IfcFile(); - file_open_status good() const { return good_; } - - /// Returns the first entity in the file, this probably is the entity - /// with the lowest id (EXPRESS ENTITY_INSTANCE_NAME) - const_iterator begin() const; - /// Returns the last entity in the file, this probably is the entity - /// with the highest id (EXPRESS ENTITY_INSTANCE_NAME) - const_iterator end() const; + file_open_status good() const { return good_; } - type_iterator types_begin() const; - type_iterator types_end() const; + /// Returns the first entity in the file, this probably is the entity + /// with the lowest id (EXPRESS ENTITY_INSTANCE_NAME) + const_iterator begin() const; + /// Returns the last entity in the file, this probably is the entity + /// with the highest id (EXPRESS ENTITY_INSTANCE_NAME) + const_iterator end() const; - type_iterator types_incl_super_begin() const; - type_iterator types_incl_super_end() const; + type_iterator types_begin() const; + type_iterator types_end() const; - /// Returns all entities in the file that match the template argument. - /// NOTE: This also returns subtypes of the requested type, for example: - /// IfcWall will also return IfcWallStandardCase entities - template - typename T::list::ptr instances_by_type() { - aggregate_of_instance::ptr untyped_list = instances_by_type(&T::Class()); - if (untyped_list) { - return untyped_list->as(); - } else { - return typename T::list::ptr(new typename T::list); - } - } + type_iterator types_incl_super_begin() const; + type_iterator types_incl_super_end() const; - template - typename T::list::ptr instances_by_type_excl_subtypes() { - aggregate_of_instance::ptr untyped_list = instances_by_type_excl_subtypes(&T::Class()); - if (untyped_list) { - return untyped_list->as(); - } else { - return typename T::list::ptr(new typename T::list); - } - } + /// Returns all entities in the file that match the template argument. + /// NOTE: This also returns subtypes of the requested type, for example: + /// IfcWall will also return IfcWallStandardCase entities + template + typename T::list::ptr instances_by_type() { + aggregate_of_instance::ptr untyped_list = instances_by_type(&T::Class()); + if (untyped_list) { + return untyped_list->as(); + } else { + return typename T::list::ptr(new typename T::list); + } + } - /// Returns all entities in the file that match the positional argument. - /// NOTE: This also returns subtypes of the requested type, for example: - /// IfcWall will also return IfcWallStandardCase entities - aggregate_of_instance::ptr instances_by_type(const IfcParse::declaration*); + template + typename T::list::ptr instances_by_type_excl_subtypes() { + aggregate_of_instance::ptr untyped_list = instances_by_type_excl_subtypes(&T::Class()); + if (untyped_list) { + return untyped_list->as(); + } else { + return typename T::list::ptr(new typename T::list); + } + } - /// Returns all entities in the file that match the positional argument. - aggregate_of_instance::ptr instances_by_type_excl_subtypes(const IfcParse::declaration*); + /// Returns all entities in the file that match the positional argument. + /// NOTE: This also returns subtypes of the requested type, for example: + /// IfcWall will also return IfcWallStandardCase entities + aggregate_of_instance::ptr instances_by_type(const IfcParse::declaration*); - /// Returns all entities in the file that match the positional argument. - /// NOTE: This also returns subtypes of the requested type, for example: - /// IfcWall will also return IfcWallStandardCase entities - aggregate_of_instance::ptr instances_by_type(const std::string& t); + /// Returns all entities in the file that match the positional argument. + aggregate_of_instance::ptr instances_by_type_excl_subtypes(const IfcParse::declaration*); - /// Returns all entities in the file that match the positional argument. - aggregate_of_instance::ptr instances_by_type_excl_subtypes(const std::string& t); - - /// Returns all entities in the file that reference the id - aggregate_of_instance::ptr instances_by_reference(int id); + /// Returns all entities in the file that match the positional argument. + /// NOTE: This also returns subtypes of the requested type, for example: + /// IfcWall will also return IfcWallStandardCase entities + aggregate_of_instance::ptr instances_by_type(const std::string& t); - /// Returns the entity with the specified id - IfcUtil::IfcBaseClass* instance_by_id(int id); + /// Returns all entities in the file that match the positional argument. + aggregate_of_instance::ptr instances_by_type_excl_subtypes(const std::string& t); - /// Returns the entity with the specified GlobalId - IfcUtil::IfcBaseClass* instance_by_guid(const std::string& guid); + /// Returns all entities in the file that reference the id + aggregate_of_instance::ptr instances_by_reference(int id); - /// Performs a depth-first traversal, returning all entity instance - /// attributes as a flat list. NB: includes the root instance specified - /// in the first function argument. - aggregate_of_instance::ptr traverse(IfcUtil::IfcBaseClass* instance, int max_level=-1); + /// Returns the entity with the specified id + IfcUtil::IfcBaseClass* instance_by_id(int id); - /// Same as traverse() but maintains topological order by using a - /// breadth-first search - aggregate_of_instance::ptr traverse_breadth_first(IfcUtil::IfcBaseClass* instance, int max_level=-1); + /// Returns the entity with the specified GlobalId + IfcUtil::IfcBaseClass* instance_by_guid(const std::string& guid); - /// Get the attribute indices corresponding to the list of entity instances - /// returned by getInverse(). - std::vector get_inverse_indices(int instance_id); + /// Performs a depth-first traversal, returning all entity instance + /// attributes as a flat list. NB: includes the root instance specified + /// in the first function argument. + aggregate_of_instance::ptr traverse(IfcUtil::IfcBaseClass* instance, int max_level = -1); - aggregate_of_instance::ptr getInverse(int instance_id, const IfcParse::declaration* type, int attribute_index); - - int getTotalInverses(int instance_id); + /// Same as traverse() but maintains topological order by using a + /// breadth-first search + aggregate_of_instance::ptr traverse_breadth_first(IfcUtil::IfcBaseClass* instance, int max_level = -1); - template - typename T::list::ptr getInverse(int instance_id, int attribute_index) { - return getInverse(instance_id, &T::Class(), attribute_index)->template as(); - } + /// Get the attribute indices corresponding to the list of entity instances + /// returned by getInverse(). + std::vector get_inverse_indices(int instance_id); - unsigned int FreshId() { return ++MaxId; } + aggregate_of_instance::ptr getInverse(int instance_id, const IfcParse::declaration* type, int attribute_index); - unsigned int getMaxId() const { return MaxId; } + int getTotalInverses(int instance_id); - const IfcParse::declaration* ifcroot_type() const { return ifcroot_type_; } + template + typename T::list::ptr getInverse(int instance_id, int attribute_index) { + return getInverse(instance_id, &T::Class(), attribute_index)->template as(); + } - void recalculate_id_counter(); + unsigned int FreshId() { return ++MaxId; } - IfcUtil::IfcBaseClass* addEntity(IfcUtil::IfcBaseClass* entity, int id=-1); - void addEntities(aggregate_of_instance::ptr es); + unsigned int getMaxId() const { return MaxId; } - void batch() { batch_mode_ = true; } - void unbatch() { process_deletion_(); batch_mode_ = false; } + const IfcParse::declaration* ifcroot_type() const { return ifcroot_type_; } - /// Removes entity instance from file and unsets references. - /// - /// Attention when running removeEntity inside a loop over a list of entities to be removed. - /// This invalidates the iterator. A workaround is to reverse the loop: - /// boost::shared_ptr entities = ...; - /// for (auto it = entities->end() - 1; it >= entities->begin(); --it) { - /// IfcUtil::IfcBaseClass *const inst = *it; - /// model->removeEntity(inst); - /// } - void removeEntity(IfcUtil::IfcBaseClass* entity); + void recalculate_id_counter(); - const IfcSpfHeader& header() const { return _header; } - IfcSpfHeader& header() { return _header; } + IfcUtil::IfcBaseClass* addEntity(IfcUtil::IfcBaseClass* entity, int id = -1); + void addEntities(aggregate_of_instance::ptr es); - std::string createTimestamp() const; + void batch() { batch_mode_ = true; } + void unbatch() { + process_deletion_(); + batch_mode_ = false; + } - size_t load(unsigned entity_instance_name, const IfcParse::entity* entity, Argument**& attributes, size_t num_attributes, int attribute_index=-1); - void seek_to(const IfcEntityInstanceData& data); - void try_read_semicolon(); + /// Removes entity instance from file and unsets references. + /// + /// Attention when running removeEntity inside a loop over a list of entities to be removed. + /// This invalidates the iterator. A workaround is to reverse the loop: + /// boost::shared_ptr entities = ...; + /// for (auto it = entities->end() - 1; it >= entities->begin(); --it) { + /// IfcUtil::IfcBaseClass *const inst = *it; + /// model->removeEntity(inst); + /// } + void removeEntity(IfcUtil::IfcBaseClass* entity); - void register_inverse(unsigned, const IfcParse::entity* from_entity, Token, int attribute_index); - void register_inverse(unsigned, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass*, int attribute_index); - void unregister_inverse(unsigned, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass*, int attribute_index); - - const IfcParse::schema_definition* schema() const { return schema_; } + const IfcSpfHeader& header() const { return _header; } + IfcSpfHeader& header() { return _header; } - std::pair getUnit(const std::string& unit_type); + std::string createTimestamp() const; - bool parsing_complete() const { return parsing_complete_; } - bool& parsing_complete() { return parsing_complete_; } + size_t load(unsigned entity_instance_name, const IfcParse::entity* entity, Argument**& attributes, size_t num_attributes, int attribute_index = -1); + void seek_to(const IfcEntityInstanceData& data); + void try_read_semicolon(); - void build_inverses(); + void register_inverse(unsigned, const IfcParse::entity* from_entity, Token, int attribute_index); + void register_inverse(unsigned, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass*, int attribute_index); + void unregister_inverse(unsigned, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass*, int attribute_index); - entity_by_guid_t& internal_guid_map() { return byguid; }; + const IfcParse::schema_definition* schema() const { return schema_; } + + std::pair getUnit(const std::string& unit_type); + + bool parsing_complete() const { return parsing_complete_; } + bool& parsing_complete() { return parsing_complete_; } + + void build_inverses(); + + entity_by_guid_t& internal_guid_map() { return byguid; }; }; #ifdef WITH_IFCXML IFC_PARSE_API IfcFile* parse_ifcxml(const std::string& filename); #endif -} +} // namespace IfcParse namespace std { - template <> - struct iterator_traits { - typedef ptrdiff_t difference_type; - typedef const IfcParse::declaration* value_type; - typedef const IfcParse::declaration*& reference; - typedef const IfcParse::declaration** pointer; - typedef std::forward_iterator_tag iterator_category; - }; -} +template <> +struct iterator_traits { + typedef ptrdiff_t difference_type; + typedef const IfcParse::declaration* value_type; + typedef const IfcParse::declaration*& reference; + typedef const IfcParse::declaration** pointer; + typedef std::forward_iterator_tag iterator_category; +}; +} // namespace std #endif diff --git a/src/ifcparse/IfcGlobalId.cpp b/src/ifcparse/IfcGlobalId.cpp index 4c3d681faf..697dc40363 100644 --- a/src/ifcparse/IfcGlobalId.cpp +++ b/src/ifcparse/IfcGlobalId.cpp @@ -17,124 +17,128 @@ * * ********************************************************************************/ -#include -#include +#include "IfcGlobalId.h" +#include "IfcBaseClass.h" +#include "IfcException.h" +#include "IfcLogger.h" + +#include +#include #include #include #include #include -#include - -#include "../ifcparse/IfcGlobalId.h" -#include "../ifcparse/IfcException.h" -#include "../ifcparse/IfcBaseClass.h" -#include "../ifcparse/IfcLogger.h" +#include static const char* chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_$"; // Converts an unsigned integer into a base64 string of length l std::string base64(unsigned v, int l) { - std::string r; - r.reserve(l); - while ( v ) { - r.push_back(chars[v%64]); - v /= 64; - } - while ( (int)r.size() != l ) r.push_back('0'); - std::reverse(r.begin(),r.end()); - return r; + std::string r; + r.reserve(l); + while (v) { + r.push_back(chars[v % 64]); + v /= 64; + } + while ((int)r.size() != l) { + r.push_back('0'); + } + std::reverse(r.begin(), r.end()); + return r; } // Converts a base64 string into an unsigned integer unsigned from_base64(const std::string& s) { - std::string::size_type zeros = s.find_first_not_of('0'); - unsigned r = 0; - if ( zeros != std::string::npos ) - for ( std::string::const_iterator i = s.begin()+zeros; i != s.end(); ++ i ) { - r *= 64; - const char* c = strchr(chars,*i); - if ( !c ) throw IfcParse::IfcException("Failed to decode GlobalId"); - r += (unsigned)(c-chars); - } - return r; + std::string::size_type zeros = s.find_first_not_of('0'); + unsigned r = 0; + if (zeros != std::string::npos) { + for (std::string::const_iterator i = s.begin() + zeros; i != s.end(); ++i) { + r *= 64; + const char* c = strchr(chars, *i); + if (!c) { + throw IfcParse::IfcException("Failed to decode GlobalId"); + } + r += (unsigned)(c - chars); + } + } + return r; } // Compresses the UUID byte array into a base64 representation std::string compress(unsigned char* v) { - std::string r; - r.reserve(22); - r += base64(v[0],2); - for ( unsigned i = 1; i < 16; i += 3 ) { - r += base64((v[i]<<16) + (v[i+1]<<8) + v[i+2],4); - } - return r; + std::string r; + r.reserve(22); + r += base64(v[0], 2); + for (unsigned i = 1; i < 16; i += 3) { + r += base64((v[i] << 16) + (v[i + 1] << 8) + v[i + 2], 4); + } + return r; } // Expands the base64 representation into a UUID byte array void expand(const std::string& s, std::vector& v) { - v.push_back((unsigned char)from_base64(s.substr(0,2))); - for( unsigned i = 0; i < 5; ++i ) { - unsigned d = from_base64(s.substr(2+4*i,4)); - for ( unsigned j = 0; j < 3; ++ j ) { - v.push_back((d>>(8*(2-j))) % 256); - } - } + v.push_back((unsigned char)from_base64(s.substr(0, 2))); + for (unsigned i = 0; i < 5; ++i) { + unsigned d = from_base64(s.substr(2 + 4 * i, 4)); + for (unsigned j = 0; j < 3; ++j) { + v.push_back((d >> (8 * (2 - j))) % 256); + } + } } // A random number generator for the UUID static boost::uuids::basic_random_generator gen; IfcParse::IfcGlobalId::IfcGlobalId() { - uuid_data = gen(); - std::vector v(uuid_data.size()); - std::copy(uuid_data.begin(), uuid_data.end(), v.begin()); - string_data = compress(&v[0]); + uuid_data = gen(); + std::vector v(uuid_data.size()); + std::copy(uuid_data.begin(), uuid_data.end(), v.begin()); + string_data = compress(&v[0]); #if BOOST_VERSION < 104400 - formatted_string = boost::lexical_cast(uuid_data); + formatted_string = boost::lexical_cast(uuid_data); #else - formatted_string = boost::uuids::to_string(uuid_data); + formatted_string = boost::uuids::to_string(uuid_data); #endif #ifndef NDEBUG - std::vector test_vector; - expand(string_data, test_vector); - boost::uuids::uuid test_uuid; - std::copy(test_vector.begin(), test_vector.end(), test_uuid.begin()); - if (uuid_data != test_uuid) { - Logger::Message(Logger::LOG_ERROR, "Internal error generating GlobalId"); - } + std::vector test_vector; + expand(string_data, test_vector); + boost::uuids::uuid test_uuid; + std::copy(test_vector.begin(), test_vector.end(), test_uuid.begin()); + if (uuid_data != test_uuid) { + Logger::Message(Logger::LOG_ERROR, "Internal error generating GlobalId"); + } #endif } IfcParse::IfcGlobalId::IfcGlobalId(const std::string& s) - : string_data(s) -{ - std::vector v; - expand(string_data, v); - std::copy(v.begin(), v.end(), uuid_data.begin()); + : string_data(s) { + std::vector v; + expand(string_data, v); + std::copy(v.begin(), v.end(), uuid_data.begin()); #if BOOST_VERSION < 104400 - formatted_string = boost::lexical_cast(uuid_data); + formatted_string = boost::lexical_cast(uuid_data); #else - formatted_string = boost::uuids::to_string(uuid_data); + formatted_string = boost::uuids::to_string(uuid_data); #endif #ifndef NDEBUG - const std::string test_string = compress(&uuid_data.data[0]); - if (string_data != test_string) { - Logger::Message(Logger::LOG_ERROR, "Internal error generating GlobalId"); - } + const std::string test_string = compress(&uuid_data.data[0]); + if (string_data != test_string) { + Logger::Message(Logger::LOG_ERROR, "Internal error generating GlobalId"); + } #endif } IfcParse::IfcGlobalId::operator const std::string&() const { - return string_data; + return string_data; } IfcParse::IfcGlobalId::operator const boost::uuids::uuid&() const { - return uuid_data; + return uuid_data; } const std::string& IfcParse::IfcGlobalId::formatted() const { - return formatted_string; + return formatted_string; } diff --git a/src/ifcparse/IfcGlobalId.h b/src/ifcparse/IfcGlobalId.h index 848169a954..33f876e56f 100644 --- a/src/ifcparse/IfcGlobalId.h +++ b/src/ifcparse/IfcGlobalId.h @@ -20,27 +20,28 @@ #ifndef IFCGLOBALID_H #define IFCGLOBALID_H -#include -#include - #include "ifc_parse_api.h" +#include +#include + namespace IfcParse { - /// A helper class for the creation of IFC GlobalIds. - class IFC_PARSE_API IfcGlobalId { - private: - std::string string_data, formatted_string; - boost::uuids::uuid uuid_data; - public: - static const unsigned int length = 22; - IfcGlobalId(); - IfcGlobalId(const std::string&); - operator const std::string&() const; - operator const boost::uuids::uuid&() const; - const std::string& formatted() const; - }; +/// A helper class for the creation of IFC GlobalIds. +class IFC_PARSE_API IfcGlobalId { + private: + std::string string_data, formatted_string; + boost::uuids::uuid uuid_data; -} + public: + static const unsigned int length = 22; + IfcGlobalId(); + IfcGlobalId(const std::string&); + operator const std::string&() const; + operator const boost::uuids::uuid&() const; + const std::string& formatted() const; +}; -#endif \ No newline at end of file +} // namespace IfcParse + +#endif diff --git a/src/ifcparse/IfcHierarchyHelper.cpp b/src/ifcparse/IfcHierarchyHelper.cpp index 5387b90d0c..509bb8cddc 100644 --- a/src/ifcparse/IfcHierarchyHelper.cpp +++ b/src/ifcparse/IfcHierarchyHelper.cpp @@ -25,982 +25,918 @@ * * ********************************************************************************/ -#include +#include "IfcHierarchyHelper.h" -#include "../ifcparse/IfcHierarchyHelper.h" +#include using namespace std::string_literals; template typename Schema::IfcAxis2Placement3D* IfcHierarchyHelper::addPlacement3d( - double ox, double oy, double oz, - double zx, double zy, double zz, - double xx, double xy, double xz) -{ - typename Schema::IfcDirection* x = addTriplet(xx, xy, xz); - typename Schema::IfcDirection* z = addTriplet(zx, zy, zz); - typename Schema::IfcCartesianPoint* o = addTriplet(ox, oy, oz); - typename Schema::IfcAxis2Placement3D* p3d = new typename Schema::IfcAxis2Placement3D(o, z, x); - addEntity(p3d); - return p3d; + double ox, double oy, double oz, double zx, double zy, double zz, double xx, double xy, double xz) { + typename Schema::IfcDirection* x = addTriplet(xx, xy, xz); + typename Schema::IfcDirection* z = addTriplet(zx, zy, zz); + typename Schema::IfcCartesianPoint* o = addTriplet(ox, oy, oz); + typename Schema::IfcAxis2Placement3D* p3d = new typename Schema::IfcAxis2Placement3D(o, z, x); + addEntity(p3d); + return p3d; } template typename Schema::IfcAxis2Placement2D* IfcHierarchyHelper::addPlacement2d( - double ox, double oy, - double xx, double xy) -{ - typename Schema::IfcDirection* x = addDoublet(xx, xy); - typename Schema::IfcCartesianPoint* o = addDoublet(ox, oy); - typename Schema::IfcAxis2Placement2D* p2d = new typename Schema::IfcAxis2Placement2D(o, x); - addEntity(p2d); - return p2d; + double ox, double oy, double xx, double xy) { + typename Schema::IfcDirection* x = addDoublet(xx, xy); + typename Schema::IfcCartesianPoint* o = addDoublet(ox, oy); + typename Schema::IfcAxis2Placement2D* p2d = new typename Schema::IfcAxis2Placement2D(o, x); + addEntity(p2d); + return p2d; } template typename Schema::IfcLocalPlacement* IfcHierarchyHelper::addLocalPlacement(typename Schema::IfcObjectPlacement* parent, - double ox, double oy, double oz, - double zx, double zy, double zz, - double xx, double xy, double xz) -{ - typename Schema::IfcLocalPlacement* lp = new typename Schema::IfcLocalPlacement(parent, - addPlacement3d(ox, oy, oz, zx, zy, zz, xx, xy, xz)); + double ox, + double oy, + double oz, + double zx, + double zy, + double zz, + double xx, + double xy, + double xz) { + typename Schema::IfcLocalPlacement* lp = new typename Schema::IfcLocalPlacement(parent, + addPlacement3d(ox, oy, oz, zx, zy, zz, xx, xy, xz)); - addEntity(lp); - return lp; + addEntity(lp); + return lp; } template typename Schema::IfcOwnerHistory* IfcHierarchyHelper::addOwnerHistory() { - typename Schema::IfcPerson* person = new typename Schema::IfcPerson(boost::none, boost::none, std::string(""), - boost::none, boost::none, boost::none, boost::none, boost::none); + typename Schema::IfcPerson* person = new typename Schema::IfcPerson(boost::none, boost::none, std::string(""), boost::none, boost::none, boost::none, boost::none, boost::none); - typename Schema::IfcOrganization* organization = new typename Schema::IfcOrganization(boost::none, - "IfcOpenShell", boost::none, boost::none, boost::none); + typename Schema::IfcOrganization* organization = new typename Schema::IfcOrganization(boost::none, + "IfcOpenShell", + boost::none, + boost::none, + boost::none); - typename Schema::IfcPersonAndOrganization* person_and_org = new typename Schema::IfcPersonAndOrganization(person, organization, boost::none); - typename Schema::IfcApplication* application = new typename Schema::IfcApplication(organization, - IFCOPENSHELL_VERSION, "IfcOpenShell", "IfcOpenShell"); + typename Schema::IfcPersonAndOrganization* person_and_org = new typename Schema::IfcPersonAndOrganization(person, organization, boost::none); + typename Schema::IfcApplication* application = new typename Schema::IfcApplication(organization, + IFCOPENSHELL_VERSION, + "IfcOpenShell", + "IfcOpenShell"); - int timestamp = (int) time(0); - typename Schema::IfcOwnerHistory* owner_hist = new typename Schema::IfcOwnerHistory(person_and_org, application, - boost::none, Schema::IfcChangeActionEnum::IfcChangeAction_ADDED, timestamp, person_and_org, application, timestamp); + int timestamp = (int)time(0); + typename Schema::IfcOwnerHistory* owner_hist = new typename Schema::IfcOwnerHistory(person_and_org, application, boost::none, Schema::IfcChangeActionEnum::IfcChangeAction_ADDED, timestamp, person_and_org, application, timestamp); - addEntity(person); - addEntity(organization); - addEntity(person_and_org); - addEntity(application); - addEntity(owner_hist); + addEntity(person); + addEntity(organization); + addEntity(person_and_org); + addEntity(application); + addEntity(owner_hist); - return owner_hist; + return owner_hist; } template typename Schema::IfcProject* IfcHierarchyHelper::addProject(typename Schema::IfcOwnerHistory* owner_hist) { - typename Schema::IfcRepresentationContext::list::ptr rep_contexts (new typename Schema::IfcRepresentationContext::list); + typename Schema::IfcRepresentationContext::list::ptr rep_contexts(new typename Schema::IfcRepresentationContext::list); - typename Schema::IfcUnit::list::ptr units (new typename Schema::IfcUnit::list); - typename Schema::IfcDimensionalExponents* dimexp = new typename Schema::IfcDimensionalExponents(0, 0, 0, 0, 0, 0, 0); - typename Schema::IfcSIUnit* unit1 = new typename Schema::IfcSIUnit(Schema::IfcUnitEnum::IfcUnit_LENGTHUNIT, - Schema::IfcSIPrefix::IfcSIPrefix_MILLI, Schema::IfcSIUnitName::IfcSIUnitName_METRE); - typename Schema::IfcSIUnit* unit2a = new typename Schema::IfcSIUnit(Schema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT, - boost::none, Schema::IfcSIUnitName::IfcSIUnitName_RADIAN); - typename Schema::IfcMeasureWithUnit* unit2b = new typename Schema::IfcMeasureWithUnit( - new typename Schema::IfcPlaneAngleMeasure(0.017453293), unit2a); - typename Schema::IfcConversionBasedUnit* unit2 = new typename Schema::IfcConversionBasedUnit(dimexp, - Schema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT, "Degrees", unit2b); + typename Schema::IfcUnit::list::ptr units(new typename Schema::IfcUnit::list); + typename Schema::IfcDimensionalExponents* dimexp = new typename Schema::IfcDimensionalExponents(0, 0, 0, 0, 0, 0, 0); + typename Schema::IfcSIUnit* unit1 = new typename Schema::IfcSIUnit(Schema::IfcUnitEnum::IfcUnit_LENGTHUNIT, + Schema::IfcSIPrefix::IfcSIPrefix_MILLI, + Schema::IfcSIUnitName::IfcSIUnitName_METRE); + typename Schema::IfcSIUnit* unit2a = new typename Schema::IfcSIUnit(Schema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT, + boost::none, + Schema::IfcSIUnitName::IfcSIUnitName_RADIAN); + typename Schema::IfcMeasureWithUnit* unit2b = new typename Schema::IfcMeasureWithUnit( + new typename Schema::IfcPlaneAngleMeasure(0.017453293), unit2a); + typename Schema::IfcConversionBasedUnit* unit2 = new typename Schema::IfcConversionBasedUnit(dimexp, + Schema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT, + "Degrees", + unit2b); - units->push(unit1); - units->push(unit2); + units->push(unit1); + units->push(unit2); - typename Schema::IfcUnitAssignment* unit_assignment = new typename Schema::IfcUnitAssignment(units); + typename Schema::IfcUnitAssignment* unit_assignment = new typename Schema::IfcUnitAssignment(units); - typename Schema::IfcProject* project = new typename Schema::IfcProject(IfcParse::IfcGlobalId(), owner_hist, boost::none, boost::none, - boost::none, boost::none, boost::none, rep_contexts, unit_assignment); + typename Schema::IfcProject* project = new typename Schema::IfcProject(IfcParse::IfcGlobalId(), owner_hist, boost::none, boost::none, boost::none, boost::none, boost::none, rep_contexts, unit_assignment); - addEntity(dimexp); - addEntity(unit1); - addEntity(unit2a); - addEntity(unit2b); - addEntity(unit2); - addEntity(unit_assignment); - addEntity(project); + addEntity(dimexp); + addEntity(unit1); + addEntity(unit2a); + addEntity(unit2b); + addEntity(unit2); + addEntity(unit_assignment); + addEntity(project); - return project; + return project; } template void IfcHierarchyHelper::relatePlacements(typename Schema::IfcProduct* parent, typename Schema::IfcProduct* product) { - typename Schema::IfcObjectPlacement* place = product->ObjectPlacement(); - if (place && place->declaration().is(Schema::IfcLocalPlacement::Class())) { - typename Schema::IfcLocalPlacement* local_place = (typename Schema::IfcLocalPlacement*) place; - if (parent->ObjectPlacement()) { - local_place->setPlacementRelTo(parent->ObjectPlacement()); - } - } + typename Schema::IfcObjectPlacement* place = product->ObjectPlacement(); + if (place && place->declaration().is(Schema::IfcLocalPlacement::Class())) { + typename Schema::IfcLocalPlacement* local_place = (typename Schema::IfcLocalPlacement*)place; + if (parent->ObjectPlacement()) { + local_place->setPlacementRelTo(parent->ObjectPlacement()); + } + } } template typename Schema::IfcSite* IfcHierarchyHelper::addSite(typename Schema::IfcProject* proj, typename Schema::IfcOwnerHistory* owner_hist) { - if (! owner_hist) { - owner_hist = getSingle(); - } - if (! owner_hist) { - owner_hist = addOwnerHistory(); - } - if (! proj) { - proj = getSingle(); - } - if (! proj) { - proj = addProject(owner_hist); - } + if (!owner_hist) { + owner_hist = getSingle(); + } + if (!owner_hist) { + owner_hist = addOwnerHistory(); + } + if (!proj) { + proj = getSingle(); + } + if (!proj) { + proj = addProject(owner_hist); + } - typename Schema::IfcSite* site = new typename Schema::IfcSite(IfcParse::IfcGlobalId(), owner_hist, boost::none, - boost::none, boost::none, addLocalPlacement(), 0, boost::none, - Schema::IfcElementCompositionEnum::IfcElementComposition_ELEMENT, - boost::none, boost::none, boost::none, boost::none, 0); + typename Schema::IfcSite* site = new typename Schema::IfcSite(IfcParse::IfcGlobalId(), owner_hist, boost::none, boost::none, boost::none, addLocalPlacement(), 0, boost::none, Schema::IfcElementCompositionEnum::IfcElementComposition_ELEMENT, boost::none, boost::none, boost::none, boost::none, 0); - addEntity(site); - addRelatedObject(proj, site, owner_hist); - return site; + addEntity(site); + addRelatedObject(proj, site, owner_hist); + return site; } template typename Schema::IfcBuilding* IfcHierarchyHelper::addBuilding(typename Schema::IfcSite* site, typename Schema::IfcOwnerHistory* owner_hist) { - if (! owner_hist) { - owner_hist = getSingle(); - } - if (! owner_hist) { - owner_hist = addOwnerHistory(); - } - if (! site) { - site = getSingle(); - } - if (! site) { - site = addSite(0, owner_hist); - } - typename Schema::IfcBuilding* building = new typename Schema::IfcBuilding(IfcParse::IfcGlobalId(), owner_hist, boost::none, boost::none, boost::none, - addLocalPlacement(), 0, boost::none, Schema::IfcElementCompositionEnum::IfcElementComposition_ELEMENT, - boost::none, boost::none, 0); + if (!owner_hist) { + owner_hist = getSingle(); + } + if (!owner_hist) { + owner_hist = addOwnerHistory(); + } + if (!site) { + site = getSingle(); + } + if (!site) { + site = addSite(0, owner_hist); + } + typename Schema::IfcBuilding* building = new typename Schema::IfcBuilding(IfcParse::IfcGlobalId(), owner_hist, boost::none, boost::none, boost::none, addLocalPlacement(), 0, boost::none, Schema::IfcElementCompositionEnum::IfcElementComposition_ELEMENT, boost::none, boost::none, 0); - addEntity(building); - addRelatedObject(site, building, owner_hist); - relatePlacements(site, building); + addEntity(building); + addRelatedObject(site, building, owner_hist); + relatePlacements(site, building); - return building; + return building; } template -typename Schema::IfcBuildingStorey* IfcHierarchyHelper::addBuildingStorey(typename Schema::IfcBuilding* building, - typename Schema::IfcOwnerHistory* owner_hist) -{ - if (! owner_hist) { - owner_hist = getSingle(); - } - if (! owner_hist) { - owner_hist = addOwnerHistory(); - } - if (! building) { - building = getSingle(); - } - if (! building) { - building = addBuilding(0, owner_hist); - } - typename Schema::IfcBuildingStorey* storey = new typename Schema::IfcBuildingStorey(IfcParse::IfcGlobalId(), - owner_hist, boost::none, boost::none, boost::none, addLocalPlacement(), 0, boost::none, - Schema::IfcElementCompositionEnum::IfcElementComposition_ELEMENT, boost::none); +typename Schema::IfcBuildingStorey* IfcHierarchyHelper::addBuildingStorey(typename Schema::IfcBuilding* building, + typename Schema::IfcOwnerHistory* owner_hist) { + if (!owner_hist) { + owner_hist = getSingle(); + } + if (!owner_hist) { + owner_hist = addOwnerHistory(); + } + if (!building) { + building = getSingle(); + } + if (!building) { + building = addBuilding(0, owner_hist); + } + typename Schema::IfcBuildingStorey* storey = new typename Schema::IfcBuildingStorey(IfcParse::IfcGlobalId(), + owner_hist, + boost::none, + boost::none, + boost::none, + addLocalPlacement(), + 0, + boost::none, + Schema::IfcElementCompositionEnum::IfcElementComposition_ELEMENT, + boost::none); - addEntity(storey); - addRelatedObject(building, storey, owner_hist); - relatePlacements(building, storey); + addEntity(storey); + addRelatedObject(building, storey, owner_hist); + relatePlacements(building, storey); - return storey; + return storey; } template -typename Schema::IfcBuildingStorey* IfcHierarchyHelper::addBuildingProduct(typename Schema::IfcProduct* product, - typename Schema::IfcBuildingStorey* storey, typename Schema::IfcOwnerHistory* owner_hist) -{ - if (! owner_hist) { - owner_hist = getSingle(); - } - if (! owner_hist) { - owner_hist = addOwnerHistory(); - } - if (! storey) { - storey = getSingle(); - } - if (! storey) { - storey = addBuildingStorey(0, owner_hist); - } - addEntity(product); +typename Schema::IfcBuildingStorey* IfcHierarchyHelper::addBuildingProduct(typename Schema::IfcProduct* product, + typename Schema::IfcBuildingStorey* storey, + typename Schema::IfcOwnerHistory* owner_hist) { + if (!owner_hist) { + owner_hist = getSingle(); + } + if (!owner_hist) { + owner_hist = addOwnerHistory(); + } + if (!storey) { + storey = getSingle(); + } + if (!storey) { + storey = addBuildingStorey(0, owner_hist); + } + addEntity(product); - // CV-2x3-158: Don't add decompositions directly to a building storey - const bool is_decomposition = product->Decomposes()->size() > 0; + // CV-2x3-158: Don't add decompositions directly to a building storey + const bool is_decomposition = product->Decomposes()->size() > 0; - if (!is_decomposition) { - addRelatedObject(storey, product, owner_hist); - relatePlacements(storey, product); - } - return storey; + if (!is_decomposition) { + addRelatedObject(storey, product, owner_hist); + relatePlacements(storey, product); + } + return storey; } template -void IfcHierarchyHelper::addExtrudedPolyline(typename Schema::IfcShapeRepresentation* rep, const std::vector >& points, double h, - typename Schema::IfcAxis2Placement2D* /*place*/, typename Schema::IfcAxis2Placement3D* place2, - typename Schema::IfcDirection* dir, typename Schema::IfcRepresentationContext* /*context*/) -{ - typename Schema::IfcCartesianPoint::list::ptr cartesian_points (new typename Schema::IfcCartesianPoint::list); - for (std::vector >::const_iterator i = points.begin(); i != points.end(); ++i) { - cartesian_points->push(addDoublet(i->first, i->second)); - } - if (cartesian_points->size()) cartesian_points->push(*cartesian_points->begin()); - typename Schema::IfcPolyline* line = new typename Schema::IfcPolyline(cartesian_points); - typename Schema::IfcArbitraryClosedProfileDef* profile = new typename Schema::IfcArbitraryClosedProfileDef( - Schema::IfcProfileTypeEnum::IfcProfileType_AREA, boost::none, line); +void IfcHierarchyHelper::addExtrudedPolyline(typename Schema::IfcShapeRepresentation* rep, const std::vector>& points, double h, typename Schema::IfcAxis2Placement2D* /*place*/, typename Schema::IfcAxis2Placement3D* place2, typename Schema::IfcDirection* dir, typename Schema::IfcRepresentationContext* /*context*/) { + typename Schema::IfcCartesianPoint::list::ptr cartesian_points(new typename Schema::IfcCartesianPoint::list); + for (std::vector>::const_iterator i = points.begin(); i != points.end(); ++i) { + cartesian_points->push(addDoublet(i->first, i->second)); + } + if (cartesian_points->size()) { + cartesian_points->push(*cartesian_points->begin()); + } + typename Schema::IfcPolyline* line = new typename Schema::IfcPolyline(cartesian_points); + typename Schema::IfcArbitraryClosedProfileDef* profile = new typename Schema::IfcArbitraryClosedProfileDef( + Schema::IfcProfileTypeEnum::IfcProfileType_AREA, boost::none, line); - typename Schema::IfcExtrudedAreaSolid* solid = new typename Schema::IfcExtrudedAreaSolid( - profile, place2 ? place2 : addPlacement3d(), dir ? dir : addTriplet(0, 0, 1), h); + typename Schema::IfcExtrudedAreaSolid* solid = new typename Schema::IfcExtrudedAreaSolid( + profile, place2 ? place2 : addPlacement3d(), dir ? dir : addTriplet(0, 0, 1), h); - typename Schema::IfcRepresentationItem::list::ptr items = rep->Items(); - items->push(solid); - rep->setItems(items); + typename Schema::IfcRepresentationItem::list::ptr items = rep->Items(); + items->push(solid); + rep->setItems(items); - addEntity(line); - addEntity(profile); - addEntity(solid); + addEntity(line); + addEntity(profile); + addEntity(solid); } template -typename Schema::IfcProductDefinitionShape* IfcHierarchyHelper::addExtrudedPolyline(const std::vector >& points, double h, - typename Schema::IfcAxis2Placement2D* place, typename Schema::IfcAxis2Placement3D* place2, typename Schema::IfcDirection* dir, - typename Schema::IfcRepresentationContext* context) -{ - typename Schema::IfcRepresentation::list::ptr reps (new typename Schema::IfcRepresentation::list); - typename Schema::IfcRepresentationItem::list::ptr items (new typename Schema::IfcRepresentationItem::list); - typename Schema::IfcShapeRepresentation* rep = new typename Schema::IfcShapeRepresentation(context - ? context - : getRepresentationContext("Model"), std::string("Body"), std::string("SweptSolid"), items); - reps->push(rep); - typename Schema::IfcProductDefinitionShape* shape = new typename Schema::IfcProductDefinitionShape(boost::none, boost::none, reps); - addEntity(rep); - addEntity(shape); - addExtrudedPolyline(rep, points, h, place, place2, dir, context); +typename Schema::IfcProductDefinitionShape* IfcHierarchyHelper::addExtrudedPolyline(const std::vector>& points, double h, typename Schema::IfcAxis2Placement2D* place, typename Schema::IfcAxis2Placement3D* place2, typename Schema::IfcDirection* dir, typename Schema::IfcRepresentationContext* context) { + typename Schema::IfcRepresentation::list::ptr reps(new typename Schema::IfcRepresentation::list); + typename Schema::IfcRepresentationItem::list::ptr items(new typename Schema::IfcRepresentationItem::list); + typename Schema::IfcShapeRepresentation* rep = new typename Schema::IfcShapeRepresentation(context + ? context + : getRepresentationContext("Model"), + std::string("Body"), + std::string("SweptSolid"), + items); + reps->push(rep); + typename Schema::IfcProductDefinitionShape* shape = new typename Schema::IfcProductDefinitionShape(boost::none, boost::none, reps); + addEntity(rep); + addEntity(shape); + addExtrudedPolyline(rep, points, h, place, place2, dir, context); - return shape; + return shape; } template -void IfcHierarchyHelper::addBox(typename Schema::IfcShapeRepresentation* rep, double w, double d, double h, - typename Schema::IfcAxis2Placement2D* place, typename Schema::IfcAxis2Placement3D* place2, - typename Schema::IfcDirection* dir, typename Schema::IfcRepresentationContext* context) -{ - if (false) { // TODO What's this? - typename Schema::IfcRectangleProfileDef* profile = new typename Schema::IfcRectangleProfileDef( - Schema::IfcProfileTypeEnum::IfcProfileType_AREA, boost::none, place ? place : addPlacement2d(), w, d); - typename Schema::IfcExtrudedAreaSolid* solid = new typename Schema::IfcExtrudedAreaSolid(profile, - place2 ? place2 : addPlacement3d(), dir ? dir : addTriplet(0, 0, 1), h); +void IfcHierarchyHelper::addBox(typename Schema::IfcShapeRepresentation* rep, double w, double d, double h, typename Schema::IfcAxis2Placement2D* place, typename Schema::IfcAxis2Placement3D* place2, typename Schema::IfcDirection* dir, typename Schema::IfcRepresentationContext* context) { + if (false) { // TODO What's this? + typename Schema::IfcRectangleProfileDef* profile = new typename Schema::IfcRectangleProfileDef( + Schema::IfcProfileTypeEnum::IfcProfileType_AREA, boost::none, place ? place : addPlacement2d(), w, d); + typename Schema::IfcExtrudedAreaSolid* solid = new typename Schema::IfcExtrudedAreaSolid(profile, + place2 ? place2 : addPlacement3d(), + dir ? dir : addTriplet(0, 0, 1), + h); - addEntity(profile); - addEntity(solid); - typename Schema::IfcRepresentationItem::list::ptr items = rep->Items(); - items->push(solid); - rep->setItems(items); - } else { - std::vector > points; - points.push_back(std::make_pair(-w/2, -d/2)); - points.push_back(std::make_pair(w/2, -d/2)); - points.push_back(std::make_pair(w/2, d/2)); - points.push_back(std::make_pair(-w/2, d/2)); - // The call to addExtrudedPolyline() closes the polyline - addExtrudedPolyline(rep, points, h, place, place2, dir, context); - } + addEntity(profile); + addEntity(solid); + typename Schema::IfcRepresentationItem::list::ptr items = rep->Items(); + items->push(solid); + rep->setItems(items); + } else { + std::vector> points; + points.push_back(std::make_pair(-w / 2, -d / 2)); + points.push_back(std::make_pair(w / 2, -d / 2)); + points.push_back(std::make_pair(w / 2, d / 2)); + points.push_back(std::make_pair(-w / 2, d / 2)); + // The call to addExtrudedPolyline() closes the polyline + addExtrudedPolyline(rep, points, h, place, place2, dir, context); + } } template void IfcHierarchyHelper::addAxis(typename Schema::IfcShapeRepresentation* rep, double l, typename Schema::IfcRepresentationContext* /*context*/) { - typename Schema::IfcCartesianPoint* p1 = addDoublet(-l / 2., 0.); - typename Schema::IfcCartesianPoint* p2 = addDoublet(+l / 2., 0.); - typename Schema::IfcCartesianPoint::list::ptr pts(new typename Schema::IfcCartesianPoint::list); - pts->push(p1); pts->push(p2); - typename Schema::IfcPolyline* poly = new typename Schema::IfcPolyline(pts); - addEntity(poly); - - typename Schema::IfcRepresentationItem::list::ptr items = rep->Items(); - items->push(poly); - rep->setItems(items); + typename Schema::IfcCartesianPoint* p1 = addDoublet(-l / 2., 0.); + typename Schema::IfcCartesianPoint* p2 = addDoublet(+l / 2., 0.); + typename Schema::IfcCartesianPoint::list::ptr pts(new typename Schema::IfcCartesianPoint::list); + pts->push(p1); + pts->push(p2); + typename Schema::IfcPolyline* poly = new typename Schema::IfcPolyline(pts); + addEntity(poly); + + typename Schema::IfcRepresentationItem::list::ptr items = rep->Items(); + items->push(poly); + rep->setItems(items); } template -typename Schema::IfcProductDefinitionShape* IfcHierarchyHelper::addBox(double w, double d, double h, typename Schema::IfcAxis2Placement2D* place, - typename Schema::IfcAxis2Placement3D* place2, typename Schema::IfcDirection* dir, typename Schema::IfcRepresentationContext* context) -{ - typename Schema::IfcRepresentation::list::ptr reps (new typename Schema::IfcRepresentation::list); - typename Schema::IfcRepresentationItem::list::ptr items (new typename Schema::IfcRepresentationItem::list); - typename Schema::IfcShapeRepresentation* rep = new typename Schema::IfcShapeRepresentation( - context ? context : getRepresentationContext("Model"), std::string("Body"), std::string("SweptSolid"), items); - reps->push(rep); - typename Schema::IfcProductDefinitionShape* shape = new typename Schema::IfcProductDefinitionShape(boost::none, boost::none, reps); - addEntity(rep); - addEntity(shape); - addBox(rep, w, d, h, place, place2, dir, context); - return shape; +typename Schema::IfcProductDefinitionShape* IfcHierarchyHelper::addBox(double w, double d, double h, typename Schema::IfcAxis2Placement2D* place, typename Schema::IfcAxis2Placement3D* place2, typename Schema::IfcDirection* dir, typename Schema::IfcRepresentationContext* context) { + typename Schema::IfcRepresentation::list::ptr reps(new typename Schema::IfcRepresentation::list); + typename Schema::IfcRepresentationItem::list::ptr items(new typename Schema::IfcRepresentationItem::list); + typename Schema::IfcShapeRepresentation* rep = new typename Schema::IfcShapeRepresentation( + context ? context : getRepresentationContext("Model"), std::string("Body"), std::string("SweptSolid"), items); + reps->push(rep); + typename Schema::IfcProductDefinitionShape* shape = new typename Schema::IfcProductDefinitionShape(boost::none, boost::none, reps); + addEntity(rep); + addEntity(shape); + addBox(rep, w, d, h, place, place2, dir, context); + return shape; } template -typename Schema::IfcProductDefinitionShape* IfcHierarchyHelper::addAxisBox(double w, double d, double h, typename Schema::IfcRepresentationContext* context) -{ - typename Schema::IfcRepresentation::list::ptr reps(new typename Schema::IfcRepresentation::list); - typename Schema::IfcRepresentationItem::list::ptr body_items(new typename Schema::IfcRepresentationItem::list); - typename Schema::IfcRepresentationItem::list::ptr axis_items(new typename Schema::IfcRepresentationItem::list); - typename Schema::IfcShapeRepresentation* body_rep = new typename Schema::IfcShapeRepresentation( - context ? context : getRepresentationContext("Model"), std::string("Body"), std::string("SweptSolid"), body_items); +typename Schema::IfcProductDefinitionShape* IfcHierarchyHelper::addAxisBox(double w, double d, double h, typename Schema::IfcRepresentationContext* context) { + typename Schema::IfcRepresentation::list::ptr reps(new typename Schema::IfcRepresentation::list); + typename Schema::IfcRepresentationItem::list::ptr body_items(new typename Schema::IfcRepresentationItem::list); + typename Schema::IfcRepresentationItem::list::ptr axis_items(new typename Schema::IfcRepresentationItem::list); + typename Schema::IfcShapeRepresentation* body_rep = new typename Schema::IfcShapeRepresentation( + context ? context : getRepresentationContext("Model"), std::string("Body"), std::string("SweptSolid"), body_items); - typename Schema::IfcShapeRepresentation* axis_rep = new typename Schema::IfcShapeRepresentation( - context ? context : getRepresentationContext("Plan"), std::string("Axis"), std::string("Curve2D"), axis_items); + typename Schema::IfcShapeRepresentation* axis_rep = new typename Schema::IfcShapeRepresentation( + context ? context : getRepresentationContext("Plan"), std::string("Axis"), std::string("Curve2D"), axis_items); - reps->push(axis_rep); - reps->push(body_rep); + reps->push(axis_rep); + reps->push(body_rep); - typename Schema::IfcProductDefinitionShape* shape = new typename Schema::IfcProductDefinitionShape(boost::none, boost::none, reps); - addEntity(shape); - addEntity(body_rep); - addBox(body_rep, w, d, h, 0, 0, 0, context); - addEntity(axis_rep); - addAxis(axis_rep, w); - - return shape; + typename Schema::IfcProductDefinitionShape* shape = new typename Schema::IfcProductDefinitionShape(boost::none, boost::none, reps); + addEntity(shape); + addEntity(body_rep); + addBox(body_rep, w, d, h, 0, 0, 0, context); + addEntity(axis_rep); + addAxis(axis_rep, w); + + return shape; } template -void IfcHierarchyHelper::clipRepresentation(typename Schema::IfcProductRepresentation* shape, - typename Schema::IfcAxis2Placement3D* place, bool agree) -{ - typename Schema::IfcRepresentation::list::ptr reps = shape->Representations(); - for (typename Schema::IfcRepresentation::list::it j = reps->begin(); j != reps->end(); ++j) { - clipRepresentation(*j, place, agree); - } +void IfcHierarchyHelper::clipRepresentation(typename Schema::IfcProductRepresentation* shape, + typename Schema::IfcAxis2Placement3D* place, + bool agree) { + typename Schema::IfcRepresentation::list::ptr reps = shape->Representations(); + for (typename Schema::IfcRepresentation::list::it j = reps->begin(); j != reps->end(); ++j) { + clipRepresentation(*j, place, agree); + } } template -void IfcHierarchyHelper::clipRepresentation(typename Schema::IfcRepresentation* rep, - typename Schema::IfcAxis2Placement3D* place, bool agree) -{ - if (!rep->RepresentationIdentifier() || *rep->RepresentationIdentifier() != "Body") return; - typename Schema::IfcPlane* plane = new typename Schema::IfcPlane(place); - typename Schema::IfcHalfSpaceSolid* half_space = new typename Schema::IfcHalfSpaceSolid(plane, agree); - addEntity(plane); - addEntity(half_space); - rep->setRepresentationType("Clipping"s); - typename Schema::IfcRepresentationItem::list::ptr items = rep->Items(); - typename Schema::IfcRepresentationItem::list::ptr new_items (new typename Schema::IfcRepresentationItem::list); - for (typename Schema::IfcRepresentationItem::list::it i = items->begin(); i != items->end(); ++i) { - auto item = dynamic_cast(*i); - if (item) { - typename Schema::IfcBooleanClippingResult* clip = new typename Schema::IfcBooleanClippingResult( - Schema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE, item, half_space); - addEntity(clip); - new_items->push(clip); - } - } - rep->setItems(new_items); +void IfcHierarchyHelper::clipRepresentation(typename Schema::IfcRepresentation* rep, + typename Schema::IfcAxis2Placement3D* place, + bool agree) { + if (!rep->RepresentationIdentifier() || *rep->RepresentationIdentifier() != "Body") { + return; + } + typename Schema::IfcPlane* plane = new typename Schema::IfcPlane(place); + typename Schema::IfcHalfSpaceSolid* half_space = new typename Schema::IfcHalfSpaceSolid(plane, agree); + addEntity(plane); + addEntity(half_space); + rep->setRepresentationType("Clipping"s); + typename Schema::IfcRepresentationItem::list::ptr items = rep->Items(); + typename Schema::IfcRepresentationItem::list::ptr new_items(new typename Schema::IfcRepresentationItem::list); + for (typename Schema::IfcRepresentationItem::list::it i = items->begin(); i != items->end(); ++i) { + auto item = dynamic_cast(*i); + if (item) { + typename Schema::IfcBooleanClippingResult* clip = new typename Schema::IfcBooleanClippingResult( + Schema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE, item, half_space); + addEntity(clip); + new_items->push(clip); + } + } + rep->setItems(new_items); } template -typename Schema::IfcSurfaceStyle* getSurfaceStyle(IfcHierarchyHelper& file, double r, double g, double b, double a = 1.0) -{ - typename Schema::IfcColourRgb* colour = new typename Schema::IfcColourRgb(boost::none, r, g, b); - typename Schema::IfcSurfaceStyleRendering* rendering = a == 1.0 - ? new typename Schema::IfcSurfaceStyleRendering(colour, boost::none, 0, 0, 0, 0, - 0, 0, Schema::IfcReflectanceMethodEnum::IfcReflectanceMethod_FLAT) - : new typename Schema::IfcSurfaceStyleRendering(colour, 1.0 - a, 0, 0, 0, 0, - 0, 0, Schema::IfcReflectanceMethodEnum::IfcReflectanceMethod_FLAT); +typename Schema::IfcSurfaceStyle* getSurfaceStyle(IfcHierarchyHelper& file, double r, double g, double b, double a = 1.0) { + typename Schema::IfcColourRgb* colour = new typename Schema::IfcColourRgb(boost::none, r, g, b); + typename Schema::IfcSurfaceStyleRendering* rendering = a == 1.0 + ? new typename Schema::IfcSurfaceStyleRendering(colour, boost::none, 0, 0, 0, 0, 0, 0, Schema::IfcReflectanceMethodEnum::IfcReflectanceMethod_FLAT) + : new typename Schema::IfcSurfaceStyleRendering(colour, 1.0 - a, 0, 0, 0, 0, 0, 0, Schema::IfcReflectanceMethodEnum::IfcReflectanceMethod_FLAT); - typename Schema::IfcSurfaceStyleElementSelect::list::ptr styles(new typename Schema::IfcSurfaceStyleElementSelect::list); - styles->push(rendering); - typename Schema::IfcSurfaceStyle* surface_style = new typename Schema::IfcSurfaceStyle( - boost::none, Schema::IfcSurfaceSide::IfcSurfaceSide_BOTH, styles); + typename Schema::IfcSurfaceStyleElementSelect::list::ptr styles(new typename Schema::IfcSurfaceStyleElementSelect::list); + styles->push(rendering); + typename Schema::IfcSurfaceStyle* surface_style = new typename Schema::IfcSurfaceStyle( + boost::none, Schema::IfcSurfaceSide::IfcSurfaceSide_BOTH, styles); - file.addEntity(colour); - file.addEntity(rendering); - file.addEntity(surface_style); + file.addEntity(colour); + file.addEntity(rendering); + file.addEntity(surface_style); - return surface_style; -} - -template -typename Schema::IfcPresentationStyleAssignment* addStyleAssignment_2x3(IfcHierarchyHelper& file, double r, double g, double b, double a = 1.0) -{ - auto surface_style = getSurfaceStyle(file, r, g, b, a); - typename Schema::IfcPresentationStyleSelect::list::ptr surface_styles(new typename Schema::IfcPresentationStyleSelect::list); - surface_styles->push(surface_style); - typename Schema::IfcPresentationStyleAssignment* style_assignment = - new typename Schema::IfcPresentationStyleAssignment(surface_styles); - file.addEntity(style_assignment); - return style_assignment; -} - -template -typename Schema::IfcPresentationStyle* addStyleAssignment_4x3(IfcHierarchyHelper& file, double r, double g, double b, double a = 1.0) -{ - return getSurfaceStyle(file, r, g, b, a); + return surface_style; } template -typename Schema::IfcPresentationStyleAssignment* setSurfaceColour_2x3(IfcHierarchyHelper& file, typename Schema::IfcProductRepresentation* shape, double r, double g, double b, double a) -{ - typename Schema::IfcPresentationStyleAssignment* style_assignment = addStyleAssignment_2x3(file, r, g, b, a); - setSurfaceColour_2x3(file, shape, style_assignment); - return style_assignment; +typename Schema::IfcPresentationStyleAssignment* addStyleAssignment_2x3(IfcHierarchyHelper& file, double r, double g, double b, double a = 1.0) { + auto surface_style = getSurfaceStyle(file, r, g, b, a); + typename Schema::IfcPresentationStyleSelect::list::ptr surface_styles(new typename Schema::IfcPresentationStyleSelect::list); + surface_styles->push(surface_style); + typename Schema::IfcPresentationStyleAssignment* style_assignment = + new typename Schema::IfcPresentationStyleAssignment(surface_styles); + file.addEntity(style_assignment); + return style_assignment; } template -typename Schema::IfcPresentationStyle* setSurfaceColour_4x3(IfcHierarchyHelper& file, typename Schema::IfcProductRepresentation* shape, double r, double g, double b, double a) -{ - typename Schema::IfcPresentationStyle* style_assignment = addStyleAssignment_4x3(file, r, g, b, a); - setSurfaceColour_4x3(file, shape, style_assignment); - return style_assignment; +typename Schema::IfcPresentationStyle* addStyleAssignment_4x3(IfcHierarchyHelper& file, double r, double g, double b, double a = 1.0) { + return getSurfaceStyle(file, r, g, b, a); } template -typename Schema::IfcPresentationStyleAssignment* setSurfaceColour_2x3(IfcHierarchyHelper& file, typename Schema::IfcRepresentation* shape, double r, double g, double b, double a) -{ - typename Schema::IfcPresentationStyleAssignment* style_assignment = addStyleAssignment_2x3(file, r, g, b, a); - setSurfaceColour_2x3(file, shape, style_assignment); - return style_assignment; +typename Schema::IfcPresentationStyleAssignment* setSurfaceColour_2x3(IfcHierarchyHelper& file, typename Schema::IfcProductRepresentation* shape, double r, double g, double b, double a) { + typename Schema::IfcPresentationStyleAssignment* style_assignment = addStyleAssignment_2x3(file, r, g, b, a); + setSurfaceColour_2x3(file, shape, style_assignment); + return style_assignment; } template -typename Schema::IfcPresentationStyle* setSurfaceColour_4x3(IfcHierarchyHelper& file, typename Schema::IfcRepresentation* shape, double r, double g, double b, double a) -{ - typename Schema::IfcPresentationStyle* style_assignment = addStyleAssignment_4x3(file, r, g, b, a); - setSurfaceColour_4x3(file, shape, style_assignment); - return style_assignment; +typename Schema::IfcPresentationStyle* setSurfaceColour_4x3(IfcHierarchyHelper& file, typename Schema::IfcProductRepresentation* shape, double r, double g, double b, double a) { + typename Schema::IfcPresentationStyle* style_assignment = addStyleAssignment_4x3(file, r, g, b, a); + setSurfaceColour_4x3(file, shape, style_assignment); + return style_assignment; } template -void setSurfaceColour_2x3(IfcHierarchyHelper& file, typename Schema::IfcProductRepresentation* shape, typename Schema::IfcPresentationStyleAssignment* style_assignment) -{ - typename Schema::IfcRepresentation::list::ptr reps = shape->Representations(); - for (typename Schema::IfcRepresentation::list::it j = reps->begin(); j != reps->end(); ++j) { - setSurfaceColour_2x3(file, *j, style_assignment); - } +typename Schema::IfcPresentationStyleAssignment* setSurfaceColour_2x3(IfcHierarchyHelper& file, typename Schema::IfcRepresentation* shape, double r, double g, double b, double a) { + typename Schema::IfcPresentationStyleAssignment* style_assignment = addStyleAssignment_2x3(file, r, g, b, a); + setSurfaceColour_2x3(file, shape, style_assignment); + return style_assignment; } template -void setSurfaceColour_4x3(IfcHierarchyHelper& file, typename Schema::IfcProductRepresentation* shape, typename Schema::IfcPresentationStyle* style) -{ - typename Schema::IfcRepresentation::list::ptr reps = shape->Representations(); - for (typename Schema::IfcRepresentation::list::it j = reps->begin(); j != reps->end(); ++j) { - setSurfaceColour_4x3(file, *j, style); - } +typename Schema::IfcPresentationStyle* setSurfaceColour_4x3(IfcHierarchyHelper& file, typename Schema::IfcRepresentation* shape, double r, double g, double b, double a) { + typename Schema::IfcPresentationStyle* style_assignment = addStyleAssignment_4x3(file, r, g, b, a); + setSurfaceColour_4x3(file, shape, style_assignment); + return style_assignment; +} + +template +void setSurfaceColour_2x3(IfcHierarchyHelper& file, typename Schema::IfcProductRepresentation* shape, typename Schema::IfcPresentationStyleAssignment* style_assignment) { + typename Schema::IfcRepresentation::list::ptr reps = shape->Representations(); + for (typename Schema::IfcRepresentation::list::it j = reps->begin(); j != reps->end(); ++j) { + setSurfaceColour_2x3(file, *j, style_assignment); + } +} + +template +void setSurfaceColour_4x3(IfcHierarchyHelper& file, typename Schema::IfcProductRepresentation* shape, typename Schema::IfcPresentationStyle* style) { + typename Schema::IfcRepresentation::list::ptr reps = shape->Representations(); + for (typename Schema::IfcRepresentation::list::it j = reps->begin(); j != reps->end(); ++j) { + setSurfaceColour_4x3(file, *j, style); + } } #ifdef HAS_SCHEMA_2x3 Ifc2x3::IfcStyledItem* create_styled_item(Ifc2x3::IfcRepresentationItem* item, Ifc2x3::IfcPresentationStyleAssignment* style_assignment) { - Ifc2x3::IfcPresentationStyleAssignment::list::ptr style_assignments(new Ifc2x3::IfcPresentationStyleAssignment::list); - style_assignments->push(style_assignment); - return new Ifc2x3::IfcStyledItem(item, style_assignments, boost::none); + Ifc2x3::IfcPresentationStyleAssignment::list::ptr style_assignments(new Ifc2x3::IfcPresentationStyleAssignment::list); + style_assignments->push(style_assignment); + return new Ifc2x3::IfcStyledItem(item, style_assignments, boost::none); } #endif #ifdef HAS_SCHEMA_4 Ifc4::IfcStyledItem* create_styled_item(Ifc4::IfcRepresentationItem* item, Ifc4::IfcPresentationStyleAssignment* style_assignment) { - Ifc4::IfcStyleAssignmentSelect::list::ptr style_assignments(new Ifc4::IfcStyleAssignmentSelect::list); - style_assignments->push(style_assignment); - return new Ifc4::IfcStyledItem(item, style_assignments, boost::none); + Ifc4::IfcStyleAssignmentSelect::list::ptr style_assignments(new Ifc4::IfcStyleAssignmentSelect::list); + style_assignments->push(style_assignment); + return new Ifc4::IfcStyledItem(item, style_assignments, boost::none); } #endif #ifdef HAS_SCHEMA_4x1 Ifc4x1::IfcStyledItem* create_styled_item(Ifc4x1::IfcRepresentationItem* item, Ifc4x1::IfcPresentationStyleAssignment* style_assignment) { - Ifc4x1::IfcStyleAssignmentSelect::list::ptr style_assignments(new Ifc4x1::IfcStyleAssignmentSelect::list); - style_assignments->push(style_assignment); - return new Ifc4x1::IfcStyledItem(item, style_assignments, boost::none); + Ifc4x1::IfcStyleAssignmentSelect::list::ptr style_assignments(new Ifc4x1::IfcStyleAssignmentSelect::list); + style_assignments->push(style_assignment); + return new Ifc4x1::IfcStyledItem(item, style_assignments, boost::none); } #endif #ifdef HAS_SCHEMA_4x2 Ifc4x2::IfcStyledItem* create_styled_item(Ifc4x2::IfcRepresentationItem* item, Ifc4x2::IfcPresentationStyleAssignment* style_assignment) { - Ifc4x2::IfcStyleAssignmentSelect::list::ptr style_assignments(new Ifc4x2::IfcStyleAssignmentSelect::list); - style_assignments->push(style_assignment); - return new Ifc4x2::IfcStyledItem(item, style_assignments, boost::none); + Ifc4x2::IfcStyleAssignmentSelect::list::ptr style_assignments(new Ifc4x2::IfcStyleAssignmentSelect::list); + style_assignments->push(style_assignment); + return new Ifc4x2::IfcStyledItem(item, style_assignments, boost::none); } #endif #ifdef HAS_SCHEMA_4x3_rc1 Ifc4x3_rc1::IfcStyledItem* create_styled_item(Ifc4x3_rc1::IfcRepresentationItem* item, Ifc4x3_rc1::IfcPresentationStyleAssignment* style_assignment) { - Ifc4x3_rc1::IfcStyleAssignmentSelect::list::ptr style_assignments(new Ifc4x3_rc1::IfcStyleAssignmentSelect::list); - style_assignments->push(style_assignment); - return new Ifc4x3_rc1::IfcStyledItem(item, style_assignments, boost::none); + Ifc4x3_rc1::IfcStyleAssignmentSelect::list::ptr style_assignments(new Ifc4x3_rc1::IfcStyleAssignmentSelect::list); + style_assignments->push(style_assignment); + return new Ifc4x3_rc1::IfcStyledItem(item, style_assignments, boost::none); } #endif #ifdef HAS_SCHEMA_4x3_rc2 Ifc4x3_rc2::IfcStyledItem* create_styled_item(Ifc4x3_rc2::IfcRepresentationItem* item, Ifc4x3_rc2::IfcPresentationStyleAssignment* style_assignment) { - Ifc4x3_rc2::IfcStyleAssignmentSelect::list::ptr style_assignments(new Ifc4x3_rc2::IfcStyleAssignmentSelect::list); - style_assignments->push(style_assignment); - return new Ifc4x3_rc2::IfcStyledItem(item, style_assignments, boost::none); + Ifc4x3_rc2::IfcStyleAssignmentSelect::list::ptr style_assignments(new Ifc4x3_rc2::IfcStyleAssignmentSelect::list); + style_assignments->push(style_assignment); + return new Ifc4x3_rc2::IfcStyledItem(item, style_assignments, boost::none); } #endif #ifdef HAS_SCHEMA_4x3_rc3 Ifc4x3_rc3::IfcStyledItem* create_styled_item(Ifc4x3_rc3::IfcRepresentationItem* item, Ifc4x3_rc3::IfcPresentationStyle* style) { - boost::shared_ptr> styles(new aggregate_of()); - styles->push(style); - return new Ifc4x3_rc3::IfcStyledItem(item, styles, boost::none); + boost::shared_ptr> styles(new aggregate_of()); + styles->push(style); + return new Ifc4x3_rc3::IfcStyledItem(item, styles, boost::none); } #endif #ifdef HAS_SCHEMA_4x3_rc4 Ifc4x3_rc4::IfcStyledItem* create_styled_item(Ifc4x3_rc4::IfcRepresentationItem* item, Ifc4x3_rc4::IfcPresentationStyle* style) { - boost::shared_ptr> styles(new aggregate_of()); - styles->push(style); - return new Ifc4x3_rc4::IfcStyledItem(item, styles, boost::none); + boost::shared_ptr> styles(new aggregate_of()); + styles->push(style); + return new Ifc4x3_rc4::IfcStyledItem(item, styles, boost::none); } #endif #ifdef HAS_SCHEMA_4x3 Ifc4x3::IfcStyledItem* create_styled_item(Ifc4x3::IfcRepresentationItem* item, Ifc4x3::IfcPresentationStyle* style) { - boost::shared_ptr> styles(new aggregate_of()); - styles->push(style); - return new Ifc4x3::IfcStyledItem(item, styles, boost::none); + boost::shared_ptr> styles(new aggregate_of()); + styles->push(style); + return new Ifc4x3::IfcStyledItem(item, styles, boost::none); } #endif #ifdef HAS_SCHEMA_4x3_tc1 Ifc4x3_tc1::IfcStyledItem* create_styled_item(Ifc4x3_tc1::IfcRepresentationItem* item, Ifc4x3_tc1::IfcPresentationStyle* style) { - boost::shared_ptr> styles(new aggregate_of()); - styles->push(style); - return new Ifc4x3_tc1::IfcStyledItem(item, styles, boost::none); + boost::shared_ptr> styles(new aggregate_of()); + styles->push(style); + return new Ifc4x3_tc1::IfcStyledItem(item, styles, boost::none); } #endif #ifdef HAS_SCHEMA_4x3_add1 Ifc4x3_add1::IfcStyledItem* create_styled_item(Ifc4x3_add1::IfcRepresentationItem* item, Ifc4x3_add1::IfcPresentationStyle* style) { - boost::shared_ptr> styles(new aggregate_of()); - styles->push(style); - return new Ifc4x3_add1::IfcStyledItem(item, styles, boost::none); + boost::shared_ptr> styles(new aggregate_of()); + styles->push(style); + return new Ifc4x3_add1::IfcStyledItem(item, styles, boost::none); } #endif template -void setSurfaceColour_2x3(IfcHierarchyHelper& file, typename Schema::IfcRepresentation* rep, typename Schema::IfcPresentationStyleAssignment* style_assignment) -{ - typename Schema::IfcRepresentationItem::list::ptr items = rep->Items(); - for (typename Schema::IfcRepresentationItem::list::it i = items->begin(); i != items->end(); ++i) { - typename Schema::IfcRepresentationItem* item = *i; - typename Schema::IfcStyledItem* styled_item = create_styled_item(item, style_assignment); - file.addEntity(styled_item); - } +void setSurfaceColour_2x3(IfcHierarchyHelper& file, typename Schema::IfcRepresentation* rep, typename Schema::IfcPresentationStyleAssignment* style_assignment) { + typename Schema::IfcRepresentationItem::list::ptr items = rep->Items(); + for (typename Schema::IfcRepresentationItem::list::it i = items->begin(); i != items->end(); ++i) { + typename Schema::IfcRepresentationItem* item = *i; + typename Schema::IfcStyledItem* styled_item = create_styled_item(item, style_assignment); + file.addEntity(styled_item); + } } template -void setSurfaceColour_4x3(IfcHierarchyHelper& file, typename Schema::IfcRepresentation* rep, typename Schema::IfcPresentationStyle* style) -{ - typename Schema::IfcRepresentationItem::list::ptr items = rep->Items(); - for (typename Schema::IfcRepresentationItem::list::it i = items->begin(); i != items->end(); ++i) { - typename Schema::IfcRepresentationItem* item = *i; - typename Schema::IfcStyledItem* styled_item = create_styled_item(item, style); - file.addEntity(styled_item); - } +void setSurfaceColour_4x3(IfcHierarchyHelper& file, typename Schema::IfcRepresentation* rep, typename Schema::IfcPresentationStyle* style) { + typename Schema::IfcRepresentationItem::list::ptr items = rep->Items(); + for (typename Schema::IfcRepresentationItem::list::it i = items->begin(); i != items->end(); ++i) { + typename Schema::IfcRepresentationItem* item = *i; + typename Schema::IfcStyledItem* styled_item = create_styled_item(item, style); + file.addEntity(styled_item); + } } #ifdef HAS_SCHEMA_2x3 -Ifc2x3::IfcPresentationStyleAssignment* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) -{ - return addStyleAssignment_2x3(file, r, g, b, a); +Ifc2x3::IfcPresentationStyleAssignment* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) { + return addStyleAssignment_2x3(file, r, g, b, a); } -Ifc2x3::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc2x3::IfcProductRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_2x3(file, shape, r, g, b, a); +Ifc2x3::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc2x3::IfcProductRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_2x3(file, shape, r, g, b, a); } -Ifc2x3::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc2x3::IfcRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_2x3(file, shape, r, g, b, a); +Ifc2x3::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc2x3::IfcRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_2x3(file, shape, r, g, b, a); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc2x3::IfcProductRepresentation* shape, Ifc2x3::IfcPresentationStyleAssignment* style_assignment) -{ - setSurfaceColour_2x3(file, shape, style_assignment); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc2x3::IfcProductRepresentation* shape, Ifc2x3::IfcPresentationStyleAssignment* style_assignment) { + setSurfaceColour_2x3(file, shape, style_assignment); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc2x3::IfcRepresentation* shape, Ifc2x3::IfcPresentationStyleAssignment* style_assignment) -{ - setSurfaceColour_2x3(file, shape, style_assignment); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc2x3::IfcRepresentation* shape, Ifc2x3::IfcPresentationStyleAssignment* style_assignment) { + setSurfaceColour_2x3(file, shape, style_assignment); } #endif #ifdef HAS_SCHEMA_4 -Ifc4::IfcPresentationStyleAssignment* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) -{ - return addStyleAssignment_2x3(file, r, g, b, a); +Ifc4::IfcPresentationStyleAssignment* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) { + return addStyleAssignment_2x3(file, r, g, b, a); } -Ifc4::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4::IfcProductRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_2x3(file, shape, r, g, b, a); +Ifc4::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4::IfcProductRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_2x3(file, shape, r, g, b, a); } -Ifc4::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4::IfcRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_2x3(file, shape, r, g, b, a); +Ifc4::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4::IfcRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_2x3(file, shape, r, g, b, a); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4::IfcProductRepresentation* shape, Ifc4::IfcPresentationStyleAssignment* style_assignment) -{ - setSurfaceColour_2x3(file, shape, style_assignment); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4::IfcProductRepresentation* shape, Ifc4::IfcPresentationStyleAssignment* style_assignment) { + setSurfaceColour_2x3(file, shape, style_assignment); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4::IfcRepresentation* shape, Ifc4::IfcPresentationStyleAssignment* style_assignment) -{ - setSurfaceColour_2x3(file, shape, style_assignment); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4::IfcRepresentation* shape, Ifc4::IfcPresentationStyleAssignment* style_assignment) { + setSurfaceColour_2x3(file, shape, style_assignment); } #endif - #ifdef HAS_SCHEMA_4x1 -Ifc4x1::IfcPresentationStyleAssignment* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) -{ - return addStyleAssignment_2x3(file, r, g, b, a); +Ifc4x1::IfcPresentationStyleAssignment* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) { + return addStyleAssignment_2x3(file, r, g, b, a); } -Ifc4x1::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x1::IfcProductRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_2x3(file, shape, r, g, b, a); +Ifc4x1::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x1::IfcProductRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_2x3(file, shape, r, g, b, a); } -Ifc4x1::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x1::IfcRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_2x3(file, shape, r, g, b, a); +Ifc4x1::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x1::IfcRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_2x3(file, shape, r, g, b, a); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x1::IfcProductRepresentation* shape, Ifc4x1::IfcPresentationStyleAssignment* style_assignment) -{ - setSurfaceColour_2x3(file, shape, style_assignment); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x1::IfcProductRepresentation* shape, Ifc4x1::IfcPresentationStyleAssignment* style_assignment) { + setSurfaceColour_2x3(file, shape, style_assignment); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x1::IfcRepresentation* shape, Ifc4x1::IfcPresentationStyleAssignment* style_assignment) -{ - setSurfaceColour_2x3(file, shape, style_assignment); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x1::IfcRepresentation* shape, Ifc4x1::IfcPresentationStyleAssignment* style_assignment) { + setSurfaceColour_2x3(file, shape, style_assignment); } #endif - #ifdef HAS_SCHEMA_4x2 -Ifc4x2::IfcPresentationStyleAssignment* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) -{ - return addStyleAssignment_2x3(file, r, g, b, a); +Ifc4x2::IfcPresentationStyleAssignment* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) { + return addStyleAssignment_2x3(file, r, g, b, a); } -Ifc4x2::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x2::IfcProductRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_2x3(file, shape, r, g, b, a); +Ifc4x2::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x2::IfcProductRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_2x3(file, shape, r, g, b, a); } -Ifc4x2::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x2::IfcRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_2x3(file, shape, r, g, b, a); +Ifc4x2::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x2::IfcRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_2x3(file, shape, r, g, b, a); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x2::IfcProductRepresentation* shape, Ifc4x2::IfcPresentationStyleAssignment* style_assignment) -{ - setSurfaceColour_2x3(file, shape, style_assignment); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x2::IfcProductRepresentation* shape, Ifc4x2::IfcPresentationStyleAssignment* style_assignment) { + setSurfaceColour_2x3(file, shape, style_assignment); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x2::IfcRepresentation* shape, Ifc4x2::IfcPresentationStyleAssignment* style_assignment) -{ - setSurfaceColour_2x3(file, shape, style_assignment); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x2::IfcRepresentation* shape, Ifc4x2::IfcPresentationStyleAssignment* style_assignment) { + setSurfaceColour_2x3(file, shape, style_assignment); } #endif #ifdef HAS_SCHEMA_4x3_rc1 -Ifc4x3_rc1::IfcPresentationStyleAssignment* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) -{ - return addStyleAssignment_2x3(file, r, g, b, a); +Ifc4x3_rc1::IfcPresentationStyleAssignment* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) { + return addStyleAssignment_2x3(file, r, g, b, a); } -Ifc4x3_rc1::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc1::IfcProductRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_2x3(file, shape, r, g, b, a); +Ifc4x3_rc1::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc1::IfcProductRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_2x3(file, shape, r, g, b, a); } -Ifc4x3_rc1::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc1::IfcRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_2x3(file, shape, r, g, b, a); +Ifc4x3_rc1::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc1::IfcRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_2x3(file, shape, r, g, b, a); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc1::IfcProductRepresentation* shape, Ifc4x3_rc1::IfcPresentationStyleAssignment* style_assignment) -{ - setSurfaceColour_2x3(file, shape, style_assignment); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc1::IfcProductRepresentation* shape, Ifc4x3_rc1::IfcPresentationStyleAssignment* style_assignment) { + setSurfaceColour_2x3(file, shape, style_assignment); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc1::IfcRepresentation* shape, Ifc4x3_rc1::IfcPresentationStyleAssignment* style_assignment) -{ - setSurfaceColour_2x3(file, shape, style_assignment); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc1::IfcRepresentation* shape, Ifc4x3_rc1::IfcPresentationStyleAssignment* style_assignment) { + setSurfaceColour_2x3(file, shape, style_assignment); } #endif #ifdef HAS_SCHEMA_4x3_rc2 -Ifc4x3_rc2::IfcPresentationStyleAssignment* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) -{ - return addStyleAssignment_2x3(file, r, g, b, a); +Ifc4x3_rc2::IfcPresentationStyleAssignment* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) { + return addStyleAssignment_2x3(file, r, g, b, a); } -Ifc4x3_rc2::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc2::IfcProductRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_2x3(file, shape, r, g, b, a); +Ifc4x3_rc2::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc2::IfcProductRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_2x3(file, shape, r, g, b, a); } -Ifc4x3_rc2::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc2::IfcRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_2x3(file, shape, r, g, b, a); +Ifc4x3_rc2::IfcPresentationStyleAssignment* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc2::IfcRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_2x3(file, shape, r, g, b, a); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc2::IfcProductRepresentation* shape, Ifc4x3_rc2::IfcPresentationStyleAssignment* style_assignment) -{ - setSurfaceColour_2x3(file, shape, style_assignment); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc2::IfcProductRepresentation* shape, Ifc4x3_rc2::IfcPresentationStyleAssignment* style_assignment) { + setSurfaceColour_2x3(file, shape, style_assignment); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc2::IfcRepresentation* shape, Ifc4x3_rc2::IfcPresentationStyleAssignment* style_assignment) -{ - setSurfaceColour_2x3(file, shape, style_assignment); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc2::IfcRepresentation* shape, Ifc4x3_rc2::IfcPresentationStyleAssignment* style_assignment) { + setSurfaceColour_2x3(file, shape, style_assignment); } #endif #ifdef HAS_SCHEMA_4x3_rc3 -Ifc4x3_rc3::IfcPresentationStyle* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) -{ - return addStyleAssignment_4x3(file, r, g, b, a); +Ifc4x3_rc3::IfcPresentationStyle* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) { + return addStyleAssignment_4x3(file, r, g, b, a); } -Ifc4x3_rc3::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc3::IfcProductRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_4x3(file, shape, r, g, b, a); +Ifc4x3_rc3::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc3::IfcProductRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_4x3(file, shape, r, g, b, a); } -Ifc4x3_rc3::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc3::IfcRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_4x3(file, shape, r, g, b, a); +Ifc4x3_rc3::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc3::IfcRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_4x3(file, shape, r, g, b, a); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc3::IfcProductRepresentation* shape, Ifc4x3_rc3::IfcPresentationStyle* style) -{ - setSurfaceColour_4x3(file, shape, style); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc3::IfcProductRepresentation* shape, Ifc4x3_rc3::IfcPresentationStyle* style) { + setSurfaceColour_4x3(file, shape, style); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc3::IfcRepresentation* shape, Ifc4x3_rc3::IfcPresentationStyle* style) -{ - setSurfaceColour_4x3(file, shape, style); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc3::IfcRepresentation* shape, Ifc4x3_rc3::IfcPresentationStyle* style) { + setSurfaceColour_4x3(file, shape, style); } #endif #ifdef HAS_SCHEMA_4x3_rc4 -Ifc4x3_rc4::IfcPresentationStyle* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) -{ - return addStyleAssignment_4x3(file, r, g, b, a); +Ifc4x3_rc4::IfcPresentationStyle* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) { + return addStyleAssignment_4x3(file, r, g, b, a); } -Ifc4x3_rc4::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc4::IfcProductRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_4x3(file, shape, r, g, b, a); +Ifc4x3_rc4::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc4::IfcProductRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_4x3(file, shape, r, g, b, a); } -Ifc4x3_rc4::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc4::IfcRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_4x3(file, shape, r, g, b, a); +Ifc4x3_rc4::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc4::IfcRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_4x3(file, shape, r, g, b, a); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc4::IfcProductRepresentation* shape, Ifc4x3_rc4::IfcPresentationStyle* style) -{ - setSurfaceColour_4x3(file, shape, style); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc4::IfcProductRepresentation* shape, Ifc4x3_rc4::IfcPresentationStyle* style) { + setSurfaceColour_4x3(file, shape, style); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc4::IfcRepresentation* shape, Ifc4x3_rc4::IfcPresentationStyle* style) -{ - setSurfaceColour_4x3(file, shape, style); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc4::IfcRepresentation* shape, Ifc4x3_rc4::IfcPresentationStyle* style) { + setSurfaceColour_4x3(file, shape, style); } #endif #ifdef HAS_SCHEMA_4x3 -Ifc4x3::IfcPresentationStyle* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) -{ - return addStyleAssignment_4x3(file, r, g, b, a); +Ifc4x3::IfcPresentationStyle* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) { + return addStyleAssignment_4x3(file, r, g, b, a); } -Ifc4x3::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3::IfcProductRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_4x3(file, shape, r, g, b, a); +Ifc4x3::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3::IfcProductRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_4x3(file, shape, r, g, b, a); } -Ifc4x3::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3::IfcRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_4x3(file, shape, r, g, b, a); +Ifc4x3::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3::IfcRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_4x3(file, shape, r, g, b, a); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3::IfcProductRepresentation* shape, Ifc4x3::IfcPresentationStyle* style) -{ - setSurfaceColour_4x3(file, shape, style); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3::IfcProductRepresentation* shape, Ifc4x3::IfcPresentationStyle* style) { + setSurfaceColour_4x3(file, shape, style); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3::IfcRepresentation* shape, Ifc4x3::IfcPresentationStyle* style) -{ - setSurfaceColour_4x3(file, shape, style); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3::IfcRepresentation* shape, Ifc4x3::IfcPresentationStyle* style) { + setSurfaceColour_4x3(file, shape, style); } #endif #ifdef HAS_SCHEMA_4x3_tc1 -Ifc4x3_tc1::IfcPresentationStyle* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) -{ - return addStyleAssignment_4x3(file, r, g, b, a); +Ifc4x3_tc1::IfcPresentationStyle* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) { + return addStyleAssignment_4x3(file, r, g, b, a); } -Ifc4x3_tc1::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_tc1::IfcProductRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_4x3(file, shape, r, g, b, a); +Ifc4x3_tc1::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_tc1::IfcProductRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_4x3(file, shape, r, g, b, a); } -Ifc4x3_tc1::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_tc1::IfcRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_4x3(file, shape, r, g, b, a); +Ifc4x3_tc1::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_tc1::IfcRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_4x3(file, shape, r, g, b, a); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_tc1::IfcProductRepresentation* shape, Ifc4x3_tc1::IfcPresentationStyle* style) -{ - setSurfaceColour_4x3(file, shape, style); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_tc1::IfcProductRepresentation* shape, Ifc4x3_tc1::IfcPresentationStyle* style) { + setSurfaceColour_4x3(file, shape, style); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_tc1::IfcRepresentation* shape, Ifc4x3_tc1::IfcPresentationStyle* style) -{ - setSurfaceColour_4x3(file, shape, style); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_tc1::IfcRepresentation* shape, Ifc4x3_tc1::IfcPresentationStyle* style) { + setSurfaceColour_4x3(file, shape, style); } #endif #ifdef HAS_SCHEMA_4x3_add1 -Ifc4x3_add1::IfcPresentationStyle* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) -{ - return addStyleAssignment_4x3(file, r, g, b, a); +Ifc4x3_add1::IfcPresentationStyle* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a) { + return addStyleAssignment_4x3(file, r, g, b, a); } -Ifc4x3_add1::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_add1::IfcProductRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_4x3(file, shape, r, g, b, a); +Ifc4x3_add1::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_add1::IfcProductRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_4x3(file, shape, r, g, b, a); } -Ifc4x3_add1::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_add1::IfcRepresentation* shape, double r, double g, double b, double a) -{ - return setSurfaceColour_4x3(file, shape, r, g, b, a); +Ifc4x3_add1::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_add1::IfcRepresentation* shape, double r, double g, double b, double a) { + return setSurfaceColour_4x3(file, shape, r, g, b, a); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_add1::IfcProductRepresentation* shape, Ifc4x3_add1::IfcPresentationStyle* style) -{ - setSurfaceColour_4x3(file, shape, style); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_add1::IfcProductRepresentation* shape, Ifc4x3_add1::IfcPresentationStyle* style) { + setSurfaceColour_4x3(file, shape, style); } -void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_add1::IfcRepresentation* shape, Ifc4x3_add1::IfcPresentationStyle* style) -{ - setSurfaceColour_4x3(file, shape, style); +void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_add1::IfcRepresentation* shape, Ifc4x3_add1::IfcPresentationStyle* style) { + setSurfaceColour_4x3(file, shape, style); } #endif template typename Schema::IfcProductDefinitionShape* IfcHierarchyHelper::addMappedItem( - typename Schema::IfcShapeRepresentation* rep, - typename Schema::IfcCartesianTransformationOperator3D* transform, - typename Schema::IfcProductDefinitionShape* def) -{ - typename Schema::IfcRepresentationMap::list::ptr maps = rep->RepresentationMap(); - typename Schema::IfcRepresentationMap* map; - if (maps->size() == 1) { - map = *maps->begin(); - } else { - map = new typename Schema::IfcRepresentationMap(addPlacement3d(), rep); - addEntity(map); - } + typename Schema::IfcShapeRepresentation* rep, + typename Schema::IfcCartesianTransformationOperator3D* transform, + typename Schema::IfcProductDefinitionShape* def) { + typename Schema::IfcRepresentationMap::list::ptr maps = rep->RepresentationMap(); + typename Schema::IfcRepresentationMap* map; + if (maps->size() == 1) { + map = *maps->begin(); + } else { + map = new typename Schema::IfcRepresentationMap(addPlacement3d(), rep); + addEntity(map); + } - typename Schema::IfcRepresentation::list::ptr representations(new typename Schema::IfcRepresentation::list); - if (def) representations = def->Representations(); + typename Schema::IfcRepresentation::list::ptr representations(new typename Schema::IfcRepresentation::list); + if (def) { + representations = def->Representations(); + } - if (!transform) { - transform = new typename Schema::IfcCartesianTransformationOperator3D(0, 0, addTriplet(0,0,0), boost::none, 0); - addEntity(transform); - } - typename Schema::IfcMappedItem* item = new typename Schema::IfcMappedItem(map, transform); - typename Schema::IfcRepresentationItem::list::ptr items(new typename Schema::IfcRepresentationItem::list); - items->push(item); - typename Schema::IfcRepresentation* new_rep = new typename Schema::IfcShapeRepresentation(rep->ContextOfItems(), boost::none, std::string("MappedRepresentation"), items); - if (rep->RepresentationIdentifier()) { - new_rep->setRepresentationIdentifier(rep->RepresentationIdentifier()); - } - addEntity(item); - addEntity(new_rep); - representations->push(new_rep); - if (!def) { - def = new typename Schema::IfcProductDefinitionShape(boost::none, boost::none, representations); - addEntity(def); - } else { - def->setRepresentations(representations); - } - return def; + if (!transform) { + transform = new typename Schema::IfcCartesianTransformationOperator3D(0, 0, addTriplet(0, 0, 0), boost::none, 0); + addEntity(transform); + } + typename Schema::IfcMappedItem* item = new typename Schema::IfcMappedItem(map, transform); + typename Schema::IfcRepresentationItem::list::ptr items(new typename Schema::IfcRepresentationItem::list); + items->push(item); + typename Schema::IfcRepresentation* new_rep = new typename Schema::IfcShapeRepresentation(rep->ContextOfItems(), boost::none, std::string("MappedRepresentation"), items); + if (rep->RepresentationIdentifier()) { + new_rep->setRepresentationIdentifier(rep->RepresentationIdentifier()); + } + addEntity(item); + addEntity(new_rep); + representations->push(new_rep); + if (!def) { + def = new typename Schema::IfcProductDefinitionShape(boost::none, boost::none, representations); + addEntity(def); + } else { + def->setRepresentations(representations); + } + return def; } template typename Schema::IfcProductDefinitionShape* IfcHierarchyHelper::addMappedItem( - typename Schema::IfcShapeRepresentation::list::ptr reps, - typename Schema::IfcCartesianTransformationOperator3D* transform) -{ - typename Schema::IfcProductDefinitionShape* def = 0; - for (typename Schema::IfcShapeRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) { - def = addMappedItem(*it, transform, def); - } - return def; + typename Schema::IfcShapeRepresentation::list::ptr reps, + typename Schema::IfcCartesianTransformationOperator3D* transform) { + typename Schema::IfcProductDefinitionShape* def = 0; + for (typename Schema::IfcShapeRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) { + def = addMappedItem(*it, transform, def); + } + return def; } template typename Schema::IfcShapeRepresentation* IfcHierarchyHelper::addEmptyRepresentation(const std::string& repid, const std::string& reptype) { - typename Schema::IfcRepresentationItem::list::ptr items(new typename Schema::IfcRepresentationItem::list); - typename Schema::IfcShapeRepresentation* shape_rep = new typename Schema::IfcShapeRepresentation(getRepresentationContext(reptype == "Curve2D" ? "Plan" : "Model"), repid, reptype, items); - addEntity(shape_rep); - return shape_rep; + typename Schema::IfcRepresentationItem::list::ptr items(new typename Schema::IfcRepresentationItem::list); + typename Schema::IfcShapeRepresentation* shape_rep = new typename Schema::IfcShapeRepresentation(getRepresentationContext(reptype == "Curve2D" ? "Plan" : "Model"), repid, reptype, items); + addEntity(shape_rep); + return shape_rep; } namespace { - template - void push_back_to_maybe_optional(T& t, U* u) { - t->push(u); - } - - // In IFC4 the IfcContext.RepresentationContexts has been made optional, so we need - // some boiler plate to push back to a list that might be optional. - template - void push_back_to_maybe_optional(boost::optional>& t, U* u) { - if (!t) { - t = boost::shared_ptr(new T); - } - (*t)->push(u); - } +template +void push_back_to_maybe_optional(T& t, U* u) { + t->push(u); } +// In IFC4 the IfcContext.RepresentationContexts has been made optional, so we need +// some boiler plate to push back to a list that might be optional. +template +void push_back_to_maybe_optional(boost::optional>& t, U* u) { + if (!t) { + t = boost::shared_ptr(new T); + } + (*t)->push(u); +} +} // namespace + template typename Schema::IfcGeometricRepresentationContext* IfcHierarchyHelper::getRepresentationContext(const std::string& s) { - typename std::map::const_iterator it = contexts.find(s); - if (it != contexts.end()) return it->second; - else { - typename Schema::IfcProject* project = getSingle(); - if (!project) { - project = addProject(); - } - auto project_contexts = project->RepresentationContexts(); - typename Schema::IfcGeometricRepresentationContext* context = new typename Schema::IfcGeometricRepresentationContext( - boost::none, s, 3, 1e-5, addPlacement3d(), addDoublet(0, 1)); - addEntity(context); - push_back_to_maybe_optional(project_contexts, context); - - project->setRepresentationContexts(project_contexts); - return contexts[s] = context; - } + typename std::map::const_iterator it = contexts.find(s); + if (it != contexts.end()) { + return it->second; + } else { + typename Schema::IfcProject* project = getSingle(); + if (!project) { + project = addProject(); + } + auto project_contexts = project->RepresentationContexts(); + typename Schema::IfcGeometricRepresentationContext* context = new typename Schema::IfcGeometricRepresentationContext( + boost::none, s, 3, 1e-5, addPlacement3d(), addDoublet(0, 1)); + addEntity(context); + push_back_to_maybe_optional(project_contexts, context); + + project->setRepresentationContexts(project_contexts); + return contexts[s] = context; + } } #ifdef HAS_SCHEMA_2x3 diff --git a/src/ifcparse/IfcHierarchyHelper.h b/src/ifcparse/IfcHierarchyHelper.h index 885d5ebea3..eb2b36ac06 100644 --- a/src/ifcparse/IfcHierarchyHelper.h +++ b/src/ifcparse/IfcHierarchyHelper.h @@ -28,361 +28,367 @@ #ifndef IFCHIERARCHYHELPER_H #define IFCHIERARCHYHELPER_H -#include - #include "ifc_parse_api.h" +#include + #ifdef HAS_SCHEMA_2x3 -#include "../ifcparse/Ifc2x3.h" +#include "Ifc2x3.h" #endif #ifdef HAS_SCHEMA_4 -#include "../ifcparse/Ifc4.h" +#include "Ifc4.h" #endif #ifdef HAS_SCHEMA_4x1 -#include "../ifcparse/Ifc4x1.h" +#include "Ifc4x1.h" #endif #ifdef HAS_SCHEMA_4x2 -#include "../ifcparse/Ifc4x2.h" +#include "Ifc4x2.h" #endif #ifdef HAS_SCHEMA_4x3_rc1 -#include "../ifcparse/Ifc4x3_rc1.h" +#include "Ifc4x3_rc1.h" #endif #ifdef HAS_SCHEMA_4x3_rc2 -#include "../ifcparse/Ifc4x3_rc2.h" +#include "Ifc4x3_rc2.h" #endif #ifdef HAS_SCHEMA_4x3_rc3 -#include "../ifcparse/Ifc4x3_rc3.h" +#include "Ifc4x3_rc3.h" #endif #ifdef HAS_SCHEMA_4x3_rc4 -#include "../ifcparse/Ifc4x3_rc4.h" +#include "Ifc4x3_rc4.h" #endif #ifdef HAS_SCHEMA_4x3 -#include "../ifcparse/Ifc4x3.h" +#include "Ifc4x3.h" #endif #ifdef HAS_SCHEMA_4x3_tc1 -#include "../ifcparse/Ifc4x3_tc1.h" +#include "Ifc4x3_tc1.h" #endif #ifdef HAS_SCHEMA_4x3_add1 -#include "../ifcparse/Ifc4x3_add1.h" +#include "Ifc4x3_add1.h" #endif -#include "../ifcparse/IfcFile.h" -#include "../ifcparse/IfcWrite.h" -#include "../ifcparse/IfcGlobalId.h" +#include "IfcFile.h" +#include "IfcGlobalId.h" +#include "IfcWrite.h" namespace { #ifdef HAS_SCHEMA_2x3 - Ifc2x3::IfcObjectDefinition* get_parent_of_relation(Ifc2x3::IfcRelContainedInSpatialStructure* t) { - return t->RelatingStructure(); - } +Ifc2x3::IfcObjectDefinition* get_parent_of_relation(Ifc2x3::IfcRelContainedInSpatialStructure* t) { + return t->RelatingStructure(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc2x3::IfcRelContainedInSpatialStructure* t) { - return t->RelatedElements()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc2x3::IfcRelContainedInSpatialStructure* t) { + return t->RelatedElements()->generalize(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc2x3::IfcRelAggregates* t) { - return t->RelatedObjects()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc2x3::IfcRelAggregates* t) { + return t->RelatedObjects()->generalize(); +} - void set_children_of_relation(Ifc2x3::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { - t->setRelatedElements(cs->as()); - } +void set_children_of_relation(Ifc2x3::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { + t->setRelatedElements(cs->as()); +} - void set_children_of_relation(Ifc2x3::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { - t->setRelatedObjects(cs->as()); - } +void set_children_of_relation(Ifc2x3::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { + t->setRelatedObjects(cs->as()); +} #endif #ifdef HAS_SCHEMA_4 - Ifc4::IfcObjectDefinition* get_parent_of_relation(Ifc4::IfcRelContainedInSpatialStructure* t) { - return t->RelatingStructure(); - } +Ifc4::IfcObjectDefinition* get_parent_of_relation(Ifc4::IfcRelContainedInSpatialStructure* t) { + return t->RelatingStructure(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4::IfcRelContainedInSpatialStructure* t) { - return t->RelatedElements()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4::IfcRelContainedInSpatialStructure* t) { + return t->RelatedElements()->generalize(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4::IfcRelAggregates* t) { - return t->RelatedObjects()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4::IfcRelAggregates* t) { + return t->RelatedObjects()->generalize(); +} - void set_children_of_relation(Ifc4::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { - t->setRelatedElements(cs->as()); - } +void set_children_of_relation(Ifc4::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { + t->setRelatedElements(cs->as()); +} - void set_children_of_relation(Ifc4::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { - t->setRelatedObjects(cs->as()); - } +void set_children_of_relation(Ifc4::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { + t->setRelatedObjects(cs->as()); +} #endif #ifdef HAS_SCHEMA_4x1 - Ifc4x1::IfcObjectDefinition* get_parent_of_relation(Ifc4x1::IfcRelContainedInSpatialStructure* t) { - return t->RelatingStructure(); - } +Ifc4x1::IfcObjectDefinition* get_parent_of_relation(Ifc4x1::IfcRelContainedInSpatialStructure* t) { + return t->RelatingStructure(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x1::IfcRelContainedInSpatialStructure* t) { - return t->RelatedElements()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x1::IfcRelContainedInSpatialStructure* t) { + return t->RelatedElements()->generalize(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x1::IfcRelAggregates* t) { - return t->RelatedObjects()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x1::IfcRelAggregates* t) { + return t->RelatedObjects()->generalize(); +} - void set_children_of_relation(Ifc4x1::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { - t->setRelatedElements(cs->as()); - } +void set_children_of_relation(Ifc4x1::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { + t->setRelatedElements(cs->as()); +} - void set_children_of_relation(Ifc4x1::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { - t->setRelatedObjects(cs->as()); - } +void set_children_of_relation(Ifc4x1::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { + t->setRelatedObjects(cs->as()); +} #endif #ifdef HAS_SCHEMA_4x2 - Ifc4x2::IfcObjectDefinition* get_parent_of_relation(Ifc4x2::IfcRelContainedInSpatialStructure* t) { - return t->RelatingStructure(); - } +Ifc4x2::IfcObjectDefinition* get_parent_of_relation(Ifc4x2::IfcRelContainedInSpatialStructure* t) { + return t->RelatingStructure(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x2::IfcRelContainedInSpatialStructure* t) { - return t->RelatedElements()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x2::IfcRelContainedInSpatialStructure* t) { + return t->RelatedElements()->generalize(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x2::IfcRelAggregates* t) { - return t->RelatedObjects()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x2::IfcRelAggregates* t) { + return t->RelatedObjects()->generalize(); +} - void set_children_of_relation(Ifc4x2::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { - t->setRelatedElements(cs->as()); - } +void set_children_of_relation(Ifc4x2::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { + t->setRelatedElements(cs->as()); +} - void set_children_of_relation(Ifc4x2::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { - t->setRelatedObjects(cs->as()); - } +void set_children_of_relation(Ifc4x2::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { + t->setRelatedObjects(cs->as()); +} #endif #ifdef HAS_SCHEMA_4x3_rc1 - Ifc4x3_rc1::IfcObjectDefinition* get_parent_of_relation(Ifc4x3_rc1::IfcRelContainedInSpatialStructure* t) { - return t->RelatingStructure(); - } +Ifc4x3_rc1::IfcObjectDefinition* get_parent_of_relation(Ifc4x3_rc1::IfcRelContainedInSpatialStructure* t) { + return t->RelatingStructure(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_rc1::IfcRelContainedInSpatialStructure* t) { - return t->RelatedElements()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_rc1::IfcRelContainedInSpatialStructure* t) { + return t->RelatedElements()->generalize(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_rc1::IfcRelAggregates* t) { - return t->RelatedObjects()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_rc1::IfcRelAggregates* t) { + return t->RelatedObjects()->generalize(); +} - void set_children_of_relation(Ifc4x3_rc1::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { - t->setRelatedElements(cs->as()); - } +void set_children_of_relation(Ifc4x3_rc1::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { + t->setRelatedElements(cs->as()); +} - void set_children_of_relation(Ifc4x3_rc1::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { - t->setRelatedObjects(cs->as()); - } +void set_children_of_relation(Ifc4x3_rc1::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { + t->setRelatedObjects(cs->as()); +} #endif #ifdef HAS_SCHEMA_4x3_rc2 - Ifc4x3_rc2::IfcObjectDefinition* get_parent_of_relation(Ifc4x3_rc2::IfcRelContainedInSpatialStructure* t) { - return t->RelatingStructure(); - } +Ifc4x3_rc2::IfcObjectDefinition* get_parent_of_relation(Ifc4x3_rc2::IfcRelContainedInSpatialStructure* t) { + return t->RelatingStructure(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_rc2::IfcRelContainedInSpatialStructure* t) { - return t->RelatedElements()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_rc2::IfcRelContainedInSpatialStructure* t) { + return t->RelatedElements()->generalize(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_rc2::IfcRelAggregates* t) { - return t->RelatedObjects()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_rc2::IfcRelAggregates* t) { + return t->RelatedObjects()->generalize(); +} - void set_children_of_relation(Ifc4x3_rc2::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { - t->setRelatedElements(cs->as()); - } +void set_children_of_relation(Ifc4x3_rc2::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { + t->setRelatedElements(cs->as()); +} - void set_children_of_relation(Ifc4x3_rc2::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { - t->setRelatedObjects(cs->as()); - } +void set_children_of_relation(Ifc4x3_rc2::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { + t->setRelatedObjects(cs->as()); +} #endif #ifdef HAS_SCHEMA_4x3_rc3 - Ifc4x3_rc3::IfcObjectDefinition* get_parent_of_relation(Ifc4x3_rc3::IfcRelContainedInSpatialStructure* t) { - return t->RelatingStructure(); - } +Ifc4x3_rc3::IfcObjectDefinition* get_parent_of_relation(Ifc4x3_rc3::IfcRelContainedInSpatialStructure* t) { + return t->RelatingStructure(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_rc3::IfcRelContainedInSpatialStructure* t) { - return t->RelatedElements()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_rc3::IfcRelContainedInSpatialStructure* t) { + return t->RelatedElements()->generalize(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_rc3::IfcRelAggregates* t) { - return t->RelatedObjects()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_rc3::IfcRelAggregates* t) { + return t->RelatedObjects()->generalize(); +} - void set_children_of_relation(Ifc4x3_rc3::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { - t->setRelatedElements(cs->as()); - } +void set_children_of_relation(Ifc4x3_rc3::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { + t->setRelatedElements(cs->as()); +} - void set_children_of_relation(Ifc4x3_rc3::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { - t->setRelatedObjects(cs->as()); - } +void set_children_of_relation(Ifc4x3_rc3::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { + t->setRelatedObjects(cs->as()); +} #endif #ifdef HAS_SCHEMA_4x3_rc4 - Ifc4x3_rc4::IfcObjectDefinition* get_parent_of_relation(Ifc4x3_rc4::IfcRelContainedInSpatialStructure* t) { - return t->RelatingStructure(); - } +Ifc4x3_rc4::IfcObjectDefinition* get_parent_of_relation(Ifc4x3_rc4::IfcRelContainedInSpatialStructure* t) { + return t->RelatingStructure(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_rc4::IfcRelContainedInSpatialStructure* t) { - return t->RelatedElements()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_rc4::IfcRelContainedInSpatialStructure* t) { + return t->RelatedElements()->generalize(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_rc4::IfcRelAggregates* t) { - return t->RelatedObjects()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_rc4::IfcRelAggregates* t) { + return t->RelatedObjects()->generalize(); +} - void set_children_of_relation(Ifc4x3_rc4::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { - t->setRelatedElements(cs->as()); - } +void set_children_of_relation(Ifc4x3_rc4::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { + t->setRelatedElements(cs->as()); +} - void set_children_of_relation(Ifc4x3_rc4::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { - t->setRelatedObjects(cs->as()); - } +void set_children_of_relation(Ifc4x3_rc4::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { + t->setRelatedObjects(cs->as()); +} #endif #ifdef HAS_SCHEMA_4x3 - Ifc4x3::IfcObjectDefinition* get_parent_of_relation(Ifc4x3::IfcRelContainedInSpatialStructure* t) { - return t->RelatingStructure(); - } +Ifc4x3::IfcObjectDefinition* get_parent_of_relation(Ifc4x3::IfcRelContainedInSpatialStructure* t) { + return t->RelatingStructure(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x3::IfcRelContainedInSpatialStructure* t) { - return t->RelatedElements()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x3::IfcRelContainedInSpatialStructure* t) { + return t->RelatedElements()->generalize(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x3::IfcRelAggregates* t) { - return t->RelatedObjects()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x3::IfcRelAggregates* t) { + return t->RelatedObjects()->generalize(); +} - void set_children_of_relation(Ifc4x3::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { - t->setRelatedElements(cs->as()); - } +void set_children_of_relation(Ifc4x3::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { + t->setRelatedElements(cs->as()); +} - void set_children_of_relation(Ifc4x3::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { - t->setRelatedObjects(cs->as()); - } +void set_children_of_relation(Ifc4x3::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { + t->setRelatedObjects(cs->as()); +} #endif #ifdef HAS_SCHEMA_4x3_tc1 - Ifc4x3_tc1::IfcObjectDefinition* get_parent_of_relation(Ifc4x3_tc1::IfcRelContainedInSpatialStructure* t) { - return t->RelatingStructure(); - } +Ifc4x3_tc1::IfcObjectDefinition* get_parent_of_relation(Ifc4x3_tc1::IfcRelContainedInSpatialStructure* t) { + return t->RelatingStructure(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_tc1::IfcRelContainedInSpatialStructure* t) { - return t->RelatedElements()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_tc1::IfcRelContainedInSpatialStructure* t) { + return t->RelatedElements()->generalize(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_tc1::IfcRelAggregates* t) { - return t->RelatedObjects()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_tc1::IfcRelAggregates* t) { + return t->RelatedObjects()->generalize(); +} - void set_children_of_relation(Ifc4x3_tc1::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { - t->setRelatedElements(cs->as()); - } +void set_children_of_relation(Ifc4x3_tc1::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { + t->setRelatedElements(cs->as()); +} - void set_children_of_relation(Ifc4x3_tc1::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { - t->setRelatedObjects(cs->as()); - } +void set_children_of_relation(Ifc4x3_tc1::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { + t->setRelatedObjects(cs->as()); +} #endif #ifdef HAS_SCHEMA_4x3_add1 - Ifc4x3_add1::IfcObjectDefinition* get_parent_of_relation(Ifc4x3_add1::IfcRelContainedInSpatialStructure* t) { - return t->RelatingStructure(); - } +Ifc4x3_add1::IfcObjectDefinition* get_parent_of_relation(Ifc4x3_add1::IfcRelContainedInSpatialStructure* t) { + return t->RelatingStructure(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_add1::IfcRelContainedInSpatialStructure* t) { - return t->RelatedElements()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_add1::IfcRelContainedInSpatialStructure* t) { + return t->RelatedElements()->generalize(); +} - aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_add1::IfcRelAggregates* t) { - return t->RelatedObjects()->generalize(); - } +aggregate_of_instance::ptr get_children_of_relation(Ifc4x3_add1::IfcRelAggregates* t) { + return t->RelatedObjects()->generalize(); +} - void set_children_of_relation(Ifc4x3_add1::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { - t->setRelatedElements(cs->as()); - } +void set_children_of_relation(Ifc4x3_add1::IfcRelContainedInSpatialStructure* t, aggregate_of_instance::ptr& cs) { + t->setRelatedElements(cs->as()); +} - void set_children_of_relation(Ifc4x3_add1::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { - t->setRelatedObjects(cs->as()); - } +void set_children_of_relation(Ifc4x3_add1::IfcRelAggregates* t, aggregate_of_instance::ptr& cs) { + t->setRelatedObjects(cs->as()); +} #endif - - IfcUtil::IfcBaseClass* get_parent_of_relation(IfcUtil::IfcBaseClass* t) { - return *t->data().getArgument( - t->declaration().as_entity()->attribute_index("RelatingObject") - ); - } - - aggregate_of_instance::ptr get_children_of_relation(IfcUtil::IfcBaseClass* t) { - return *t->data().getArgument( - t->declaration().as_entity()->attribute_index("RelatedElements") - ); - } - - void set_children_of_relation(IfcUtil::IfcBaseClass* t, aggregate_of_instance::ptr& cs) { - IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument; - attr->set(cs); - t->data().setArgument( - t->declaration().as_entity()->attribute_index("RelatedElements"), - attr - ); - } +IfcUtil::IfcBaseClass* get_parent_of_relation(IfcUtil::IfcBaseClass* t) { + return *t->data().getArgument( + t->declaration().as_entity()->attribute_index("RelatingObject")); } + +aggregate_of_instance::ptr get_children_of_relation(IfcUtil::IfcBaseClass* t) { + return *t->data().getArgument( + t->declaration().as_entity()->attribute_index("RelatedElements")); +} + +void set_children_of_relation(IfcUtil::IfcBaseClass* t, aggregate_of_instance::ptr& cs) { + IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument; + attr->set(cs); + t->data().setArgument( + t->declaration().as_entity()->attribute_index("RelatedElements"), + attr); +} +} // namespace template class IFC_PARSE_API IfcHierarchyHelper : public IfcParse::IfcFile { -public: - IfcHierarchyHelper() : IfcParse::IfcFile(&Schema::get_schema()) {} + public: + IfcHierarchyHelper() : IfcParse::IfcFile(&Schema::get_schema()) {} - template - T* addTriplet(double x, double y, double z) { - std::vector a; a.push_back(x); a.push_back(y); a.push_back(z); - T* t = new T(a); - addEntity(t); - return t; - } + template + T* addTriplet(double x, double y, double z) { + std::vector a; + a.push_back(x); + a.push_back(y); + a.push_back(z); + T* t = new T(a); + addEntity(t); + return t; + } - template - T* addDoublet(double x, double y) { - std::vector a; a.push_back(x); a.push_back(y); - T* t = new T(a); - addEntity(t); - return t; - } + template + T* addDoublet(double x, double y) { + std::vector a; + a.push_back(x); + a.push_back(y); + T* t = new T(a); + addEntity(t); + return t; + } - template - T* getSingle() { - typename T::list::ptr ts = instances_by_type(); - if (ts->size() != 1) return 0; - return *ts->begin(); - } - - typename Schema::IfcAxis2Placement3D* addPlacement3d(double ox=0.0, double oy=0.0, double oz=0.0, - double zx=0.0, double zy=0.0, double zz=1.0, - double xx=1.0, double xy=0.0, double xz=0.0); + template + T* getSingle() { + typename T::list::ptr ts = instances_by_type(); + if (ts->size() != 1) { + return 0; + } + return *ts->begin(); + } - typename Schema::IfcAxis2Placement2D* addPlacement2d(double ox=0.0, double oy=0.0, - double xx=1.0, double xy=0.0); + typename Schema::IfcAxis2Placement3D* addPlacement3d(double ox = 0.0, double oy = 0.0, double oz = 0.0, double zx = 0.0, double zy = 0.0, double zz = 1.0, double xx = 1.0, double xy = 0.0, double xz = 0.0); - typename Schema::IfcLocalPlacement* addLocalPlacement(typename Schema::IfcObjectPlacement* parent = 0, - double ox=0.0, double oy=0.0, double oz=0.0, - double zx=0.0, double zy=0.0, double zz=1.0, - double xx=1.0, double xy=0.0, double xz=0.0); + typename Schema::IfcAxis2Placement2D* addPlacement2d(double ox = 0.0, double oy = 0.0, double xx = 1.0, double xy = 0.0); - template - void addRelatedObject(typename Schema::IfcObjectDefinition* relating_object, - typename Schema::IfcObjectDefinition* related_object, typename Schema::IfcOwnerHistory* owner_hist = 0) - { - typename T::list::ptr li = instances_by_type(); - bool found = false; - for (typename T::list::it i = li->begin(); i != li->end(); ++i) { - T* rel = *i; + typename Schema::IfcLocalPlacement* addLocalPlacement(typename Schema::IfcObjectPlacement* parent = 0, + double ox = 0.0, + double oy = 0.0, + double oz = 0.0, + double zx = 0.0, + double zy = 0.0, + double zz = 1.0, + double xx = 1.0, + double xy = 0.0, + double xz = 0.0); + + template + void addRelatedObject(typename Schema::IfcObjectDefinition* relating_object, + typename Schema::IfcObjectDefinition* related_object, + typename Schema::IfcOwnerHistory* owner_hist = 0) { + typename T::list::ptr li = instances_by_type(); + bool found = false; + for (typename T::list::it i = li->begin(); i != li->end(); ++i) { + T* rel = *i; try { if (get_parent_of_relation(rel) == relating_object) { aggregate_of_instance::ptr products = get_children_of_relation(rel); @@ -392,88 +398,100 @@ public: break; } } catch (std::exception& e) { - Logger::Error(e); - } catch (...) { - Logger::Error("Unknown error in addRelatedObject()"); - } - } - if (! found) { - if (! owner_hist) { - owner_hist = getSingle(); - } - if (! owner_hist) { - owner_hist = addOwnerHistory(); - } + Logger::Error(e); + } catch (...) { + Logger::Error("Unknown error in addRelatedObject()"); + } + } + if (!found) { + if (!owner_hist) { + owner_hist = getSingle(); + } + if (!owner_hist) { + owner_hist = addOwnerHistory(); + } - aggregate_of_instance::ptr related_objects (new aggregate_of_instance); - related_objects->push(related_object); + aggregate_of_instance::ptr related_objects(new aggregate_of_instance); + related_objects->push(related_object); - IfcEntityInstanceData* data = new IfcEntityInstanceData(&T::Class()); - { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(IfcParse::IfcGlobalId()); data->setArgument(0, attr); } - { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(owner_hist); data->setArgument(1, attr); } - int relating_index = 4, related_index = 5; - if (T::Class().name() == "IfcRelContainedInSpatialStructure") { - // IfcRelContainedInSpatialStructure has attributes reversed. - std::swap(relating_index, related_index); - } - { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(relating_object); data->setArgument(relating_index, attr); } - { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(related_objects); data->setArgument(related_index, attr); } - - T* t = (T*)Schema::get_schema().instantiate(data); - addEntity(t); - } - } + IfcEntityInstanceData* data = new IfcEntityInstanceData(&T::Class()); + { + IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); + attr->set(IfcParse::IfcGlobalId()); + data->setArgument(0, attr); + } + { + IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); + attr->set(owner_hist); + data->setArgument(1, attr); + } + int relating_index = 4, related_index = 5; + if (T::Class().name() == "IfcRelContainedInSpatialStructure") { + // IfcRelContainedInSpatialStructure has attributes reversed. + std::swap(relating_index, related_index); + } + { + IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); + attr->set(relating_object); + data->setArgument(relating_index, attr); + } + { + IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); + attr->set(related_objects); + data->setArgument(related_index, attr); + } - typename Schema::IfcOwnerHistory* addOwnerHistory(); - typename Schema::IfcProject* addProject(typename Schema::IfcOwnerHistory* owner_hist = 0); - void relatePlacements(typename Schema::IfcProduct* parent, typename Schema::IfcProduct* product); - typename Schema::IfcSite* addSite(typename Schema::IfcProject* proj = 0, typename Schema::IfcOwnerHistory* owner_hist = 0); - typename Schema::IfcBuilding* addBuilding(typename Schema::IfcSite* site = 0, typename Schema::IfcOwnerHistory* owner_hist = 0); + T* t = (T*)Schema::get_schema().instantiate(data); + addEntity(t); + } + } - typename Schema::IfcBuildingStorey* addBuildingStorey(typename Schema::IfcBuilding* building = 0, - typename Schema::IfcOwnerHistory* owner_hist = 0); + typename Schema::IfcOwnerHistory* addOwnerHistory(); + typename Schema::IfcProject* addProject(typename Schema::IfcOwnerHistory* owner_hist = 0); + void relatePlacements(typename Schema::IfcProduct* parent, typename Schema::IfcProduct* product); + typename Schema::IfcSite* addSite(typename Schema::IfcProject* proj = 0, typename Schema::IfcOwnerHistory* owner_hist = 0); + typename Schema::IfcBuilding* addBuilding(typename Schema::IfcSite* site = 0, typename Schema::IfcOwnerHistory* owner_hist = 0); - typename Schema::IfcBuildingStorey* addBuildingProduct(typename Schema::IfcProduct* product, - typename Schema::IfcBuildingStorey* storey = 0, typename Schema::IfcOwnerHistory* owner_hist = 0); + typename Schema::IfcBuildingStorey* addBuildingStorey(typename Schema::IfcBuilding* building = 0, + typename Schema::IfcOwnerHistory* owner_hist = 0); - void addExtrudedPolyline(typename Schema::IfcShapeRepresentation* rep, const std::vector >& points, double h, - typename Schema::IfcAxis2Placement2D* place=0, typename Schema::IfcAxis2Placement3D* place2=0, - typename Schema::IfcDirection* dir=0, typename Schema::IfcRepresentationContext* context=0); + typename Schema::IfcBuildingStorey* addBuildingProduct(typename Schema::IfcProduct* product, + typename Schema::IfcBuildingStorey* storey = 0, + typename Schema::IfcOwnerHistory* owner_hist = 0); - typename Schema::IfcProductDefinitionShape* addExtrudedPolyline(const std::vector >& points, double h, - typename Schema::IfcAxis2Placement2D* place=0, typename Schema::IfcAxis2Placement3D* place2=0, typename Schema::IfcDirection* dir=0, - typename Schema::IfcRepresentationContext* context=0); + void addExtrudedPolyline(typename Schema::IfcShapeRepresentation* rep, const std::vector>& points, double h, typename Schema::IfcAxis2Placement2D* place = 0, typename Schema::IfcAxis2Placement3D* place2 = 0, typename Schema::IfcDirection* dir = 0, typename Schema::IfcRepresentationContext* context = 0); - void addBox(typename Schema::IfcShapeRepresentation* rep, double w, double d, double h, - typename Schema::IfcAxis2Placement2D* place=0, typename Schema::IfcAxis2Placement3D* place2=0, - typename Schema::IfcDirection* dir=0, typename Schema::IfcRepresentationContext* context=0); + typename Schema::IfcProductDefinitionShape* addExtrudedPolyline(const std::vector>& points, double h, typename Schema::IfcAxis2Placement2D* place = 0, typename Schema::IfcAxis2Placement3D* place2 = 0, typename Schema::IfcDirection* dir = 0, typename Schema::IfcRepresentationContext* context = 0); - typename Schema::IfcProductDefinitionShape* addBox(double w, double d, double h, typename Schema::IfcAxis2Placement2D* place=0, - typename Schema::IfcAxis2Placement3D* place2=0, typename Schema::IfcDirection* dir=0, typename Schema::IfcRepresentationContext* context=0); + void addBox(typename Schema::IfcShapeRepresentation* rep, double w, double d, double h, typename Schema::IfcAxis2Placement2D* place = 0, typename Schema::IfcAxis2Placement3D* place2 = 0, typename Schema::IfcDirection* dir = 0, typename Schema::IfcRepresentationContext* context = 0); - void addAxis(typename Schema::IfcShapeRepresentation* rep, double l, typename Schema::IfcRepresentationContext* context=0); + typename Schema::IfcProductDefinitionShape* addBox(double w, double d, double h, typename Schema::IfcAxis2Placement2D* place = 0, typename Schema::IfcAxis2Placement3D* place2 = 0, typename Schema::IfcDirection* dir = 0, typename Schema::IfcRepresentationContext* context = 0); - typename Schema::IfcProductDefinitionShape* addAxisBox(double w, double d, double h, typename Schema::IfcRepresentationContext* context=0); + void addAxis(typename Schema::IfcShapeRepresentation* rep, double l, typename Schema::IfcRepresentationContext* context = 0); - void clipRepresentation(typename Schema::IfcProductRepresentation* shape, - typename Schema::IfcAxis2Placement3D* place, bool agree); + typename Schema::IfcProductDefinitionShape* addAxisBox(double w, double d, double h, typename Schema::IfcRepresentationContext* context = 0); - void clipRepresentation(typename Schema::IfcRepresentation* shape, - typename Schema::IfcAxis2Placement3D* place, bool agree); + void clipRepresentation(typename Schema::IfcProductRepresentation* shape, + typename Schema::IfcAxis2Placement3D* place, + bool agree); - typename Schema::IfcProductDefinitionShape* addMappedItem(typename Schema::IfcShapeRepresentation*, - typename Schema::IfcCartesianTransformationOperator3D* transform = 0, - typename Schema::IfcProductDefinitionShape* def = 0); + void clipRepresentation(typename Schema::IfcRepresentation* shape, + typename Schema::IfcAxis2Placement3D* place, + bool agree); - typename Schema::IfcProductDefinitionShape* addMappedItem(typename Schema::IfcShapeRepresentation::list::ptr, - typename Schema::IfcCartesianTransformationOperator3D* transform = 0); - - typename Schema::IfcShapeRepresentation* addEmptyRepresentation(const std::string& repid = "Body", const std::string& reptype = "SweptSolid"); + typename Schema::IfcProductDefinitionShape* addMappedItem(typename Schema::IfcShapeRepresentation*, + typename Schema::IfcCartesianTransformationOperator3D* transform = 0, + typename Schema::IfcProductDefinitionShape* def = 0); - typename Schema::IfcGeometricRepresentationContext* getRepresentationContext(const std::string&); + typename Schema::IfcProductDefinitionShape* addMappedItem(typename Schema::IfcShapeRepresentation::list::ptr, + typename Schema::IfcCartesianTransformationOperator3D* transform = 0); -private: - std::map contexts; + typename Schema::IfcShapeRepresentation* addEmptyRepresentation(const std::string& repid = "Body", const std::string& reptype = "SweptSolid"); + + typename Schema::IfcGeometricRepresentationContext* getRepresentationContext(const std::string&); + + private: + std::map contexts; }; #ifdef HAS_SCHEMA_2x3 @@ -530,7 +548,7 @@ IFC_PARSE_API Ifc4x3_rc3::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHel IFC_PARSE_API Ifc4x3_rc3::IfcPresentationStyle* setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc3::IfcRepresentation* shape, double r, double g, double b, double a = 1.0); IFC_PARSE_API void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc3::IfcProductRepresentation* shape, Ifc4x3_rc3::IfcPresentationStyle* style); IFC_PARSE_API void setSurfaceColour(IfcHierarchyHelper& file, Ifc4x3_rc3::IfcRepresentation* shape, Ifc4x3_rc3::IfcPresentationStyle* style); -#endif +#endif #ifdef HAS_SCHEMA_4x3_rc4 IFC_PARSE_API Ifc4x3_rc4::IfcPresentationStyle* addStyleAssignment(IfcHierarchyHelper& file, double r, double g, double b, double a = 1.0); diff --git a/src/ifcparse/IfcLogger.cpp b/src/ifcparse/IfcLogger.cpp index e98bbb642c..5a8acc2567 100644 --- a/src/ifcparse/IfcLogger.cpp +++ b/src/ifcparse/IfcLogger.cpp @@ -19,217 +19,215 @@ #include "IfcLogger.h" -#include "../ifcparse/IfcException.h" -#include "../ifcparse/Argument.h" +#include "Argument.h" +#include "IfcException.h" +#include #include #include - -#include #include +#include #include - -#include -#include -#include +#include #include #include -#include +#include +#include namespace { - std::string get_time(bool with_milliseconds=false) { - std::ostringstream oss; - time_t now = time(nullptr); - oss << std::put_time(localtime(&now), "%F %T"); +std::string get_time(bool with_milliseconds = false) { + std::ostringstream oss; + time_t now = time(nullptr); + oss << std::put_time(localtime(&now), "%F %T"); - if (with_milliseconds) { - auto now_chrono = std::chrono::system_clock::now(); - auto ms = std::chrono::duration_cast(now_chrono.time_since_epoch()) % 1000; - oss << '.' << std::setfill('0') << std::setw(3) << ms.count(); - } + if (with_milliseconds) { + auto now_chrono = std::chrono::system_clock::now(); + auto ms = std::chrono::duration_cast(now_chrono.time_since_epoch()) % 1000; + oss << '.' << std::setfill('0') << std::setw(3) << ms.count(); + } - return oss.str(); - } - - template - struct severity_strings { - static const std::array, 5> value; - }; - - template <> - const std::array, 5> severity_strings::value = { "Performance", "Debug", "Notice", "Warning", "Error" }; - - template <> - const std::array, 5> severity_strings::value = { L"Performance", L"Debug", L"Notice", L"Warning", L"Error" }; - - template - void plain_text_message(T& os, const boost::optional& current_product, Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseInterface* instance) { - os << "[" << severity_strings::value[type] << "] "; - os << "[" << get_time(type <= Logger::LOG_PERF).c_str() << "] "; - if (current_product) { - std::string global_id = *((IfcUtil::IfcBaseEntity*)*current_product)->get("GlobalId"); - os << "{" << global_id.c_str() << "} "; - } - os << message.c_str() << std::endl; - if (instance) { - std::string instance_string = instance->data().toString(); - if (instance_string.size() > 259) { - instance_string = instance_string.substr(0, 256) + "..."; - } - os << instance_string.c_str() << std::endl; - } - } - - template - std::basic_string string_as(const std::string& s) { - std::basic_string v; - v.assign(s.begin(), s.end()); - return v; - } - - template - void json_message(T& os, const boost::optional& current_product, Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseInterface* instance) { - boost::property_tree::basic_ptree, std::basic_string > pt; - - // @todo this is crazy - static const typename T::char_type time_string[] = { 't', 'i', 'm', 'e', 0 }; - static const typename T::char_type level_string[] = { 'l', 'e', 'v', 'e', 'l', 0 }; - static const typename T::char_type product_string[] = { 'p', 'r', 'o', 'd', 'u', 'c', 't', 0 }; - static const typename T::char_type message_string[] = { 'm', 'e', 's', 's', 'a', 'g', 'e', 0 }; - static const typename T::char_type instance_string[] = { 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 0 }; - - pt.put(level_string, severity_strings::value[type]); - if (current_product) { - pt.put(product_string, string_as((**current_product).data().toString())); - } - pt.put(message_string, string_as(message)); - if (instance) { - pt.put(instance_string, string_as(instance->data().toString())); - } - - pt.put(time_string, string_as(get_time())); - - boost::property_tree::write_json(os, pt, false); - } + return oss.str(); } +template +struct severity_strings { + static const std::array, 5> value; +}; + +template <> +const std::array, 5> severity_strings::value = {"Performance", "Debug", "Notice", "Warning", "Error"}; + +template <> +const std::array, 5> severity_strings::value = {L"Performance", L"Debug", L"Notice", L"Warning", L"Error"}; + +template +void plain_text_message(T& os, const boost::optional& current_product, Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseInterface* instance) { + os << "[" << severity_strings::value[type] << "] "; + os << "[" << get_time(type <= Logger::LOG_PERF).c_str() << "] "; + if (current_product) { + std::string global_id = *((IfcUtil::IfcBaseEntity*)*current_product)->get("GlobalId"); + os << "{" << global_id.c_str() << "} "; + } + os << message.c_str() << std::endl; + if (instance) { + std::string instance_string = instance->data().toString(); + if (instance_string.size() > 259) { + instance_string = instance_string.substr(0, 256) + "..."; + } + os << instance_string.c_str() << std::endl; + } +} + +template +std::basic_string string_as(const std::string& s) { + std::basic_string v; + v.assign(s.begin(), s.end()); + return v; +} + +template +void json_message(T& os, const boost::optional& current_product, Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseInterface* instance) { + boost::property_tree::basic_ptree, std::basic_string> pt; + + // @todo this is crazy + static const typename T::char_type time_string[] = {'t', 'i', 'm', 'e', 0}; + static const typename T::char_type level_string[] = {'l', 'e', 'v', 'e', 'l', 0}; + static const typename T::char_type product_string[] = {'p', 'r', 'o', 'd', 'u', 'c', 't', 0}; + static const typename T::char_type message_string[] = {'m', 'e', 's', 's', 'a', 'g', 'e', 0}; + static const typename T::char_type instance_string[] = {'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 0}; + + pt.put(level_string, severity_strings::value[type]); + if (current_product) { + pt.put(product_string, string_as((**current_product).data().toString())); + } + pt.put(message_string, string_as(message)); + if (instance) { + pt.put(instance_string, string_as(instance->data().toString())); + } + + pt.put(time_string, string_as(get_time())); + + boost::property_tree::write_json(os, pt, false); +} +} // namespace + void Logger::SetProduct(boost::optional product) { - if (verbosity <= LOG_DEBUG && product) { - Message(LOG_DEBUG, "Begin processing", *product); - } - if (!product && print_perf_stats_on_element) { - PrintPerformanceStats(); - performance_statistics.clear(); - } - current_product = product; + if (verbosity <= LOG_DEBUG && product) { + Message(LOG_DEBUG, "Begin processing", *product); + } + if (!product && print_perf_stats_on_element) { + PrintPerformanceStats(); + performance_statistics.clear(); + } + current_product = product; } void Logger::SetOutput(std::ostream* l1, std::ostream* l2) { - wlog1 = wlog2 = 0; - log1 = l1; - log2 = l2; - if (!log2) { - log2 = &log_stream; - } + wlog1 = wlog2 = 0; + log1 = l1; + log2 = l2; + if (!log2) { + log2 = &log_stream; + } } void Logger::SetOutput(std::wostream* l1, std::wostream* l2) { - log1 = log2 = 0; - wlog1 = l1; - wlog2 = l2; - if (!wlog2) { - log2 = &log_stream; - } + log1 = log2 = 0; + wlog1 = l1; + wlog2 = l2; + if (!wlog2) { + log2 = &log_stream; + } } void Logger::Message(Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseInterface* instance) { - static std::mutex m; - std::lock_guard lk(m); + static std::mutex m; + std::lock_guard lk(m); - if (type == LOG_PERF) { - if (!first_timepoint) { - first_timepoint = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()).time_since_epoch().count(); - } - double t0 = (std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()).time_since_epoch().count() - *first_timepoint) / 1.e9; - if (message.substr(0, 5) == "done ") { - auto orig = message.substr(5); - performance_statistics[orig] += t0 - performance_signal_start[orig]; - } else { - performance_signal_start[message] = t0; - } - } + if (type == LOG_PERF) { + if (!first_timepoint) { + first_timepoint = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()).time_since_epoch().count(); + } + double t0 = (std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()).time_since_epoch().count() - *first_timepoint) / 1.e9; + if (message.substr(0, 5) == "done ") { + auto orig = message.substr(5); + performance_statistics[orig] += t0 - performance_signal_start[orig]; + } else { + performance_signal_start[message] = t0; + } + } - if (type > max_severity) { - max_severity = type; - } - if ((log2 || wlog2) && type >= verbosity) { - if (format == FMT_PLAIN) { + if (type > max_severity) { + max_severity = type; + } + if ((log2 || wlog2) && type >= verbosity) { + if (format == FMT_PLAIN) { if (log2) { plain_text_message(*log2, current_product, type, message, instance); } else if (wlog2) { plain_text_message(*wlog2, current_product, type, message, instance); } - } else if (format == FMT_JSON) { + } else if (format == FMT_JSON) { if (log2) { json_message(*log2, current_product, type, message, instance); } else if (wlog2) { json_message(*wlog2, current_product, type, message, instance); } - } - } + } + } } void Logger::Message(Logger::Severity type, const std::exception& exception, const IfcUtil::IfcBaseInterface* instance) { - Message(type, std::string(exception.what()), instance); + Message(type, std::string(exception.what()), instance); } template void status(T& log1, const std::string& message, bool new_line) { - log1 << message.c_str(); - if (new_line) { - log1 << std::endl; - } else { - log1 << std::flush; - } + log1 << message.c_str(); + if (new_line) { + log1 << std::endl; + } else { + log1 << std::flush; + } } void Logger::Status(const std::string& message, bool new_line) { - if (log1) { - status(*log1, message, new_line); - } else if (wlog1) { - status(*wlog1, message, new_line); - } + if (log1) { + status(*log1, message, new_line); + } else if (wlog1) { + status(*wlog1, message, new_line); + } } void Logger::ProgressBar(int progress) { - Status("\r[" + std::string(progress,'#') + std::string(50 - progress,' ') + "]", false); + Status("\r[" + std::string(progress, '#') + std::string(50 - progress, ' ') + "]", false); } std::string Logger::GetLog() { - return log_stream.str(); + return log_stream.str(); } void Logger::PrintPerformanceStats() { - std::vector> items; - for (auto& p : performance_statistics) { - items.push_back({ p.second, p.first }); - } + std::vector> items; + for (auto& p : performance_statistics) { + items.push_back({p.second, p.first}); + } - std::sort(items.begin(), items.end()); - std::reverse(items.begin(), items.end()); + std::sort(items.begin(), items.end()); + std::reverse(items.begin(), items.end()); - size_t max_size = 0; - for (auto& p : items) { - if (p.second.size() > max_size) { - max_size = p.second.size(); - } - } + size_t max_size = 0; + for (auto& p : items) { + if (p.second.size() > max_size) { + max_size = p.second.size(); + } + } - for (auto& p : items) { - auto s = p.second + std::string(max_size - p.second.size(), ' ') + ": " + std::to_string(p.first); - Message(LOG_PERF, s); - } + for (auto& p : items) { + auto s = p.second + std::string(max_size - p.second.size(), ' ') + ": " + std::to_string(p.first); + Message(LOG_PERF, s); + } } void Logger::Verbosity(Logger::Severity v) { verbosity = v; } @@ -252,4 +250,4 @@ boost::optional Logger::current_product; boost::optional Logger::first_timepoint; std::map Logger::performance_statistics; std::map Logger::performance_signal_start; -bool Logger::print_perf_stats_on_element = false; \ No newline at end of file +bool Logger::print_perf_stats_on_element = false; diff --git a/src/ifcparse/IfcLogger.h b/src/ifcparse/IfcLogger.h index 1133e3a279..0534813254 100644 --- a/src/ifcparse/IfcLogger.h +++ b/src/ifcparse/IfcLogger.h @@ -20,93 +20,100 @@ #ifndef IFCLOGGER_H #define IFCLOGGER_H -#include "../ifcparse/IfcBaseClass.h" +#include "ifc_parse_api.h" +#include "IfcBaseClass.h" -#include -#include -#include -#include -#include #include -#include - #include #include - -#include "ifc_parse_api.h" +#include +#include +#include +#include +#include +#include class IFC_PARSE_API Logger { -public: - typedef enum { LOG_PERF, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, LOG_ERROR } Severity; - typedef enum { FMT_PLAIN, FMT_JSON } Format; -private: + public: + typedef enum { + LOG_PERF, + LOG_DEBUG, + LOG_NOTICE, + LOG_WARNING, + LOG_ERROR + } Severity; + typedef enum { + FMT_PLAIN, + FMT_JSON + } Format; - // To both stream variants need to exist at runtime or should this be a - // template argument of Logger or controlled using preprocessor directives? - static std::ostream* log1; - static std::ostream* log2; - - static std::wostream* wlog1; - static std::wostream* wlog2; + private: + // To both stream variants need to exist at runtime or should this be a + // template argument of Logger or controlled using preprocessor directives? + static std::ostream* log1; + static std::ostream* log2; - static std::stringstream log_stream; + static std::wostream* wlog1; + static std::wostream* wlog2; - static Severity verbosity; - static Format format; - static boost::optional current_product; - static Severity max_severity; + static std::stringstream log_stream; - static boost::optional first_timepoint; - static std::map performance_statistics; - static std::map performance_signal_start; + static Severity verbosity; + static Format format; + static boost::optional current_product; + static Severity max_severity; - static bool print_perf_stats_on_element; + static boost::optional first_timepoint; + static std::map performance_statistics; + static std::map performance_signal_start; -public: - static void SetProduct(boost::optional product); + static bool print_perf_stats_on_element; - /// Determines to what stream respectively progress and errors are logged - static void SetOutput(std::wostream* l1, std::wostream* l2); - - /// Determines to what stream respectively progress and errors are logged - static void SetOutput(std::ostream* l1, std::ostream* l2); + public: + static void SetProduct(boost::optional product); - /// Determines the types of log messages to get logged - static void Verbosity(Severity v); - static Severity Verbosity(); - static Severity MaxSeverity(); + /// Determines to what stream respectively progress and errors are logged + static void SetOutput(std::wostream* l1, std::wostream* l2); - /// Determines output format: plain text or sequence of JSON objects - static void OutputFormat(Format f); - static Format OutputFormat(); - - /// Log a message to the output stream - static void Message(Severity type, const std::string& message, const IfcUtil::IfcBaseInterface* instance = 0); - static void Message(Severity type, const std::exception& message, const IfcUtil::IfcBaseInterface* instance = 0); - - static void Notice(const std::string& message, const IfcUtil::IfcBaseInterface* instance = 0) { Message(LOG_NOTICE, message, instance); } + /// Determines to what stream respectively progress and errors are logged + static void SetOutput(std::ostream* l1, std::ostream* l2); + + /// Determines the types of log messages to get logged + static void Verbosity(Severity v); + static Severity Verbosity(); + static Severity MaxSeverity(); + + /// Determines output format: plain text or sequence of JSON objects + static void OutputFormat(Format f); + static Format OutputFormat(); + + /// Log a message to the output stream + static void Message(Severity type, const std::string& message, const IfcUtil::IfcBaseInterface* instance = 0); + static void Message(Severity type, const std::exception& message, const IfcUtil::IfcBaseInterface* instance = 0); + + static void Notice(const std::string& message, const IfcUtil::IfcBaseInterface* instance = 0) { Message(LOG_NOTICE, message, instance); } static void Warning(const std::string& message, const IfcUtil::IfcBaseInterface* instance = 0) { Message(LOG_WARNING, message, instance); } static void Error(const std::string& message, const IfcUtil::IfcBaseInterface* instance = 0) { Message(LOG_ERROR, message, instance); } - - static void Notice(const std::exception& exception, const IfcUtil::IfcBaseInterface* instance = 0) { Message(LOG_NOTICE, exception, instance); } - static void Warning(const std::exception& exception, const IfcUtil::IfcBaseInterface* instance = 0) { Message(LOG_WARNING, exception, instance); } - static void Error(const std::exception& exception, const IfcUtil::IfcBaseInterface* instance = 0) { Message(LOG_ERROR, exception, instance); } - static void Status(const std::string& message, bool new_line=true); + static void Notice(const std::exception& exception, const IfcUtil::IfcBaseInterface* instance = 0) { Message(LOG_NOTICE, exception, instance); } + static void Warning(const std::exception& exception, const IfcUtil::IfcBaseInterface* instance = 0) { Message(LOG_WARNING, exception, instance); } + static void Error(const std::exception& exception, const IfcUtil::IfcBaseInterface* instance = 0) { Message(LOG_ERROR, exception, instance); } - static void ProgressBar(int progress); - static std::string GetLog(); - static void PrintPerformanceStats(); - static void PrintPerformanceStatsOnElement(bool b) { print_perf_stats_on_element = b; } + static void Status(const std::string& message, bool new_line = true); + + static void ProgressBar(int progress); + static std::string GetLog(); + static void PrintPerformanceStats(); + static void PrintPerformanceStatsOnElement(bool b) { print_perf_stats_on_element = b; } }; -#define PERF(x) \ -\ -Logger::Message(Logger::LOG_PERF, x);\ -\ -BOOST_SCOPE_EXIT(void) { \ -Logger::Message(Logger::LOG_PERF, "done " + std::string(x));\ -} BOOST_SCOPE_EXIT_END - +#define PERF(x) \ + \ + Logger::Message(Logger::LOG_PERF, x); \ + \ + BOOST_SCOPE_EXIT(void) { \ + Logger::Message(Logger::LOG_PERF, "done " + std::string(x)); \ + } \ + BOOST_SCOPE_EXIT_END #endif diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index c1e2895b7c..f3bc6257e2 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -17,48 +17,48 @@ * * ********************************************************************************/ -#include "../ifcparse/IfcCharacterDecoder.h" -#include "../ifcparse/IfcParse.h" -#include "../ifcparse/IfcException.h" -#include "../ifcparse/IfcBaseClass.h" -#include "../ifcparse/IfcSpfStream.h" -#include "../ifcparse/IfcFile.h" -#include "../ifcparse/IfcSIPrefix.h" -#include "../ifcparse/IfcSchema.h" -#include "../ifcparse/utils.h" +#include "IfcParse.h" + +#include "IfcBaseClass.h" +#include "IfcCharacterDecoder.h" +#include "IfcException.h" +#include "IfcFile.h" +#include "IfcSchema.h" +#include "IfcSIPrefix.h" +#include "IfcSpfStream.h" +#include "utils.h" #ifdef USE_MMAP #include #endif -#include +#include +#include +#include +#include #include #include -#include +#include #include #include -#include - -#include -#include -#include +#include #define PERMISSIVE_FLOAT using namespace IfcParse; -// A static locale for the real number parser. strtod() is locale-dependent, causing issues -// in locales that have ',' as a decimal separator. Therefore the non standard _strtod_l() / -// strtod_l() is used and a reference to the "C" locale is obtained here. The alternative is -// to use std::istringstream::imbue(std::locale::classic()), but there are subtleties in -// parsing in MSVC2010 and it appears to be much slower. +// A static locale for the real number parser. strtod() is locale-dependent, causing issues +// in locales that have ',' as a decimal separator. Therefore the non standard _strtod_l() / +// strtod_l() is used and a reference to the "C" locale is obtained here. The alternative is +// to use std::istringstream::imbue(std::locale::classic()), but there are subtleties in +// parsing in MSVC2010 and it appears to be much slower. #if defined(_MSC_VER) -static _locale_t locale = (_locale_t) 0; +static _locale_t locale = (_locale_t)0; void init_locale() { - if (locale == (_locale_t) 0) { - locale = _create_locale(LC_NUMERIC, "C"); - } + if (locale == (_locale_t)0) { + locale = _create_locale(LC_NUMERIC, "C"); + } } #else @@ -73,14 +73,14 @@ static locale_t locale = (locale_t)0; void init_locale() {} double strtod_l(const char* start, char** end, locale_t loc) { - double d; - std::stringstream ss; - ss.imbue(std::locale::classic()); - ss << start; - ss >> d; - size_t nread = ss.tellg(); - *end = const_cast(start) + nread; - return d; + double d; + std::stringstream ss; + ss.imbue(std::locale::classic()); + ss << start; + ss >> d; + size_t nread = ss.tellg(); + *end = const_cast(start) + nread; + return d; } #else @@ -92,16 +92,16 @@ double strtod_l(const char* start, char** end, locale_t loc) { static locale_t locale = (locale_t)0; void init_locale() { - if (locale == (locale_t)0) { - locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0); - } + if (locale == (locale_t)0) { + locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0); + } } #endif #endif -// +// // Opens the file and gets the filesize // #ifdef USE_MMAP @@ -109,202 +109,205 @@ IfcSpfStream::IfcSpfStream(const std::string& fn, bool mmap) #else IfcSpfStream::IfcSpfStream(const std::string& fn) #endif - : stream(0) - , buffer(0) - , valid(false) - , eof(false) -{ + : stream(0), + buffer(0), + valid(false), + eof(false) { #ifdef _MSC_VER - std::wstring fn_ws = IfcUtil::path::from_utf8(fn); - const wchar_t* fn_wide = fn_ws.c_str(); + std::wstring fn_ws = IfcUtil::path::from_utf8(fn); + const wchar_t* fn_wide = fn_ws.c_str(); #ifdef USE_MMAP - if (mmap) { - mfs = boost::iostreams::mapped_file_source(boost::filesystem::wpath(fn_wide)); - } else { + if (mmap) { + mfs = boost::iostreams::mapped_file_source(boost::filesystem::wpath(fn_wide)); + } else { #endif - stream = _wfopen(fn_wide, L"rb"); -#ifdef USE_MMAP - } + stream = _wfopen(fn_wide, L"rb"); +#ifdef USE_MMAP + } #endif #else #ifdef USE_MMAP - if (mmap) { - mfs = boost::iostreams::mapped_file_source(fn); - } else { + if (mmap) { + mfs = boost::iostreams::mapped_file_source(fn); + } else { #endif - stream = fopen(fn.c_str(), "rb"); -#ifdef USE_MMAP - } + stream = fopen(fn.c_str(), "rb"); +#ifdef USE_MMAP + } #endif #endif #ifdef USE_MMAP - if (mmap) { - if (!mfs.is_open()) { - return; - } + if (mmap) { + if (!mfs.is_open()) { + return; + } - valid = true; - buffer = mfs.data(); - ptr = 0; - len = mfs.size(); - } else { + valid = true; + buffer = mfs.data(); + ptr = 0; + len = mfs.size(); + } else { #endif - if (stream == NULL) { - return; - } + if (stream == NULL) { + return; + } - valid = true; - fseek(stream, 0, SEEK_END); - size = (unsigned int)ftell(stream); - rewind(stream); - char* buffer_rw = new char[size]; - len = (unsigned int)fread(buffer_rw, 1, size, stream); - buffer = buffer_rw; - eof = len == 0; - ptr = 0; - fclose(stream); - stream = nullptr; -#ifdef USE_MMAP - } + valid = true; + fseek(stream, 0, SEEK_END); + size = (unsigned int)ftell(stream); + rewind(stream); + char* buffer_rw = new char[size]; + len = (unsigned int)fread(buffer_rw, 1, size, stream); + buffer = buffer_rw; + eof = len == 0; + ptr = 0; + fclose(stream); + stream = nullptr; +#ifdef USE_MMAP + } #endif } IfcSpfStream::IfcSpfStream(std::istream& f, int l) - : stream(0) - , buffer(0) -{ - eof = false; - size = l; - char* buffer_rw = new char[size]; - f.read(buffer_rw,size); - buffer = buffer_rw; - valid = f.gcount() == size; - ptr = 0; - len = l; + : stream(0), + buffer(0) { + eof = false; + size = l; + char* buffer_rw = new char[size]; + f.read(buffer_rw, size); + buffer = buffer_rw; + valid = f.gcount() == size; + ptr = 0; + len = l; } IfcSpfStream::IfcSpfStream(void* data, int l) - : stream(0) - , buffer(0) -{ - eof = false; - size = l; - buffer = (char*) data; - valid = true; - ptr = 0; - len = l; + : stream(0), + buffer(0) { + eof = false; + size = l; + buffer = (char*)data; + valid = true; + ptr = 0; + len = l; } -IfcSpfStream::~IfcSpfStream() -{ - Close(); +IfcSpfStream::~IfcSpfStream() { + Close(); } void IfcSpfStream::Close() { #ifdef USE_MMAP - if (mfs.is_open()) { - mfs.close(); - return; - } + if (mfs.is_open()) { + mfs.close(); + return; + } #endif - delete[] buffer; - if (stream) { - fclose(stream); - } + delete[] buffer; + if (stream) { + fclose(stream); + } } // // Seeks an arbitrary position in the file // void IfcSpfStream::Seek(unsigned int o) { - ptr = o; - if (ptr >= len) throw IfcException("Reading outside of file limits"); - eof = false; + ptr = o; + if (ptr >= len) { + throw IfcException("Reading outside of file limits"); + } + eof = false; } // // Returns the character at the cursor // char IfcSpfStream::Peek() { - return buffer[ptr]; + return buffer[ptr]; } // // Returns the character at specified offset // char IfcSpfStream::Read(unsigned int o) { - return buffer[o]; + return buffer[o]; } // // Returns the cursor position // unsigned int IfcSpfStream::Tell() { - return ptr; + return ptr; } // // Increments cursor and reads new chunk if necessary // void IfcSpfStream::Inc() { - if ( ++ptr == len ) { - eof = true; - return; - } - const char current = IfcSpfStream::Peek(); - if (current == '\n' || current == '\r') { - // NB this is recursive. It might as well be a loop. - IfcSpfStream::Inc(); - } + if (++ptr == len) { + eof = true; + return; + } + const char current = IfcSpfStream::Peek(); + if (current == '\n' || current == '\r') { + // NB this is recursive. It might as well be a loop. + IfcSpfStream::Inc(); + } } -IfcSpfLexer::IfcSpfLexer(IfcParse::IfcSpfStream *s, IfcParse::IfcFile* f) { - file = f; - stream = s; - decoder = new IfcCharacterDecoder(s); +IfcSpfLexer::IfcSpfLexer(IfcParse::IfcSpfStream* s, IfcParse::IfcFile* f) { + file = f; + stream = s; + decoder = new IfcCharacterDecoder(s); } IfcSpfLexer::~IfcSpfLexer() { - delete decoder; + delete decoder; } unsigned int IfcSpfLexer::skipWhitespace() { - unsigned int n = 0; - while ( !stream->eof ) { - char c = stream->Peek(); - if ( (c == ' ' || c == '\r' || c == '\n' || c == '\t' ) ) { - stream->Inc(); - ++n; - } - else break; - } - return n; + unsigned int n = 0; + while (!stream->eof) { + char c = stream->Peek(); + if ((c == ' ' || c == '\r' || c == '\n' || c == '\t')) { + stream->Inc(); + ++n; + } else { + break; + } + } + return n; } unsigned int IfcSpfLexer::skipComment() { - char c = stream->Peek(); - if (c != '/') return 0; - stream->Inc(); - c = stream->Peek(); - if (c != '*') { - stream->Seek(stream->Tell() - 1); - return 0; - } - unsigned int n = 2; - char p = 0; - while ( !stream->eof ) { - c = stream->Peek(); - stream->Inc(); - ++ n; - if (c == '/' && p == '*') break; - p = c; - } - return n; + char c = stream->Peek(); + if (c != '/') { + return 0; + } + stream->Inc(); + c = stream->Peek(); + if (c != '*') { + stream->Seek(stream->Tell() - 1); + return 0; + } + unsigned int n = 2; + char p = 0; + while (!stream->eof) { + c = stream->Peek(); + stream->Inc(); + ++n; + if (c == '/' && p == '*') { + break; + } + p = c; + } + return n; } // @@ -312,564 +315,584 @@ unsigned int IfcSpfLexer::skipComment() { // Token IfcSpfLexer::Next() { - if ( stream->eof ) return NoneTokenPtr(); + if (stream->eof) { + return NoneTokenPtr(); + } - while (skipWhitespace() || skipComment()) {} - - if ( stream->eof ) return NoneTokenPtr(); - unsigned int pos = stream->Tell(); + while (skipWhitespace() || skipComment()) { + } - char c = stream->Peek(); - - // If the cursor is at [()=,;$*] we know token consists of single char - if (c == '(' || c == ')' || c == '=' || c == ',' || c == ';' || c == '$' || c == '*') { - stream->Inc(); - return OperatorTokenPtr(this, pos, pos+1); - } + if (stream->eof) { + return NoneTokenPtr(); + } + unsigned int pos = stream->Tell(); - int len = 0; + char c = stream->Peek(); - while ( ! stream->eof ) { + // If the cursor is at [()=,;$*] we know token consists of single char + if (c == '(' || c == ')' || c == '=' || c == ',' || c == ';' || c == '$' || c == '*') { + stream->Inc(); + return OperatorTokenPtr(this, pos, pos + 1); + } - // Read character and increment pointer if not starting a new token - c = stream->Peek(); - if ( len && (c == '(' || c == ')' || c == '=' || c == ',' || c == ';' || c == '/') ) break; - stream->Inc(); - len ++; + int len = 0; - // If a string is encountered defer processing to the IfcCharacterDecoder - if ( c == '\'' ) decoder->skip(); - } - if ( len ) return GeneralTokenPtr(this, pos, stream->Tell()); - else return NoneTokenPtr(); + while (!stream->eof) { + + // Read character and increment pointer if not starting a new token + c = stream->Peek(); + if (len && (c == '(' || c == ')' || c == '=' || c == ',' || c == ';' || c == '/')) { + break; + } + stream->Inc(); + len++; + + // If a string is encountered defer processing to the IfcCharacterDecoder + if (c == '\'') { + decoder->skip(); + } + } + if (len) { + return GeneralTokenPtr(this, pos, stream->Tell()); + } else { + return NoneTokenPtr(); + } } bool IfcSpfStream::is_eof_at(unsigned int local_ptr) { - return local_ptr >= len; + return local_ptr >= len; } void IfcSpfStream::increment_at(unsigned int& local_ptr) { - if (++local_ptr == len) { - return; - } - const char current = IfcSpfStream::peek_at(local_ptr); - if (current == '\n' || current == '\r') IfcSpfStream::increment_at(local_ptr); + if (++local_ptr == len) { + return; + } + const char current = IfcSpfStream::peek_at(local_ptr); + if (current == '\n' || current == '\r') { + IfcSpfStream::increment_at(local_ptr); + } } char IfcSpfStream::peek_at(unsigned int local_ptr) { - return buffer[local_ptr]; + return buffer[local_ptr]; } // // Reads a std::string from the file at specified offset // Omits whitespace and comments // -void IfcSpfLexer::TokenString(unsigned int offset, std::string &buffer) { - buffer.clear(); - while (!stream->is_eof_at(offset)) { - char c = stream->peek_at(offset); - if ( buffer.size() && (c == '(' || c == ')' || c == '=' || c == ',' || c == ';' || c == '/') ) break; - stream->increment_at(offset); - if ( c == ' ' || c == '\r' || c == '\n' || c == '\t' ) continue; - else if ( c == '\'' ) { - // todo, make decoder use local offset ptr - buffer = decoder->get(offset); - break; - } - else buffer.push_back(c); - } +void IfcSpfLexer::TokenString(unsigned int offset, std::string& buffer) { + buffer.clear(); + while (!stream->is_eof_at(offset)) { + char c = stream->peek_at(offset); + if (buffer.size() && (c == '(' || c == ')' || c == '=' || c == ',' || c == ';' || c == '/')) { + break; + } + stream->increment_at(offset); + if (c == ' ' || c == '\r' || c == '\n' || c == '\t') { + continue; + } else if (c == '\'') { + // todo, make decoder use local offset ptr + buffer = decoder->get(offset); + break; + } else { + buffer.push_back(c); + } + } } //Note: according to STEP standard, there may be newlines in tokens -inline void RemoveTokenSeparators(IfcSpfStream* stream, unsigned start, unsigned end, std::string &oDestination) { - oDestination.clear(); - for (unsigned i = start; i < end; i++) { - char c = stream->Read(i); - if (c == ' ' || c == '\r' || c == '\n' || c == '\t') - continue; - oDestination += c; - } +inline void RemoveTokenSeparators(IfcSpfStream* stream, unsigned start, unsigned end, std::string& oDestination) { + oDestination.clear(); + for (unsigned i = start; i < end; i++) { + char c = stream->Read(i); + if (c == ' ' || c == '\r' || c == '\n' || c == '\t') { + continue; + } + oDestination += c; + } } -bool ParseInt(const char *pStart, int &val) { - char* pEnd; - long result = strtol(pStart, &pEnd, 10); - if (*pEnd != 0) - return false; - val = (int)result; - return true; +bool ParseInt(const char* pStart, int& val) { + char* pEnd; + long result = strtol(pStart, &pEnd, 10); + if (*pEnd != 0) { + return false; + } + val = (int)result; + return true; } -bool ParseFloat(const char *pStart, double &val) { - char* pEnd; +bool ParseFloat(const char* pStart, double& val) { + char* pEnd; #ifdef _MSC_VER - double result = _strtod_l(pStart, &pEnd, locale); + double result = _strtod_l(pStart, &pEnd, locale); #else - double result = strtod_l(pStart, &pEnd, locale); + double result = strtod_l(pStart, &pEnd, locale); #endif - if (*pEnd != 0) - return false; - val = result; - return true; + if (*pEnd != 0) { + return false; + } + val = result; + return true; } -bool ParseBool(const char *pStart, int &val) { - if (strlen(pStart) != 3 || pStart[0] != '.' || pStart[2] != '.') - return false; - char mid = pStart[1]; - - if (mid == 'T') { - val = 1; - } else if (mid == 'F') { - val = 0; - } else if (mid == 'U') { - val = 2; - } else { - return false; - } +bool ParseBool(const char* pStart, int& val) { + if (strlen(pStart) != 3 || pStart[0] != '.' || pStart[2] != '.') { + return false; + } + char mid = pStart[1]; - return true; + if (mid == 'T') { + val = 1; + } else if (mid == 'F') { + val = 0; + } else if (mid == 'U') { + val = 2; + } else { + return false; + } + + return true; } Token IfcParse::OperatorTokenPtr(IfcSpfLexer* lexer, unsigned start, unsigned end) { - char first = lexer->stream->Read(start); - Token token(lexer, start, end, Token_OPERATOR); - token.value_char = first; - return token; + char first = lexer->stream->Read(start); + Token token(lexer, start, end, Token_OPERATOR); + token.value_char = first; + return token; } Token IfcParse::GeneralTokenPtr(IfcSpfLexer* lexer, unsigned start, unsigned end) { - Token token(lexer, start, end, Token_NONE); + Token token(lexer, start, end, Token_NONE); - //extract token into temp buffer (remove eol-s, no encoding changes) - std::string &tokenStr = lexer->GetTempString(); - RemoveTokenSeparators(lexer->stream, start, end, tokenStr); - - //determine type of the token - char first = lexer->stream->Read(start); - if (first == '#') { - token.type = Token_IDENTIFIER; - if (!ParseInt(tokenStr.c_str() + 1, token.value_int)) - throw IfcException("Identifier token as not integer"); - } - else if (first == '\'') - token.type = Token_STRING; - else if (first == '.') { - token.type = Token_ENUMERATION; - if (ParseBool(tokenStr.c_str(), token.value_int)) //bool is also enumeration - token.type = Token_BOOL; - } - else if (first == '"') - token.type = Token_BINARY; - else if (ParseInt(tokenStr.c_str(), token.value_int)) - token.type = Token_INT; - else if (ParseFloat(tokenStr.c_str(), token.value_double)) - token.type = Token_FLOAT; - else - token.type = Token_KEYWORD; + //extract token into temp buffer (remove eol-s, no encoding changes) + std::string& tokenStr = lexer->GetTempString(); + RemoveTokenSeparators(lexer->stream, start, end, tokenStr); - return token; + //determine type of the token + char first = lexer->stream->Read(start); + if (first == '#') { + token.type = Token_IDENTIFIER; + if (!ParseInt(tokenStr.c_str() + 1, token.value_int)) { + throw IfcException("Identifier token as not integer"); + } + } else if (first == '\'') { + token.type = Token_STRING; + } else if (first == '.') { + token.type = Token_ENUMERATION; + if (ParseBool(tokenStr.c_str(), token.value_int)) { //bool is also enumeration + token.type = Token_BOOL; + } + } else if (first == '"') { + token.type = Token_BINARY; + } else if (ParseInt(tokenStr.c_str(), token.value_int)) { + token.type = Token_INT; + } else if (ParseFloat(tokenStr.c_str(), token.value_double)) { + token.type = Token_FLOAT; + } else { + token.type = Token_KEYWORD; + } + + return token; } Token IfcParse::NoneTokenPtr() { return Token(); } - bool TokenFunc::isOperator(const Token& t) { - return t.type == Token_OPERATOR; + return t.type == Token_OPERATOR; } bool TokenFunc::isOperator(const Token& t, char op) { - return t.type == Token_OPERATOR && t.value_char == op; + return t.type == Token_OPERATOR && t.value_char == op; } bool TokenFunc::isIdentifier(const Token& t) { - return t.type == Token_IDENTIFIER; + return t.type == Token_IDENTIFIER; } bool TokenFunc::isString(const Token& t) { - return t.type == Token_STRING; + return t.type == Token_STRING; } bool TokenFunc::isEnumeration(const Token& t) { - return t.type == Token_ENUMERATION || t.type == Token_BOOL; + return t.type == Token_ENUMERATION || t.type == Token_BOOL; } bool TokenFunc::isBinary(const Token& t) { - return t.type == Token_BINARY; + return t.type == Token_BINARY; } bool TokenFunc::isKeyword(const Token& t) { - return t.type == Token_KEYWORD; + return t.type == Token_KEYWORD; } bool TokenFunc::isInt(const Token& t) { - return t.type == Token_INT; + return t.type == Token_INT; } bool TokenFunc::isBool(const Token& t) { - // Bool and logical share the same storage type, just logical unknown is stored as 2. - return t.type == Token_BOOL && t.value_int != 2; + // Bool and logical share the same storage type, just logical unknown is stored as 2. + return t.type == Token_BOOL && t.value_int != 2; } bool TokenFunc::isLogical(const Token& t) { - return t.type == Token_BOOL; + return t.type == Token_BOOL; } bool TokenFunc::isFloat(const Token& t) { #ifdef PERMISSIVE_FLOAT - /// NB: We are being more permissive here then allowed by the standard - return t.type == Token_FLOAT || t.type == Token_INT; + /// NB: We are being more permissive here then allowed by the standard + return t.type == Token_FLOAT || t.type == Token_INT; #else - return t.type == Token_FLOAT; + return t.type == Token_FLOAT; #endif } int TokenFunc::asInt(const Token& t) { - if (t.type != Token_INT) { - throw IfcInvalidTokenException(t.startPos, toString(t), "integer"); - } - return t.value_int; + if (t.type != Token_INT) { + throw IfcInvalidTokenException(t.startPos, toString(t), "integer"); + } + return t.value_int; } int TokenFunc::asIdentifier(const Token& t) { - if (t.type != Token_IDENTIFIER) { - throw IfcInvalidTokenException(t.startPos, toString(t), "instance name"); - } - return t.value_int; + if (t.type != Token_IDENTIFIER) { + throw IfcInvalidTokenException(t.startPos, toString(t), "instance name"); + } + return t.value_int; } bool TokenFunc::asBool(const Token& t) { - if (t.type != Token_BOOL) { - throw IfcInvalidTokenException(t.startPos, toString(t), "boolean"); - } - return t.value_int == 1; + if (t.type != Token_BOOL) { + throw IfcInvalidTokenException(t.startPos, toString(t), "boolean"); + } + return t.value_int == 1; } boost::logic::tribool TokenFunc::asLogical(const Token& t) { - if (t.type != Token_BOOL) { - throw IfcInvalidTokenException(t.startPos, toString(t), "boolean"); - } + if (t.type != Token_BOOL) { + throw IfcInvalidTokenException(t.startPos, toString(t), "boolean"); + } - if (t.value_int == 0) { - return false; - } else if (t.value_int == 1) { - return true; - } else { - return boost::logic::indeterminate; - } + if (t.value_int == 0) { + return false; + } else if (t.value_int == 1) { + return true; + } else { + return boost::logic::indeterminate; + } } double TokenFunc::asFloat(const Token& t) { #ifdef PERMISSIVE_FLOAT - if (t.type == Token_INT) { - /// NB: We are being more permissive here then allowed by the standard - return t.value_int; - } else // ----> continues beyond preprocessor directive + if (t.type == Token_INT) { + /// NB: We are being more permissive here then allowed by the standard + return t.value_int; + } else // ----> continues beyond preprocessor directive #endif - if (t.type == Token_FLOAT) { - return t.value_double; - } else { - throw IfcInvalidTokenException(t.startPos, toString(t), "real"); - } + if (t.type == Token_FLOAT) { + return t.value_double; + } else { + throw IfcInvalidTokenException(t.startPos, toString(t), "real"); + } } -const std::string &TokenFunc::asStringRef(const Token& t) { +const std::string& TokenFunc::asStringRef(const Token& t) { if (t.type == Token_NONE) { throw IfcParse::IfcException("Null token encountered, premature end of file?"); } - std::string &str = t.lexer->GetTempString(); - t.lexer->TokenString(t.startPos, str); - if ((isString(t) || isEnumeration(t) || isBinary(t)) && !str.empty()) { - //remove start+end characters in-place - str.erase(str.end()-1); - str.erase(str.begin()); - } - return str; + std::string& str = t.lexer->GetTempString(); + t.lexer->TokenString(t.startPos, str); + if ((isString(t) || isEnumeration(t) || isBinary(t)) && !str.empty()) { + //remove start+end characters in-place + str.erase(str.end() - 1); + str.erase(str.begin()); + } + return str; } std::string TokenFunc::asString(const Token& t) { - if (isString(t) || isEnumeration(t) || isBinary(t)) { - return asStringRef(t); - } else { - throw IfcInvalidTokenException(t.startPos, toString(t), "string"); - } + if (isString(t) || isEnumeration(t) || isBinary(t)) { + return asStringRef(t); + } else { + throw IfcInvalidTokenException(t.startPos, toString(t), "string"); + } } boost::dynamic_bitset<> TokenFunc::asBinary(const Token& t) { - const std::string &str = asStringRef(t); - if (str.size() < 1) { - throw IfcException("Token is not a valid binary sequence"); - } - - std::string::const_iterator it = str.begin(); - int n = *it - '0'; - if ((n < 0 || n > 3) || (str.size() == 1 && n != 0)) { - throw IfcException("Token is not a valid binary sequence"); - } + const std::string& str = asStringRef(t); + if (str.size() < 1) { + throw IfcException("Token is not a valid binary sequence"); + } - ++it; - unsigned i = ((unsigned)str.size()-1) * 4 - n; - boost::dynamic_bitset<> bitset(i); + std::string::const_iterator it = str.begin(); + int n = *it - '0'; + if ((n < 0 || n > 3) || (str.size() == 1 && n != 0)) { + throw IfcException("Token is not a valid binary sequence"); + } - for(; it != str.end(); ++it) { - const std::string::value_type& c = *it; - int value = (c < 'A') ? (c - '0') : (c - 'A' + 10); - for (unsigned j = 0; j < 4; ++j) { - if (i-- == 0) break; - if (value & (1 << (3-j))) { - bitset.set(i); - } - } - } + ++it; + unsigned i = ((unsigned)str.size() - 1) * 4 - n; + boost::dynamic_bitset<> bitset(i); - return bitset; + for (; it != str.end(); ++it) { + const std::string::value_type& c = *it; + int value = (c < 'A') ? (c - '0') : (c - 'A' + 10); + for (unsigned j = 0; j < 4; ++j) { + if (i-- == 0) { + break; + } + if (value & (1 << (3 - j))) { + bitset.set(i); + } + } + } + + return bitset; } std::string TokenFunc::toString(const Token& t) { - std::string result; - t.lexer->TokenString(t.startPos, result); - return result; + std::string result; + t.lexer->TokenString(t.startPos, result); + return result; } - TokenArgument::TokenArgument(const Token& t) { - token = t; + token = t; } EntityArgument::EntityArgument(const Token& t) { - IfcParse::IfcFile* file = t.lexer->file; - IfcEntityInstanceData* data = read(0, file, t.startPos); - // Data needs to be loaded, for the tokens - // to be consumed and parsing to continue. - data->load(); - entity = file->schema()->instantiate(data); + IfcParse::IfcFile* file = t.lexer->file; + IfcEntityInstanceData* data = read(0, file, t.startPos); + // Data needs to be loaded, for the tokens + // to be consumed and parsing to continue. + data->load(); + entity = file->schema()->instantiate(data); } namespace { - template - class vector_or_array { - std::vector* vector_; - T* array_; - size_t size_, index_; +template +class vector_or_array { + std::vector* vector_; + T* array_; + size_t size_, index_; - public: - vector_or_array(std::vector* vector) - : vector_(vector) - , array_(0) - , size_(0) - , index_(0) - {} + public: + vector_or_array(std::vector* 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) - {} + vector_or_array(Argument** arr, size_t size) + : vector_(0), + array_(arr), + size_(size), + index_(0) {} - void push_back(const T& t) { - // @todo this should log a warning when the size is exceeded - if (array_ && index_ < size_) { - array_[index_++] = t; - } else if (vector_) { - vector_->push_back(t); - } - } + void push_back(const T& t) { + // @todo this should log a warning when the size is exceeded + if (array_ && index_ < size_) { + array_[index_++] = t; + } else if (vector_) { + vector_->push_back(t); + } + } - size_t index() const { - if (vector_) { - return vector_->size(); - } else { - return index_; - } - } - }; -} + size_t index() const { + if (vector_) { + return vector_->size(); + } else { + return index_; + } + } +}; +} // namespace -// +// // Reads the arguments from a list of token // Aditionally, registers the ids (i.e. #[\d]+) in the inverse map // size_t IfcParse::IfcFile::load(unsigned entity_instance_name, const IfcParse::entity* entity, Argument**& attributes, size_t num_attributes, int attribute_index) { - Token next = tokens->Next(); + Token next = tokens->Next(); - std::vector* vector = 0; - vector_or_array filler(attributes, num_attributes); - if (attributes == 0) { - if (num_attributes != 0) { - // If num_attributes is zero we know this is a top-level entity instance (or header entity) being parsed. - // There can only be parsed one of these at a time, so we can reuse the vector we have defined at the file - // scope. - if (entity) { - vector = &internal_attribute_vector_; - } else { - vector = &internal_attribute_vector_simple_type_; - } - vector->clear(); - } else { - vector = new std::vector; - } - filler = vector_or_array(vector); - } + std::vector* vector = 0; + vector_or_array filler(attributes, num_attributes); + if (attributes == 0) { + if (num_attributes != 0) { + // If num_attributes is zero we know this is a top-level entity instance (or header entity) being parsed. + // There can only be parsed one of these at a time, so we can reuse the vector we have defined at the file + // scope. + if (entity) { + vector = &internal_attribute_vector_; + } else { + vector = &internal_attribute_vector_simple_type_; + } + vector->clear(); + } else { + vector = new std::vector; + } + filler = vector_or_array(vector); + } - size_t return_value = 0; + size_t return_value = 0; - while( next.startPos || next.lexer ) { - if ( TokenFunc::isOperator(next,',') ) { - // do nothing - } else if ( TokenFunc::isOperator(next,')') ) { - break; - } else if ( TokenFunc::isOperator(next,'(') ) { - return_value++; - ArgumentList* alist = new ArgumentList(); - // entity is passed along here, after all the it is the type of the instance - // that owns the list that is significant for inverse attributes - alist->size() = load(entity_instance_name, entity, alist->arguments(), 0, attribute_index == -1 ? (int)filler.index() : attribute_index); - filler.push_back(alist); - } else { - return_value++; - if (TokenFunc::isIdentifier(next)) { - if (!parsing_complete_) { - register_inverse(entity_instance_name, entity, next, attribute_index == -1 ? (int)filler.index() : attribute_index); - } - } - - if (TokenFunc::isKeyword(next)) { - try { - auto ea = new EntityArgument(next); - addEntity(((IfcUtil::IfcBaseClass*) *ea)); - filler.push_back(ea); - } catch (IfcException& e) { - Logger::Message(Logger::LOG_ERROR, e.what()); - } - } else { - filler.push_back(new TokenArgument(next)); - } + while (next.startPos || next.lexer) { + if (TokenFunc::isOperator(next, ',')) { + // do nothing + } else if (TokenFunc::isOperator(next, ')')) { + break; + } else if (TokenFunc::isOperator(next, '(')) { + return_value++; + ArgumentList* alist = new ArgumentList(); + // entity is passed along here, after all the it is the type of the instance + // that owns the list that is significant for inverse attributes + alist->size() = load(entity_instance_name, entity, alist->arguments(), 0, attribute_index == -1 ? (int)filler.index() : attribute_index); + filler.push_back(alist); + } else { + return_value++; + if (TokenFunc::isIdentifier(next)) { + if (!parsing_complete_) { + register_inverse(entity_instance_name, entity, next, attribute_index == -1 ? (int)filler.index() : attribute_index); + } + } - } - next = tokens->Next(); - } + if (TokenFunc::isKeyword(next)) { + try { + auto ea = new EntityArgument(next); + addEntity(((IfcUtil::IfcBaseClass*)*ea)); + filler.push_back(ea); + } catch (IfcException& e) { + Logger::Message(Logger::LOG_ERROR, e.what()); + } + } else { + filler.push_back(new TokenArgument(next)); + } + } + next = tokens->Next(); + } - if (vector) { - // Obviously don't try and create a 0-length array. - if (num_attributes || vector->size()) { - // @todo figure out whether all this logic is still necessary, since we know the - // expected amount of attributes and shouldn't be able to access more than allowed - // by the schema. - attributes = new Argument*[(std::max)(num_attributes, vector->size())]{ nullptr }; + if (vector) { + // Obviously don't try and create a 0-length array. + if (num_attributes || vector->size()) { + // @todo figure out whether all this logic is still necessary, since we know the + // expected amount of attributes and shouldn't be able to access more than allowed + // by the schema. + attributes = new Argument* [(std::max)(num_attributes, vector->size())] { nullptr }; - // @todo this appears unnecessary, we increment this in the loop already, - // which is more accurate as the filler can't go above it's size in case - // it uses the pre-allocated c-array. - // -> return_value = vector->size(); + // @todo this appears unnecessary, we increment this in the loop already, + // which is more accurate as the filler can't go above it's size in case + // it uses the pre-allocated c-array. + // -> return_value = vector->size(); - for (size_t i = 0; i < vector->size(); ++i) { - attributes[i] = vector->at(i); - } - } + for (size_t i = 0; i < vector->size(); ++i) { + attributes[i] = vector->at(i); + } + } - if ((vector != &internal_attribute_vector_) && (vector != &internal_attribute_vector_simple_type_)) { - delete vector; - } - } + if ((vector != &internal_attribute_vector_) && (vector != &internal_attribute_vector_simple_type_)) { + delete vector; + } + } - return return_value; + return return_value; } IfcUtil::ArgumentType ArgumentList::type() const { - if (size_ == 0) { - return IfcUtil::Argument_EMPTY_AGGREGATE; - } + if (size_ == 0) { + return IfcUtil::Argument_EMPTY_AGGREGATE; + } - const IfcUtil::ArgumentType elem_type = list_[0]->type(); - return IfcUtil::make_aggregate(elem_type); + const IfcUtil::ArgumentType elem_type = list_[0]->type(); + return IfcUtil::make_aggregate(elem_type); } // templated helper function for reading arguments into a list -template +template std::vector read_aggregate_as_vector(Argument** list, size_t size) { - std::vector return_value; - return_value.reserve(size); - for (size_t i = 0; i < size; ++i) { - return_value.push_back(*list[i]); - } - return return_value; + std::vector return_value; + return_value.reserve(size); + for (size_t i = 0; i < size; ++i) { + return_value.push_back(*list[i]); + } + return return_value; } -template -std::vector< std::vector > read_aggregate_of_aggregate_as_vector2(Argument** list, size_t size) { - std::vector< std::vector > return_value; - return_value.reserve(size); - for (size_t i = 0; i < size; ++i) { - return_value.push_back(*list[i]); - } - return return_value; +template +std::vector> read_aggregate_of_aggregate_as_vector2(Argument** list, size_t size) { + std::vector> return_value; + return_value.reserve(size); + for (size_t i = 0; i < size; ++i) { + return_value.push_back(*list[i]); + } + return return_value; } // // Functions for casting the ArgumentList to other types // ArgumentList::operator std::vector() const { - return read_aggregate_as_vector(list_, size_); + return read_aggregate_as_vector(list_, size_); } ArgumentList::operator std::vector() const { - return read_aggregate_as_vector(list_, size_); + return read_aggregate_as_vector(list_, size_); } ArgumentList::operator std::vector() const { - return read_aggregate_as_vector(list_, size_); + return read_aggregate_as_vector(list_, size_); } -ArgumentList::operator std::vector >() const { - return read_aggregate_as_vector >(list_, size_); +ArgumentList::operator std::vector>() const { + return read_aggregate_as_vector>(list_, size_); } ArgumentList::operator aggregate_of_instance::ptr() const { - aggregate_of_instance::ptr l ( new aggregate_of_instance() ); - for (size_t i = 0; i < size_; ++i) { - // FIXME: account for $ + aggregate_of_instance::ptr l(new aggregate_of_instance()); + for (size_t i = 0; i < size_; ++i) { + // FIXME: account for $ try { - IfcUtil::IfcBaseClass *entity = *list_[i]; + IfcUtil::IfcBaseClass* entity = *list_[i]; l->push(entity); } catch (IfcException e) { Logger::Error(e); } - } - return l; + } + return l; } -ArgumentList::operator std::vector< std::vector >() const { - return read_aggregate_of_aggregate_as_vector2(list_, size_); +ArgumentList::operator std::vector>() const { + return read_aggregate_of_aggregate_as_vector2(list_, size_); } -ArgumentList::operator std::vector< std::vector >() const { - return read_aggregate_of_aggregate_as_vector2(list_, size_); +ArgumentList::operator std::vector>() const { + return read_aggregate_of_aggregate_as_vector2(list_, size_); } ArgumentList::operator aggregate_of_aggregate_of_instance::ptr() const { - aggregate_of_aggregate_of_instance::ptr l ( new aggregate_of_aggregate_of_instance() ); - for (size_t i = 0; i < size_; ++i) { - const Argument* arg = list_[i]; - const ArgumentList* arg_list; - if ((arg_list = dynamic_cast(arg)) != 0) { - aggregate_of_instance::ptr e = *arg_list; - l->push(e); - } else { - auto token = dynamic_cast(arg); - int startpos = token ? token->token.startPos : 0; - std::string string_rep = this->toString(); - throw IfcInvalidTokenException(startpos, string_rep, "nested aggregate"); - } - } - return l; + aggregate_of_aggregate_of_instance::ptr l(new aggregate_of_aggregate_of_instance()); + for (size_t i = 0; i < size_; ++i) { + const Argument* arg = list_[i]; + const ArgumentList* arg_list; + if ((arg_list = dynamic_cast(arg)) != 0) { + aggregate_of_instance::ptr e = *arg_list; + l->push(e); + } else { + auto token = dynamic_cast(arg); + int startpos = token ? token->token.startPos : 0; + std::string string_rep = this->toString(); + throw IfcInvalidTokenException(startpos, string_rep, "nested aggregate"); + } + } + return l; } unsigned int ArgumentList::size() const { return (unsigned int)size_; } -Argument* ArgumentList::operator [] (unsigned int i) const { - if (i >= size_) { - throw IfcAttributeOutOfRangeException("Argument index out of range"); - } - return list_[i]; +Argument* ArgumentList::operator[](unsigned int i) const { + if (i >= size_) { + throw IfcAttributeOutOfRangeException("Argument index out of range"); + } + return list_[i]; } /* @@ -887,52 +910,51 @@ void ArgumentList::set(unsigned int i, Argument* argument) { */ std::string ArgumentList::toString(bool upper) const { - std::stringstream ss; - ss << "("; - for (size_t i = 0; i < size_; ++i) { - if (i != 0) { - ss << ","; - } - ss << list_[i]->toString(upper); - } - ss << ")"; - return ss.str(); + std::stringstream ss; + ss << "("; + for (size_t i = 0; i < size_; ++i) { + if (i != 0) { + ss << ","; + } + ss << list_[i]->toString(upper); + } + ss << ")"; + return ss.str(); } bool ArgumentList::isNull() const { return false; } ArgumentList::~ArgumentList() { - for (size_t i = 0; i < size_; ++i) { - delete list_[i]; - } - delete[] list_; + for (size_t i = 0; i < size_; ++i) { + delete list_[i]; + } + delete[] list_; } - IfcUtil::ArgumentType TokenArgument::type() const { - if (TokenFunc::isInt(token)) { - return IfcUtil::Argument_INT; - } else if (TokenFunc::isBool(token)) { - return IfcUtil::Argument_BOOL; - } else if (TokenFunc::isLogical(token)) { - return IfcUtil::Argument_LOGICAL; - } else if (TokenFunc::isFloat(token)) { - return IfcUtil::Argument_DOUBLE; - } else if (TokenFunc::isString(token)) { - return IfcUtil::Argument_STRING; - } else if (TokenFunc::isEnumeration(token)) { - return IfcUtil::Argument_ENUMERATION; - } else if (TokenFunc::isIdentifier(token)) { - return IfcUtil::Argument_ENTITY_INSTANCE; - } else if (TokenFunc::isBinary(token)) { - return IfcUtil::Argument_BINARY; - } else if (TokenFunc::isOperator(token, '$')) { - return IfcUtil::Argument_NULL; - } else if (TokenFunc::isOperator(token, '*')) { - return IfcUtil::Argument_DERIVED; - } else { - return IfcUtil::Argument_UNKNOWN; - } + if (TokenFunc::isInt(token)) { + return IfcUtil::Argument_INT; + } else if (TokenFunc::isBool(token)) { + return IfcUtil::Argument_BOOL; + } else if (TokenFunc::isLogical(token)) { + return IfcUtil::Argument_LOGICAL; + } else if (TokenFunc::isFloat(token)) { + return IfcUtil::Argument_DOUBLE; + } else if (TokenFunc::isString(token)) { + return IfcUtil::Argument_STRING; + } else if (TokenFunc::isEnumeration(token)) { + return IfcUtil::Argument_ENUMERATION; + } else if (TokenFunc::isIdentifier(token)) { + return IfcUtil::Argument_ENTITY_INSTANCE; + } else if (TokenFunc::isBinary(token)) { + return IfcUtil::Argument_BINARY; + } else if (TokenFunc::isOperator(token, '$')) { + return IfcUtil::Argument_NULL; + } else if (TokenFunc::isOperator(token, '*')) { + return IfcUtil::Argument_DERIVED; + } else { + return IfcUtil::Argument_UNKNOWN; + } } // @@ -946,121 +968,125 @@ TokenArgument::operator std::string() const { return TokenFunc::asString(token); TokenArgument::operator boost::dynamic_bitset<>() const { return TokenFunc::asBinary(token); } TokenArgument::operator IfcUtil::IfcBaseClass*() const { return token.lexer->file->instance_by_id(TokenFunc::asIdentifier(token)); } unsigned int TokenArgument::size() const { return 1; } -Argument* TokenArgument::operator [] (unsigned int /*i*/) const { throw IfcException("Argument is not a list of attributes"); } -std::string TokenArgument::toString(bool upper) const { - if ( upper && TokenFunc::isString(token) ) { - return IfcWrite::IfcCharacterEncoder(TokenFunc::asString(token)); - } else { - return TokenFunc::toString(token); - } +Argument* TokenArgument::operator[](unsigned int /*i*/) const { throw IfcException("Argument is not a list of attributes"); } +std::string TokenArgument::toString(bool upper) const { + if (upper && TokenFunc::isString(token)) { + return IfcWrite::IfcCharacterEncoder(TokenFunc::asString(token)); + } else { + return TokenFunc::toString(token); + } } -bool TokenArgument::isNull() const { return TokenFunc::isOperator(token,'$'); } +bool TokenArgument::isNull() const { return TokenFunc::isOperator(token, '$'); } IfcUtil::ArgumentType EntityArgument::type() const { - return IfcUtil::Argument_ENTITY_INSTANCE; + return IfcUtil::Argument_ENTITY_INSTANCE; } // // Functions for casting the EntityArgument to other types // EntityArgument::operator IfcUtil::IfcBaseClass*() const { - return entity; + return entity; } unsigned int EntityArgument::size() const { - return 1; + return 1; } -Argument* EntityArgument::operator [] (unsigned int /*i*/) const { - throw IfcException("Argument is not a list of arguments"); +Argument* EntityArgument::operator[](unsigned int /*i*/) const { + throw IfcException("Argument is not a list of arguments"); } std::string EntityArgument::toString(bool upper) const { - return entity->data().toString(upper); + return entity->data().toString(upper); } bool EntityArgument::isNull() const { return false; } EntityArgument::~EntityArgument() { - // We don't delete it here, rather it will be freed as part of the entity_file_map. - // For that purpose when parsed, the simple type instance is explicitly added to the - // file. The reason is we want parsed simply types to behave the same as constructed - // simple types. + // We don't delete it here, rather it will be freed as part of the entity_file_map. + // For that purpose when parsed, the simple type instance is explicitly added to the + // file. The reason is we want parsed simply types to behave the same as constructed + // simple types. - // delete entity; + // delete entity; } // // Reads an Entity from the list of Tokens at the specified offset in the file // IfcEntityInstanceData* IfcParse::read(unsigned int i, IfcFile* f, boost::optional offset) { - if (offset) { - f->tokens->stream->Seek(*offset); - } - Token datatype = f->tokens->Next(); - if (!TokenFunc::isKeyword(datatype)) throw IfcException("Unexpected token while parsing entity"); - const IfcParse::declaration* ty = f->schema()->declaration_by_name(TokenFunc::asStringRef(datatype)); - IfcEntityInstanceData* e = new IfcEntityInstanceData(ty, f, i, offset.get_value_or(0)); - return e; + if (offset) { + f->tokens->stream->Seek(*offset); + } + Token datatype = f->tokens->Next(); + if (!TokenFunc::isKeyword(datatype)) { + throw IfcException("Unexpected token while parsing entity"); + } + const IfcParse::declaration* ty = f->schema()->declaration_by_name(TokenFunc::asStringRef(datatype)); + IfcEntityInstanceData* e = new IfcEntityInstanceData(ty, f, i, offset.get_value_or(0)); + return e; } void IfcParse::IfcFile::seek_to(const IfcEntityInstanceData& data) { - if (tokens->stream->Tell() != data.offset_in_file()) { - tokens->stream->Seek(data.offset_in_file()); - Token datatype = tokens->Next(); - if (!TokenFunc::isKeyword(datatype)) throw IfcException("Unexpected token while parsing entity instance"); - } - tokens->Next(); + if (tokens->stream->Tell() != data.offset_in_file()) { + tokens->stream->Seek(data.offset_in_file()); + Token datatype = tokens->Next(); + if (!TokenFunc::isKeyword(datatype)) { + throw IfcException("Unexpected token while parsing entity instance"); + } + } + tokens->Next(); } void IfcParse::IfcFile::try_read_semicolon() { - unsigned int old_offset = tokens->stream->Tell(); - Token semilocon = tokens->Next(); - if (!TokenFunc::isOperator(semilocon, ';')) { - tokens->stream->Seek(old_offset); - } + unsigned int old_offset = tokens->stream->Tell(); + Token semilocon = tokens->Next(); + if (!TokenFunc::isOperator(semilocon, ';')) { + tokens->stream->Seek(old_offset); + } } void IfcParse::IfcFile::register_inverse(unsigned id_from, const IfcParse::entity* from_entity, Token t, int attribute_index) { - // Assume a check on token type has already been performed - auto e = from_entity; - byref_excl[t.value_int].push_back(id_from); - while (e) { - byref[{t.value_int, e->index_in_schema(), attribute_index}].push_back(id_from); - e = e->supertype(); - } + // Assume a check on token type has already been performed + auto e = from_entity; + byref_excl[t.value_int].push_back(id_from); + while (e) { + byref[{t.value_int, e->index_in_schema(), attribute_index}].push_back(id_from); + e = e->supertype(); + } } void IfcParse::IfcFile::register_inverse(unsigned id_from, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass* inst, int attribute_index) { - auto e = from_entity; - byref_excl[inst->data().id()].push_back(id_from); - while (e) { - byref[{inst->data().id(), e->index_in_schema(), attribute_index}].push_back(id_from); - e = e->supertype(); - } + auto e = from_entity; + byref_excl[inst->data().id()].push_back(id_from); + while (e) { + byref[{inst->data().id(), e->index_in_schema(), attribute_index}].push_back(id_from); + e = e->supertype(); + } } void IfcParse::IfcFile::unregister_inverse(unsigned id_from, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass* inst, int attribute_index) { - auto e = from_entity; - while (e) { - std::vector& ids = byref[{inst->data().id(), e->index_in_schema(), attribute_index}]; - std::vector::iterator it = std::find(ids.begin(), ids.end(), id_from); - if (it == ids.end()) { - // @todo inverses also need to be populated when multiple instances are added to a new file. - // throw IfcParse::IfcException("Instance not found among inverses"); - } else { - ids.erase(it); - } - e = e->supertype(); - } + auto e = from_entity; + while (e) { + std::vector& ids = byref[{inst->data().id(), e->index_in_schema(), attribute_index}]; + std::vector::iterator it = std::find(ids.begin(), ids.end(), id_from); + if (it == ids.end()) { + // @todo inverses also need to be populated when multiple instances are added to a new file. + // throw IfcParse::IfcException("Instance not found among inverses"); + } else { + ids.erase(it); + } + e = e->supertype(); + } - std::vector& ids = byref_excl[inst->data().id()]; - std::vector::iterator it = std::find(ids.begin(), ids.end(), id_from); - if (it == ids.end()) { - // @todo inverses also need to be populated when multiple instances are added to a new file. - // throw IfcParse::IfcException("Instance not found among inverses"); - } else { - ids.erase(it); - } + std::vector& ids = byref_excl[inst->data().id()]; + std::vector::iterator it = std::find(ids.begin(), ids.end(), id_from); + if (it == ids.end()) { + // @todo inverses also need to be populated when multiple instances are added to a new file. + // throw IfcParse::IfcException("Instance not found among inverses"); + } else { + ids.erase(it); + } } // @@ -1068,440 +1094,450 @@ void IfcParse::IfcFile::unregister_inverse(unsigned id_from, const IfcParse::ent // Note that this initializes the entity if it is not initialized // std::string IfcEntityInstanceData::toString(bool upper) const { - if (attributes_ == 0) { - load(); - } + if (attributes_ == 0) { + load(); + } - std::stringstream ss; - ss.imbue(std::locale::classic()); - - std::string dt; - if (type_) { - dt = type()->name(); - if (upper) { - boost::to_upper(dt); - } + std::stringstream ss; + ss.imbue(std::locale::classic()); - if (type()->as_entity() || id_ != 0) { - ss << "#" << id_ << "="; - } - } + std::string dt; + if (type_) { + dt = type()->name(); + if (upper) { + boost::to_upper(dt); + } - ss << dt << "("; + if (type()->as_entity() || id_ != 0) { + ss << "#" << id_ << "="; + } + } - for (size_t i = 0; i < getArgumentCount(); ++i) { - if (i != 0) { - ss << ","; - } - if (attributes_[i] == 0) { - ss << "$"; - } else { - ss << attributes_[i]->toString(upper); - } - } - ss << ")"; + ss << dt << "("; - return ss.str(); + for (size_t i = 0; i < getArgumentCount(); ++i) { + if (i != 0) { + ss << ","; + } + if (attributes_[i] == 0) { + ss << "$"; + } else { + ss << attributes_[i]->toString(upper); + } + } + ss << ")"; + + return ss.str(); } -void IfcEntityInstanceData::clearArguments() -{ - if (attributes_ != NULL) { - for (size_t i = 0; i < getArgumentCount(); ++i) { - delete attributes_[i]; - } - delete[] attributes_; - attributes_ = NULL; - } +void IfcEntityInstanceData::clearArguments() { + if (attributes_ != NULL) { + for (size_t i = 0; i < getArgumentCount(); ++i) { + delete attributes_[i]; + } + delete[] attributes_; + attributes_ = NULL; + } } IfcEntityInstanceData::~IfcEntityInstanceData() { - clearArguments(); + clearArguments(); } unsigned IfcEntityInstanceData::set_id(boost::optional i) { - if (i) { - return id_ = *i; - } else { - return id_ = file->FreshId(); - } + if (i) { + return id_ = *i; + } else { + return id_ = file->FreshId(); + } } // // Returns the entities of Entity type that have this entity in their ArgumentList // aggregate_of_instance::ptr IfcEntityInstanceData::getInverse(const IfcParse::declaration* type, int attribute_index) const { - static std::mutex m; - std::lock_guard lk(m); + static std::mutex m; + std::lock_guard lk(m); - return file->getInverse(id_, type, attribute_index); + return file->getInverse(id_, type, attribute_index); } void IfcEntityInstanceData::load() const { - static std::recursive_mutex m; - std::lock_guard lk(m); + static std::recursive_mutex m; + std::lock_guard lk(m); - Argument** tmp_data = nullptr; - - if (file->parsing_complete()) { - // only when parsing is fully complete we need to seek to the instance, otherwise - // we know the token cursor is currently at the keyword token - file->seek_to(*this); - } else { - // Apparently the load() function assumes one token later after the opening parenthesis - file->tokens->Next(); - } + Argument** tmp_data = nullptr; - // type_ is 0 for header entities which have their size predetermined in code - // in that we have attributes_ pre-constructed to the correct size in the constructor - // in the other case load() will use a vector internally to grow to the size found in the file - size_t n = file->load(id(), type_ ? type_->as_entity() : nullptr, type_ ? tmp_data : attributes_, getArgumentCount()); - if (n != getArgumentCount()) { - Logger::Error("Wrong number of attributes on instance with id #" + std::to_string(id_) + - " at offset " + std::to_string(this->offset_in_file()) + - " expected " + std::to_string(getArgumentCount()) + - " got " + std::to_string(n)); - } + if (file->parsing_complete()) { + // only when parsing is fully complete we need to seek to the instance, otherwise + // we know the token cursor is currently at the keyword token + file->seek_to(*this); + } else { + // Apparently the load() function assumes one token later after the opening parenthesis + file->tokens->Next(); + } - file->try_read_semicolon(); - - // @todo does this need to be atomic somehow? - if (tmp_data) { - attributes_ = tmp_data; - } + // type_ is 0 for header entities which have their size predetermined in code + // in that we have attributes_ pre-constructed to the correct size in the constructor + // in the other case load() will use a vector internally to grow to the size found in the file + size_t n = file->load(id(), type_ ? type_->as_entity() : nullptr, type_ ? tmp_data : attributes_, getArgumentCount()); + if (n != getArgumentCount()) { + Logger::Error("Wrong number of attributes on instance with id #" + std::to_string(id_) + + " at offset " + std::to_string(this->offset_in_file()) + + " expected " + std::to_string(getArgumentCount()) + + " got " + std::to_string(n)); + } + + file->try_read_semicolon(); + + // @todo does this need to be atomic somehow? + if (tmp_data) { + attributes_ = tmp_data; + } } namespace { - // @todo remove redundancy with python wrapper code (which is not identical due to - // different handling of enumerations) - IfcUtil::ArgumentType get_argument_type(const IfcParse::declaration* decl, size_t i) { - const IfcParse::parameter_type* pt = 0; - if (decl->as_entity()) { - pt = decl->as_entity()->attribute_by_index(i)->type_of_attribute(); - if (decl->as_entity()->derived()[i]) { - return IfcUtil::Argument_DERIVED; - } - } else if (decl->as_type_declaration() && i == 0) { - pt = decl->as_type_declaration()->declared_type(); - } else if (decl->as_enumeration_type() && i == 0) { - return IfcUtil::Argument_ENUMERATION; - } +// @todo remove redundancy with python wrapper code (which is not identical due to +// different handling of enumerations) +IfcUtil::ArgumentType get_argument_type(const IfcParse::declaration* decl, size_t i) { + const IfcParse::parameter_type* pt = 0; + if (decl->as_entity()) { + pt = decl->as_entity()->attribute_by_index(i)->type_of_attribute(); + if (decl->as_entity()->derived()[i]) { + return IfcUtil::Argument_DERIVED; + } + } else if (decl->as_type_declaration() && i == 0) { + pt = decl->as_type_declaration()->declared_type(); + } else if (decl->as_enumeration_type() && i == 0) { + return IfcUtil::Argument_ENUMERATION; + } - if (pt == 0) { - return IfcUtil::Argument_UNKNOWN; - } else { - return IfcUtil::from_parameter_type(pt); - } - } + if (pt == 0) { + return IfcUtil::Argument_UNKNOWN; + } else { + return IfcUtil::from_parameter_type(pt); + } } +} // namespace IfcEntityInstanceData::IfcEntityInstanceData(const IfcEntityInstanceData& e) { - file = 0; - type_ = e.type_; - id_ = 0; + file = 0; + type_ = e.type_; + id_ = 0; - const size_t count = e.getArgumentCount(); + const size_t count = e.getArgumentCount(); - // In order not to have the instance read from file - attributes_ = new Argument*[count]; + // 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), get_argument_type(e.type(), i), true); - } + for (unsigned int i = 0; i < count; ++i) { + attributes_[i] = 0; + this->setArgument(i, e.getArgument(i), get_argument_type(e.type(), i), true); + } } static IfcParse::NullArgument static_null_attribute; Argument* IfcEntityInstanceData::getArgument(size_t i) const { - if (attributes_ == 0) { - load(); - } - if (i < getArgumentCount()) { - if (attributes_[i] == nullptr) { - return &static_null_attribute; - } else { - return attributes_[i]; - } - } else { - throw IfcParse::IfcException("Attribute index out of range"); - } + if (attributes_ == 0) { + load(); + } + if (i < getArgumentCount()) { + if (attributes_[i] == nullptr) { + return &static_null_attribute; + } else { + return attributes_[i]; + } + } else { + throw IfcParse::IfcException("Attribute index out of range"); + } } class unregister_inverse_visitor { -private: - IfcFile& file_; - const IfcEntityInstanceData& data_; + private: + IfcFile& file_; + const IfcEntityInstanceData& data_; -public: - unregister_inverse_visitor(IfcFile& file, const IfcEntityInstanceData& data) - : file_(file), data_(data) - {} + public: + unregister_inverse_visitor(IfcFile& file, const IfcEntityInstanceData& data) + : file_(file), + data_(data) {} - void operator()(IfcUtil::IfcBaseClass* inst, int index) { - file_.unregister_inverse(data_.id(), data_.type()->as_entity(), inst, index); - } + void operator()(IfcUtil::IfcBaseClass* inst, int index) { + file_.unregister_inverse(data_.id(), data_.type()->as_entity(), inst, index); + } }; class register_inverse_visitor { -private: - IfcFile& file_; - const IfcEntityInstanceData& data_; + private: + IfcFile& file_; + const IfcEntityInstanceData& data_; -public: - register_inverse_visitor(IfcFile& file, const IfcEntityInstanceData& data) - : file_(file), data_(data) - {} + public: + register_inverse_visitor(IfcFile& file, const IfcEntityInstanceData& data) + : file_(file), + data_(data) {} - void operator()(IfcUtil::IfcBaseClass* inst, int index) { - file_.register_inverse(data_.id(), data_.type()->as_entity(), inst, index); - } + void operator()(IfcUtil::IfcBaseClass* inst, int index) { + file_.register_inverse(data_.id(), data_.type()->as_entity(), inst, index); + } }; class add_to_instance_list_visitor { -private: - aggregate_of_instance::ptr& list_; + private: + aggregate_of_instance::ptr& list_; -public: - add_to_instance_list_visitor(aggregate_of_instance::ptr& list) - : list_(list) - {} + public: + add_to_instance_list_visitor(aggregate_of_instance::ptr& list) + : list_(list) {} - void operator()(IfcUtil::IfcBaseClass* inst) { - list_->push(inst); - } + void operator()(IfcUtil::IfcBaseClass* inst) { + list_->push(inst); + } }; class apply_individual_instance_visitor { -private: - Argument* attribute_; - IfcEntityInstanceData* data_; - int attribute_index_; + private: + Argument* attribute_; + IfcEntityInstanceData* data_; + int attribute_index_; - template - void apply_attribute_(T& t, Argument* attr, int index) const { - if (!attr) { - return; - } + template + void apply_attribute_(T& t, Argument* attr, int index) const { + if (!attr) { + return; + } - if (attr->type() == IfcUtil::Argument_ENTITY_INSTANCE) { - IfcUtil::IfcBaseClass* inst = *attr; - t(inst, index); - } else if (attr->type() == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) { - aggregate_of_instance::ptr entity_list_attribute = *attr; - for (aggregate_of_instance::it it = entity_list_attribute->begin(); it != entity_list_attribute->end(); ++it) { - t(*it, index); - } - } else if (attr->type() == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) { - aggregate_of_aggregate_of_instance::ptr entity_list_attribute = *attr; - for (aggregate_of_aggregate_of_instance::outer_it it = entity_list_attribute->begin(); it != entity_list_attribute->end(); ++it) { - for (aggregate_of_aggregate_of_instance::inner_it jt = it->begin(); jt != it->end(); ++jt) { - t(*jt, index); - } - } - } - }; -public: - apply_individual_instance_visitor(Argument* attribute, int idx) - : attribute_(attribute), data_(0), attribute_index_(idx) - {} + if (attr->type() == IfcUtil::Argument_ENTITY_INSTANCE) { + IfcUtil::IfcBaseClass* inst = *attr; + t(inst, index); + } else if (attr->type() == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) { + aggregate_of_instance::ptr entity_list_attribute = *attr; + for (aggregate_of_instance::it it = entity_list_attribute->begin(); it != entity_list_attribute->end(); ++it) { + t(*it, index); + } + } else if (attr->type() == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) { + aggregate_of_aggregate_of_instance::ptr entity_list_attribute = *attr; + for (aggregate_of_aggregate_of_instance::outer_it it = entity_list_attribute->begin(); it != entity_list_attribute->end(); ++it) { + for (aggregate_of_aggregate_of_instance::inner_it jt = it->begin(); jt != it->end(); ++jt) { + t(*jt, index); + } + } + } + }; - apply_individual_instance_visitor(IfcEntityInstanceData* data) - : attribute_(0), data_(data) - {} + public: + apply_individual_instance_visitor(Argument* attribute, int idx) + : attribute_(attribute), + data_(0), + attribute_index_(idx) {} - template - void apply(T& t) const { - if (attribute_) { - apply_attribute_(t, attribute_, attribute_index_); - } else { - for (size_t i = 0; i < data_->getArgumentCount(); ++i) { - Argument* attr = data_->getArgument(i); - apply_attribute_(t, attr, i); - } - } - }; + apply_individual_instance_visitor(IfcEntityInstanceData* data) + : attribute_(0), + data_(data) {} + template + void apply(T& t) const { + if (attribute_) { + apply_attribute_(t, attribute_, attribute_index_); + } else { + for (size_t i = 0; i < data_->getArgumentCount(); ++i) { + Argument* attr = data_->getArgument(i); + apply_attribute_(t, attr, i); + } + } + }; }; void IfcEntityInstanceData::setArgument(size_t i, Argument* a, IfcUtil::ArgumentType attr_type, bool make_copy) { - if (attributes_ == 0) { - load(); - } - Argument* new_attribute = a; - if (make_copy) { - if (attr_type == IfcUtil::Argument_UNKNOWN) { - attr_type = a->type(); - } else if (a->isNull()) { - attr_type = IfcUtil::Argument_NULL; - } + if (attributes_ == 0) { + load(); + } + Argument* new_attribute = a; + if (make_copy) { + if (attr_type == IfcUtil::Argument_UNKNOWN) { + attr_type = a->type(); + } else if (a->isNull()) { + attr_type = IfcUtil::Argument_NULL; + } - IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); + IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); - switch (attr_type) { - case IfcUtil::Argument_NULL: - copy->set(boost::blank()); - break; - case IfcUtil::Argument_DERIVED: - copy->set(IfcWrite::IfcWriteArgument::Derived()); - break; - case IfcUtil::Argument_INT: - copy->set(static_cast(*a)); - break; - case IfcUtil::Argument_BOOL: - copy->set(static_cast(*a)); - break; - case IfcUtil::Argument_LOGICAL: { - boost::logic::tribool tb = *a; - copy->set(tb); - break; - } - case IfcUtil::Argument_DOUBLE: - copy->set(static_cast(*a)); - break; - case IfcUtil::Argument_STRING: - copy->set(static_cast(*a)); - break; - case IfcUtil::Argument_BINARY: { - boost::dynamic_bitset<> attr_value = *a; - copy->set(attr_value); - break; } - case IfcUtil::Argument_AGGREGATE_OF_INT: { - std::vector attr_value = *a; - copy->set(attr_value); - break; } - case IfcUtil::Argument_AGGREGATE_OF_DOUBLE: { - std::vector attr_value = *a; - copy->set(attr_value); - break; } - case IfcUtil::Argument_AGGREGATE_OF_STRING: { - std::vector attr_value = *a; - copy->set(attr_value); - break; } - case IfcUtil::Argument_AGGREGATE_OF_BINARY: { - std::vector< boost::dynamic_bitset<> > attr_value = *a; - copy->set(attr_value); - break; } - case IfcUtil::Argument_ENUMERATION: { - std::string enum_literal = a->toString(); - // Remove leading and trailing '.' - enum_literal = enum_literal.substr(1, enum_literal.size() - 2); - - const IfcParse::enumeration_type* enum_type = type()->as_enumeration_type() - ? type()->as_enumeration_type() - : type()->as_entity()->attribute_by_index(i)->type_of_attribute()-> - as_named_type()->declared_type()->as_enumeration_type(); - - std::vector::const_iterator it = std::find( - enum_type->enumeration_items().begin(), - enum_type->enumeration_items().end(), - enum_literal); - - if (it == enum_type->enumeration_items().end()) { - throw IfcParse::IfcException(enum_literal + " does not name a valid item for " + enum_type->name()); - } + switch (attr_type) { + case IfcUtil::Argument_NULL: + copy->set(boost::blank()); + break; + case IfcUtil::Argument_DERIVED: + copy->set(IfcWrite::IfcWriteArgument::Derived()); + break; + case IfcUtil::Argument_INT: + copy->set(static_cast(*a)); + break; + case IfcUtil::Argument_BOOL: + copy->set(static_cast(*a)); + break; + case IfcUtil::Argument_LOGICAL: { + boost::logic::tribool tb = *a; + copy->set(tb); + break; + } + case IfcUtil::Argument_DOUBLE: + copy->set(static_cast(*a)); + break; + case IfcUtil::Argument_STRING: + copy->set(static_cast(*a)); + break; + case IfcUtil::Argument_BINARY: { + boost::dynamic_bitset<> attr_value = *a; + copy->set(attr_value); + break; + } + case IfcUtil::Argument_AGGREGATE_OF_INT: { + std::vector attr_value = *a; + copy->set(attr_value); + break; + } + case IfcUtil::Argument_AGGREGATE_OF_DOUBLE: { + std::vector attr_value = *a; + copy->set(attr_value); + break; + } + case IfcUtil::Argument_AGGREGATE_OF_STRING: { + std::vector attr_value = *a; + copy->set(attr_value); + break; + } + case IfcUtil::Argument_AGGREGATE_OF_BINARY: { + std::vector> attr_value = *a; + copy->set(attr_value); + break; + } + case IfcUtil::Argument_ENUMERATION: { + std::string enum_literal = a->toString(); + // Remove leading and trailing '.' + enum_literal = enum_literal.substr(1, enum_literal.size() - 2); - copy->set(IfcWrite::IfcWriteArgument::EnumerationReference(it - enum_type->enumeration_items().begin(), it->c_str())); - break; } - case IfcUtil::Argument_ENTITY_INSTANCE: { - copy->set(static_cast(*a)); - break; } - case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: { - aggregate_of_instance::ptr instances = *a; - aggregate_of_instance::ptr mapped_instances(new aggregate_of_instance); - // @todo mapped_instances are not actually mapped to the file using add(). - for (aggregate_of_instance::it it = instances->begin(); it != instances->end(); ++it) { - mapped_instances->push(*it); - } - copy->set(mapped_instances); - break; } - case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT: { - std::vector< std::vector > attr_value = *a; - copy->set(attr_value); - break; } - case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE: { - std::vector< std::vector > attr_value = *a; - copy->set(attr_value); - break; } - case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE: { - aggregate_of_aggregate_of_instance::ptr instances = *a; - aggregate_of_aggregate_of_instance::ptr mapped_instances(new aggregate_of_aggregate_of_instance); - for (aggregate_of_aggregate_of_instance::outer_it it = instances->begin(); it != instances->end(); ++it) { - std::vector inner; - for (aggregate_of_aggregate_of_instance::inner_it jt = it->begin(); jt != it->end(); ++jt) { - inner.push_back(*jt); - } - mapped_instances->push(inner); - } - copy->set(mapped_instances); - break; } - case IfcUtil::Argument_EMPTY_AGGREGATE: - case IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE: { - IfcUtil::ArgumentType t2 = IfcUtil::from_parameter_type(type()->as_entity()->attribute_by_index(i)->type_of_attribute()); - delete copy; - copy = 0; - setArgument(i, a, t2, make_copy); - break; } - default: - case IfcUtil::Argument_UNKNOWN: - throw IfcParse::IfcException(std::string("Unknown attribute encountered: '") + a->toString() + "' at index '" + boost::lexical_cast(i) + "'"); - break; - } + const IfcParse::enumeration_type* enum_type = type()->as_enumeration_type() + ? type()->as_enumeration_type() + : type()->as_entity()->attribute_by_index(i)->type_of_attribute()->as_named_type()->declared_type()->as_enumeration_type(); - if (!copy) { - return; - } + std::vector::const_iterator it = std::find( + enum_type->enumeration_items().begin(), + enum_type->enumeration_items().end(), + enum_literal); - new_attribute = copy; - } + if (it == enum_type->enumeration_items().end()) { + throw IfcParse::IfcException(enum_literal + " does not name a valid item for " + enum_type->name()); + } - if (attributes_[i] != 0) { - Argument* current_attribute = attributes_[i]; - if (this->file) { + copy->set(IfcWrite::IfcWriteArgument::EnumerationReference(it - enum_type->enumeration_items().begin(), it->c_str())); + break; + } + case IfcUtil::Argument_ENTITY_INSTANCE: { + copy->set(static_cast(*a)); + break; + } + case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: { + aggregate_of_instance::ptr instances = *a; + aggregate_of_instance::ptr mapped_instances(new aggregate_of_instance); + // @todo mapped_instances are not actually mapped to the file using add(). + for (aggregate_of_instance::it it = instances->begin(); it != instances->end(); ++it) { + mapped_instances->push(*it); + } + copy->set(mapped_instances); + break; + } + case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT: { + std::vector> attr_value = *a; + copy->set(attr_value); + break; + } + case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE: { + std::vector> attr_value = *a; + copy->set(attr_value); + break; + } + case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE: { + aggregate_of_aggregate_of_instance::ptr instances = *a; + aggregate_of_aggregate_of_instance::ptr mapped_instances(new aggregate_of_aggregate_of_instance); + for (aggregate_of_aggregate_of_instance::outer_it it = instances->begin(); it != instances->end(); ++it) { + std::vector inner; + for (aggregate_of_aggregate_of_instance::inner_it jt = it->begin(); jt != it->end(); ++jt) { + inner.push_back(*jt); + } + mapped_instances->push(inner); + } + copy->set(mapped_instances); + break; + } + case IfcUtil::Argument_EMPTY_AGGREGATE: + case IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE: { + IfcUtil::ArgumentType t2 = IfcUtil::from_parameter_type(type()->as_entity()->attribute_by_index(i)->type_of_attribute()); + delete copy; + copy = 0; + setArgument(i, a, t2, make_copy); + break; + } + default: + case IfcUtil::Argument_UNKNOWN: + throw IfcParse::IfcException(std::string("Unknown attribute encountered: '") + a->toString() + "' at index '" + boost::lexical_cast(i) + "'"); + break; + } - // Deregister old attribute guid in file guid map. - if (i == 0 && this->type() && this->file->ifcroot_type() && this->type()->is(*this->file->ifcroot_type())) { - try { - auto guid = (std::string) *current_attribute; - auto it = this->file->internal_guid_map().find(guid); - if (it != this->file->internal_guid_map().end() && &it->second->data() == this) { - this->file->internal_guid_map().erase(it); - } - } catch (IfcParse::IfcException& e) { - Logger::Error(e); - } - } + if (!copy) { + return; + } - // Deregister inverse indices in file - unregister_inverse_visitor visitor(*this->file, *this); - apply_individual_instance_visitor(current_attribute, i).apply(visitor); - } - delete attributes_[i]; - } + new_attribute = copy; + } - if (this->file) { - // Register inverse indices in file - register_inverse_visitor visitor(*this->file, *this); - apply_individual_instance_visitor(new_attribute, i).apply(visitor); - } + if (attributes_[i] != 0) { + Argument* current_attribute = attributes_[i]; + if (this->file) { - attributes_[i] = new_attribute; + // Deregister old attribute guid in file guid map. + if (i == 0 && this->type() && this->file->ifcroot_type() && this->type()->is(*this->file->ifcroot_type())) { + try { + auto guid = (std::string)*current_attribute; + auto it = this->file->internal_guid_map().find(guid); + if (it != this->file->internal_guid_map().end() && &it->second->data() == this) { + this->file->internal_guid_map().erase(it); + } + } catch (IfcParse::IfcException& e) { + Logger::Error(e); + } + } - // Register new attribute guid in guid map - if (this->file) { - if (i == 0 && this->type() && this->file->ifcroot_type() && this->type()->is(*this->file->ifcroot_type())) { - try { - auto guid = (std::string) *new_attribute; - auto it = this->file->internal_guid_map().find(guid); - if (it != this->file->internal_guid_map().end()) { - Logger::Warning("Duplicate guid " + guid); - } - this->file->internal_guid_map()[guid] = this->file->instance_by_id(this->id()); - } catch (IfcParse::IfcException& e) { - Logger::Error(e); - } - } - } + // Deregister inverse indices in file + unregister_inverse_visitor visitor(*this->file, *this); + apply_individual_instance_visitor(current_attribute, i).apply(visitor); + } + delete attributes_[i]; + } + + if (this->file) { + // Register inverse indices in file + register_inverse_visitor visitor(*this->file, *this); + apply_individual_instance_visitor(new_attribute, i).apply(visitor); + } + + attributes_[i] = new_attribute; + + // Register new attribute guid in guid map + if (this->file) { + if (i == 0 && this->type() && this->file->ifcroot_type() && this->type()->is(*this->file->ifcroot_type())) { + try { + auto guid = (std::string)*new_attribute; + auto it = this->file->internal_guid_map().find(guid); + if (it != this->file->internal_guid_map().end()) { + Logger::Warning("Duplicate guid " + guid); + } + this->file->internal_guid_map()[guid] = this->file->instance_by_id(this->id()); + } catch (IfcParse::IfcException& e) { + Logger::Error(e); + } + } + } } // @@ -1510,1146 +1546,1146 @@ void IfcEntityInstanceData::setArgument(size_t i, Argument* a, IfcUtil::Argument // #ifdef USE_MMAP IfcFile::IfcFile(const std::string& fn, bool mmap) { - initialize_(new IfcSpfStream(fn, mmap)); + initialize_(new IfcSpfStream(fn, mmap)); } #else IfcFile::IfcFile(const std::string& fn) { - initialize_(new IfcSpfStream(fn)); + initialize_(new IfcSpfStream(fn)); } #endif IfcFile::IfcFile(std::istream& f, int len) { - initialize_(new IfcSpfStream(f, len)); + initialize_(new IfcSpfStream(f, len)); } IfcFile::IfcFile(void* data, int len) { - initialize_(new IfcSpfStream(data, len)); + initialize_(new IfcSpfStream(data, len)); } IfcFile::IfcFile(IfcParse::IfcSpfStream* s) { - initialize_(s); + initialize_(s); } IfcFile::IfcFile(const IfcParse::schema_definition* schema) - : parsing_complete_(true) - , schema_(schema) - , ifcroot_type_(schema_->declaration_by_name("IfcRoot")) - , MaxId(0) - , tokens(0) - , stream(0) -{ - setDefaultHeaderValues(); + : parsing_complete_(true), + schema_(schema), + ifcroot_type_(schema_->declaration_by_name("IfcRoot")), + MaxId(0), + tokens(0), + stream(0) { + setDefaultHeaderValues(); } void IfcFile::initialize_(IfcParse::IfcSpfStream* s) { - // Initialize a "C" locale for locale-independent - // number parsing. See comment above on line 41. - init_locale(); + // Initialize a "C" locale for locale-independent + // number parsing. See comment above on line 41. + init_locale(); - // prevent heap allocations during parse - internal_attribute_vector_.reserve(64); - internal_attribute_vector_simple_type_.reserve(16); + // prevent heap allocations during parse + internal_attribute_vector_.reserve(64); + internal_attribute_vector_simple_type_.reserve(16); - parsing_complete_ = false; - MaxId = 0; - tokens = 0; - stream = 0; - schema_ = 0; + parsing_complete_ = false; + MaxId = 0; + tokens = 0; + stream = 0; + schema_ = 0; - setDefaultHeaderValues(); - - stream = s; - if (!stream->valid) { - good_ = file_open_status::READ_ERROR; - return; - } + setDefaultHeaderValues(); - tokens = new IfcSpfLexer(stream, this); - - std::vector schemas; + stream = s; + if (!stream->valid) { + good_ = file_open_status::READ_ERROR; + return; + } - _header.file(this); - if (_header.tryRead()) { - try { - schemas = _header.file_schema().schema_identifiers(); - } catch (...) { - // Purposely empty catch block - } - } else { - good_ = file_open_status::NO_HEADER; - } + tokens = new IfcSpfLexer(stream, this); - if (schemas.size() == 1) { - try { - schema_ = IfcParse::schema_by_name(schemas.front()); - } catch (const IfcParse::IfcException& e) { - good_ = file_open_status::UNSUPPORTED_SCHEMA; - Logger::Error(e); - } - } + std::vector schemas; - if (schema_ == 0) { - Logger::Message(Logger::LOG_ERROR, "No support for file schema encountered (" - + boost::algorithm::join(schemas, ", ") + ")"); - return; - } + _header.file(this); + if (_header.tryRead()) { + try { + schemas = _header.file_schema().schema_identifiers(); + } catch (...) { + // Purposely empty catch block + } + } else { + good_ = file_open_status::NO_HEADER; + } - ifcroot_type_ = schema_->declaration_by_name("IfcRoot"); + if (schemas.size() == 1) { + try { + schema_ = IfcParse::schema_by_name(schemas.front()); + } catch (const IfcParse::IfcException& e) { + good_ = file_open_status::UNSUPPORTED_SCHEMA; + Logger::Error(e); + } + } - boost::circular_buffer token_stream(3, Token()); + if (schema_ == 0) { + Logger::Message(Logger::LOG_ERROR, "No support for file schema encountered (" + boost::algorithm::join(schemas, ", ") + ")"); + return; + } - IfcEntityInstanceData* data; - IfcUtil::IfcBaseClass* instance = 0; + ifcroot_type_ = schema_->declaration_by_name("IfcRoot"); - unsigned current_id = 0; - int progress = 0; - Logger::Status("Scanning file..."); + boost::circular_buffer token_stream(3, Token()); - int paren_stack_depth = 0; - int attribute_index = -1; - - while (!stream->eof) { - if (token_stream[0].type == IfcParse::Token_IDENTIFIER && - token_stream[1].type == IfcParse::Token_OPERATOR && - token_stream[1].value_char == '=' && - token_stream[2].type == IfcParse::Token_KEYWORD) - { - attribute_index = 0; + IfcEntityInstanceData* data; + IfcUtil::IfcBaseClass* instance = 0; - current_id = (unsigned) TokenFunc::asIdentifier(token_stream[0]); - const IfcParse::declaration* entity_type; - try { - entity_type = schema_->declaration_by_name(TokenFunc::asStringRef(token_stream[2])); - } catch (const IfcException& ex) { - Logger::Message(Logger::LOG_ERROR, std::string(ex.what()) + " at offset " + std::to_string(token_stream[2].startPos)); - goto advance; - } - - data = new IfcEntityInstanceData(entity_type, this, current_id, token_stream[2].startPos); - instance = schema()->instantiate(data); + unsigned current_id = 0; + int progress = 0; + Logger::Status("Scanning file..."); + + int paren_stack_depth = 0; + int attribute_index = -1; + + while (!stream->eof) { + if (token_stream[0].type == IfcParse::Token_IDENTIFIER && + token_stream[1].type == IfcParse::Token_OPERATOR && + token_stream[1].value_char == '=' && + token_stream[2].type == IfcParse::Token_KEYWORD) { + attribute_index = 0; + + current_id = (unsigned)TokenFunc::asIdentifier(token_stream[0]); + const IfcParse::declaration* entity_type; + try { + entity_type = schema_->declaration_by_name(TokenFunc::asStringRef(token_stream[2])); + } catch (const IfcException& ex) { + Logger::Message(Logger::LOG_ERROR, std::string(ex.what()) + " at offset " + std::to_string(token_stream[2].startPos)); + goto advance; + } + + data = new IfcEntityInstanceData(entity_type, this, current_id, token_stream[2].startPos); + instance = schema()->instantiate(data); /// @todo Printing to stdout in a library class feels weird. Maybe move the progress prints to the client code? - // Update the status after every 1000 instances parsed - if (!((++progress) % 1000)) { - std::stringstream ss; ss << "\r#" << current_id; - Logger::Status(ss.str(), false); - } + // Update the status after every 1000 instances parsed + if (!((++progress) % 1000)) { + std::stringstream ss; + ss << "\r#" << current_id; + Logger::Status(ss.str(), false); + } - if (!lazy_load_) { - data->load(); - } + if (!lazy_load_) { + data->load(); + } - if (instance->declaration().is(*ifcroot_type_)) { - try { - const std::string guid = *instance->data().getArgument(0); - if ( byguid.find(guid) != byguid.end() ) { - std::stringstream ss; - ss << "Instance encountered with non-unique GlobalId " << guid; - Logger::Message(Logger::LOG_WARNING,ss.str()); - } - byguid[guid] = instance; - } catch (const IfcException& ex) { - Logger::Message(Logger::LOG_ERROR,ex.what()); - } - // this has consumed the instance tokens, set stack depth to 0 - paren_stack_depth = 0; - attribute_index = -1; - } + if (instance->declaration().is(*ifcroot_type_)) { + try { + const std::string guid = *instance->data().getArgument(0); + if (byguid.find(guid) != byguid.end()) { + std::stringstream ss; + ss << "Instance encountered with non-unique GlobalId " << guid; + Logger::Message(Logger::LOG_WARNING, ss.str()); + } + byguid[guid] = instance; + } catch (const IfcException& ex) { + Logger::Message(Logger::LOG_ERROR, ex.what()); + } + // this has consumed the instance tokens, set stack depth to 0 + paren_stack_depth = 0; + attribute_index = -1; + } - const IfcParse::declaration* ty = &instance->declaration(); + const IfcParse::declaration* ty = &instance->declaration(); - { - aggregate_of_instance::ptr insts = instances_by_type_excl_subtypes(ty); - if (!insts) { - insts = aggregate_of_instance::ptr(new aggregate_of_instance()); - bytype_excl[ty] = insts; - } - insts->push(instance); - } + { + aggregate_of_instance::ptr insts = instances_by_type_excl_subtypes(ty); + if (!insts) { + insts = aggregate_of_instance::ptr(new aggregate_of_instance()); + bytype_excl[ty] = insts; + } + insts->push(instance); + } - for (;;) { - aggregate_of_instance::ptr insts = instances_by_type(ty); - if (!insts) { - insts = aggregate_of_instance::ptr(new aggregate_of_instance()); - bytype[ty] = insts; - } - insts->push(instance); - const IfcParse::declaration* pt = ty->as_entity()->supertype(); - if (pt) { - ty = pt; - } else { - break; - } - } + for (;;) { + aggregate_of_instance::ptr insts = instances_by_type(ty); + if (!insts) { + insts = aggregate_of_instance::ptr(new aggregate_of_instance()); + bytype[ty] = insts; + } + insts->push(instance); + const IfcParse::declaration* pt = ty->as_entity()->supertype(); + if (pt) { + ty = pt; + } else { + break; + } + } - if (byid.find(current_id) != byid.end()) { - std::stringstream ss; - ss << "Overwriting instance with name #" << current_id; - Logger::Message(Logger::LOG_WARNING,ss.str()); - } - byid[current_id] = instance; - - MaxId = (std::max)(MaxId, current_id); - } else if (token_stream[0].type == IfcParse::Token_IDENTIFIER && instance) { - register_inverse(current_id, instance->declaration().as_entity(), token_stream[0], attribute_index); - } else if (token_stream[0].type == IfcParse::Token_OPERATOR && token_stream[0].value_char == '(') { - paren_stack_depth++; - } else if (token_stream[0].type == IfcParse::Token_OPERATOR && token_stream[0].value_char == ')') { - paren_stack_depth--; - if (paren_stack_depth == 0) { - attribute_index = -1; - } - } else if (paren_stack_depth == 1 && token_stream[0].type == IfcParse::Token_OPERATOR && token_stream[0].value_char == ',') { - attribute_index++; - } + if (byid.find(current_id) != byid.end()) { + std::stringstream ss; + ss << "Overwriting instance with name #" << current_id; + Logger::Message(Logger::LOG_WARNING, ss.str()); + } + byid[current_id] = instance; - advance: - Token next_token; - try { - next_token = tokens->Next(); - } catch (const IfcException& e) { - Logger::Message(Logger::LOG_ERROR, std::string(e.what()) + ". Parsing terminated"); - } catch (...) { - Logger::Message(Logger::LOG_ERROR, "Parsing terminated"); - } + MaxId = (std::max)(MaxId, current_id); + } else if (token_stream[0].type == IfcParse::Token_IDENTIFIER && instance) { + register_inverse(current_id, instance->declaration().as_entity(), token_stream[0], attribute_index); + } else if (token_stream[0].type == IfcParse::Token_OPERATOR && token_stream[0].value_char == '(') { + paren_stack_depth++; + } else if (token_stream[0].type == IfcParse::Token_OPERATOR && token_stream[0].value_char == ')') { + paren_stack_depth--; + if (paren_stack_depth == 0) { + attribute_index = -1; + } + } else if (paren_stack_depth == 1 && token_stream[0].type == IfcParse::Token_OPERATOR && token_stream[0].value_char == ',') { + attribute_index++; + } - if (next_token.type == Token_NONE) break; + advance: + Token next_token; + try { + next_token = tokens->Next(); + } catch (const IfcException& e) { + Logger::Message(Logger::LOG_ERROR, std::string(e.what()) + ". Parsing terminated"); + } catch (...) { + Logger::Message(Logger::LOG_ERROR, "Parsing terminated"); + } - token_stream.push_back(next_token); - } + if (next_token.type == Token_NONE) { + break; + } - Logger::Status("\rDone scanning file "); + token_stream.push_back(next_token); + } - parsing_complete_ = true; + Logger::Status("\rDone scanning file "); - return; + parsing_complete_ = true; + + return; } void IfcFile::recalculate_id_counter() { - entity_by_id_t::key_type k = 0; - for (auto& p : byid) { - if (p.first > k) { - k = p.first; - } - } - MaxId = (unsigned int)k; + entity_by_id_t::key_type k = 0; + for (auto& p : byid) { + if (p.first > k) { + k = p.first; + } + } + MaxId = (unsigned int)k; } class traversal_recorder { - aggregate_of_instance::ptr list_; - std::map instances_by_level_; - int mode_; + aggregate_of_instance::ptr list_; + std::map instances_by_level_; + int mode_; -public: - traversal_recorder(int mode) : mode_(mode) { - if (mode == 0) { - list_.reset(new aggregate_of_instance); - } - }; + public: + traversal_recorder(int mode) : mode_(mode) { + if (mode == 0) { + list_.reset(new aggregate_of_instance); + } + }; - void push_back(int level, IfcUtil::IfcBaseClass* instance) { - if (mode_ == 0) { - list_->push(instance); - } else { - auto& l = instances_by_level_[level]; - if (!l) { - l.reset(new aggregate_of_instance); - } - l->push(instance); - } - } + void push_back(int level, IfcUtil::IfcBaseClass* instance) { + if (mode_ == 0) { + list_->push(instance); + } else { + auto& l = instances_by_level_[level]; + if (!l) { + l.reset(new aggregate_of_instance); + } + l->push(instance); + } + } - aggregate_of_instance::ptr get_list() const { - if (mode_ == 0) { - return list_; - } else { - aggregate_of_instance::ptr l(new aggregate_of_instance); - for (auto& p : instances_by_level_) { - l->push(p.second); - } - return l; - } - } + aggregate_of_instance::ptr get_list() const { + if (mode_ == 0) { + return list_; + } else { + aggregate_of_instance::ptr l(new aggregate_of_instance); + for (auto& p : instances_by_level_) { + l->push(p.second); + } + return l; + } + } }; class traversal_visitor { -private: - std::set& visited_; - traversal_recorder& list_; - int level_; - int max_level_; + private: + std::set& visited_; + traversal_recorder& list_; + int level_; + int max_level_; -public: - traversal_visitor(std::set& visited, traversal_recorder& list, int level, int max_level) - : visited_(visited) - , list_(list) - , level_(level) - , max_level_(max_level) - {} + public: + traversal_visitor(std::set& visited, traversal_recorder& list, int level, int max_level) + : visited_(visited), + list_(list), + level_(level), + max_level_(max_level) {} - void operator()(IfcUtil::IfcBaseClass* inst, int index); + void operator()(IfcUtil::IfcBaseClass* inst, int index); }; void traverse_(IfcUtil::IfcBaseClass* instance, std::set& visited, traversal_recorder& list, int level, int max_level) { - if (visited.find(instance) != visited.end()) { - return; - } - visited.insert(instance); - list.push_back(level, instance); + if (visited.find(instance) != visited.end()) { + return; + } + visited.insert(instance); + list.push_back(level, instance); - if (level >= max_level && max_level > 0) return; + if (level >= max_level && max_level > 0) { + return; + } - traversal_visitor visit(visited, list, level + 1, max_level); - apply_individual_instance_visitor(&instance->data()).apply(visit); + traversal_visitor visit(visited, list, level + 1, max_level); + apply_individual_instance_visitor(&instance->data()).apply(visit); } void traversal_visitor::operator()(IfcUtil::IfcBaseClass* inst, int /* index */) { - traverse_(inst, visited_, list_, level_, max_level_); + traverse_(inst, visited_, list_, level_, max_level_); } aggregate_of_instance::ptr IfcParse::traverse(IfcUtil::IfcBaseClass* instance, int max_level) { - std::set visited; - traversal_recorder r(0); - traverse_(instance, visited, r, 0, max_level); - return r.get_list(); + std::set visited; + traversal_recorder r(0); + traverse_(instance, visited, r, 0, max_level); + return r.get_list(); } // I'm cheating this isn't breadth-first, but rather we record visited instances // keeping track of their rank and return a list ordered by rank. Is this equivalent? aggregate_of_instance::ptr IfcParse::traverse_breadth_first(IfcUtil::IfcBaseClass* instance, int max_level) { - std::set visited; - traversal_recorder r(1); - traverse_(instance, visited, r, 0, max_level); - return r.get_list(); + std::set visited; + traversal_recorder r(1); + traverse_(instance, visited, r, 0, max_level); + return r.get_list(); } /// @note: for backwards compatibility aggregate_of_instance::ptr IfcFile::traverse(IfcUtil::IfcBaseClass* instance, int max_level) { - return IfcParse::traverse(instance, max_level); + return IfcParse::traverse(instance, max_level); } /// @note: for backwards compatibility aggregate_of_instance::ptr IfcFile::traverse_breadth_first(IfcUtil::IfcBaseClass* instance, int max_level) { - return IfcParse::traverse_breadth_first(instance, max_level); + return IfcParse::traverse_breadth_first(instance, max_level); } void IfcFile::addEntities(aggregate_of_instance::ptr es) { - for( aggregate_of_instance::it i = es->begin(); i != es->end(); ++ i ) { - addEntity(*i); - } + for (aggregate_of_instance::it i = es->begin(); i != es->end(); ++i) { + addEntity(*i); + } } IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id) { - if (id != -1 && byid.find((unsigned)id) != byid.end()) { - throw IfcParse::IfcException("An instance with id " + boost::lexical_cast(id) + " is already part of this file"); - } + if (id != -1 && byid.find((unsigned)id) != byid.end()) { + throw IfcParse::IfcException("An instance with id " + boost::lexical_cast(id) + " is already part of this file"); + } - if (entity->declaration().schema() != schema()) { - throw IfcParse::IfcException("Unabled to add instance from " + entity->declaration().schema()->name() + " schema to file with " + schema()->name() + " schema"); - } + if (entity->declaration().schema() != schema()) { + throw IfcParse::IfcException("Unabled to add instance from " + entity->declaration().schema()->name() + " schema to file with " + schema()->name() + " schema"); + } - // If this instance has been inserted before, return - // a reference to the copy that was created from it. - entity_entity_map_t::iterator mit = entity_file_map.find(entity->identity()); - if (mit != entity_file_map.end()) { - return mit->second; - } + // If this instance has been inserted before, return + // a reference to the copy that was created from it. + entity_entity_map_t::iterator mit = entity_file_map.find(entity->identity()); + if (mit != entity_file_map.end()) { + return mit->second; + } - IfcUtil::IfcBaseClass* new_entity = entity; + IfcUtil::IfcBaseClass* new_entity = entity; - // Obtain all forward references by a depth-first - // traversal and add them to the file. - if (parsing_complete_) { - try { - aggregate_of_instance::ptr entity_attributes = traverse(entity, 1); - for (aggregate_of_instance::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) { - if (*it != entity) { - entity_entity_map_t::iterator mit2 = entity_file_map.find((*it)->identity()); - if (mit2 == entity_file_map.end()) { - entity_file_map.insert(entity_entity_map_t::value_type((*it)->identity(), addEntity(*it))); - } - } - } - } catch (...) { - Logger::Message(Logger::LOG_ERROR, "Failed to visit forward references of", entity); - } - } + // Obtain all forward references by a depth-first + // traversal and add them to the file. + if (parsing_complete_) { + try { + aggregate_of_instance::ptr entity_attributes = traverse(entity, 1); + for (aggregate_of_instance::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) { + if (*it != entity) { + entity_entity_map_t::iterator mit2 = entity_file_map.find((*it)->identity()); + if (mit2 == entity_file_map.end()) { + entity_file_map.insert(entity_entity_map_t::value_type((*it)->identity(), addEntity(*it))); + } + } + } + } catch (...) { + Logger::Message(Logger::LOG_ERROR, "Failed to visit forward references of", entity); + } + } - // See whether the instance is already part of a file - if (entity->data().file != 0) { - if (entity->data().file == this) { - if (!entity->declaration().as_entity()) { - // While not a mapping that can be queried, we do need to free the instance later on - byidentity[new_entity->identity()] = new_entity; - } + // See whether the instance is already part of a file + if (entity->data().file != 0) { + if (entity->data().file == this) { + if (!entity->declaration().as_entity()) { + // While not a mapping that can be queried, we do need to free the instance later on + byidentity[new_entity->identity()] = new_entity; + } - // If it is part of this file - // nothing else needs to be done. - return entity; - } + // If it is part of this file + // nothing else needs to be done. + return entity; + } - // An instance is being added from another file. A copy of the - // container and entity is created. The attribute references - // need to be updated to point to instances in this file. - IfcFile* other_file = entity->data().file; - IfcEntityInstanceData* we = new IfcEntityInstanceData(entity->data()); - new_entity = schema()->instantiate(we); - - // In case an entity is added that contains geometry, the unit - // information needs to be accounted for for IfcLengthMeasures. + // An instance is being added from another file. A copy of the + // container and entity is created. The attribute references + // need to be updated to point to instances in this file. + IfcFile* other_file = entity->data().file; + IfcEntityInstanceData* we = new IfcEntityInstanceData(entity->data()); + new_entity = schema()->instantiate(we); + + // In case an entity is added that contains geometry, the unit + // information needs to be accounted for for IfcLengthMeasures. double conversion_factor = std::numeric_limits::quiet_NaN(); - for (size_t i = 0; i < we->getArgumentCount(); ++i) { - Argument* attr = we->getArgument(i); - IfcUtil::ArgumentType attr_type = attr->type(); + for (size_t i = 0; i < we->getArgumentCount(); ++i) { + Argument* attr = we->getArgument(i); + IfcUtil::ArgumentType attr_type = attr->type(); - IfcParse::declaration* decl = 0; - if (entity->declaration().as_entity()) { - decl = 0; - const parameter_type* pt = entity->declaration().as_entity()->attribute_by_index(i)->type_of_attribute(); - while (pt->as_aggregation_type()) { - pt = pt->as_aggregation_type()->type_of_element(); - } - if (pt->as_named_type()) { - decl = pt->as_named_type()->declared_type(); - } - } - - if (attr_type == IfcUtil::Argument_ENTITY_INSTANCE) { - entity_entity_map_t::const_iterator eit = entity_file_map.find(((IfcUtil::IfcBaseClass*)(*attr))->identity()); - if (eit == entity_file_map.end()) throw IfcParse::IfcException("Unable to map instance to file"); - - IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); - copy->set(eit->second); - we->setArgument(i, copy); - } else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) { - aggregate_of_instance::ptr instances = *attr; - aggregate_of_instance::ptr new_instances(new aggregate_of_instance); - for (aggregate_of_instance::it it = instances->begin(); it != instances->end(); ++it) { - entity_entity_map_t::const_iterator eit = entity_file_map.find((*it)->identity()); - if (eit == entity_file_map.end()) throw IfcParse::IfcException("Unable to map instance to file"); - new_instances->push(eit->second); - } - - IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); - copy->set(new_instances); - we->setArgument(i, copy); - } else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) { - aggregate_of_aggregate_of_instance::ptr instances = *attr; - aggregate_of_aggregate_of_instance::ptr new_instances(new aggregate_of_aggregate_of_instance); - for (aggregate_of_aggregate_of_instance::outer_it it = instances->begin(); it != instances->end(); ++it) { - std::vector list; - for (aggregate_of_aggregate_of_instance::inner_it jt = it->begin(); jt != it->end(); ++jt) { - entity_entity_map_t::const_iterator eit = entity_file_map.find((*jt)->identity()); - if (eit == entity_file_map.end()) throw IfcParse::IfcException("Unable to map instance to file"); - list.push_back(eit->second); - } - new_instances->push(list); - } + IfcParse::declaration* decl = 0; + if (entity->declaration().as_entity()) { + decl = 0; + const parameter_type* pt = entity->declaration().as_entity()->attribute_by_index(i)->type_of_attribute(); + while (pt->as_aggregation_type()) { + pt = pt->as_aggregation_type()->type_of_element(); + } + if (pt->as_named_type()) { + decl = pt->as_named_type()->declared_type(); + } + } - IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); - copy->set(new_instances); - we->setArgument(i, copy); - } else if (decl && decl->is(*schema()->declaration_by_name("IfcLengthMeasure"))) { - if (boost::math::isnan(conversion_factor)) { - std::pair this_file_unit = { nullptr, 1.0 }; - std::pair other_file_unit = { nullptr, 1.0 }; - try { - this_file_unit = getUnit("LENGTHUNIT"); - other_file_unit = other_file->getUnit("LENGTHUNIT"); - } catch (IfcParse::IfcException&) {} - if (this_file_unit.first && other_file_unit.first) { - conversion_factor = other_file_unit.second / this_file_unit.second; - } else { - conversion_factor = 1.; - } - } - if (attr_type == IfcUtil::Argument_DOUBLE) { - double v = *attr; - v *= conversion_factor; - - IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); - copy->set(v); - we->setArgument(i, copy); - } else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) { - std::vector v = *attr; - for (std::vector::iterator it = v.begin(); it != v.end(); ++it) { - (*it) *= conversion_factor; - } - - IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); - copy->set(v); - we->setArgument(i, copy); - } else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE) { - std::vector> v = *attr; - for (std::vector>::iterator it = v.begin(); it != v.end(); ++it) { - std::vector& v2 = (*it); - for (std::vector::iterator jt = v2.begin(); jt != v2.end(); ++jt) { - (*jt) *= conversion_factor; - } - } + if (attr_type == IfcUtil::Argument_ENTITY_INSTANCE) { + entity_entity_map_t::const_iterator eit = entity_file_map.find(((IfcUtil::IfcBaseClass*)(*attr))->identity()); + if (eit == entity_file_map.end()) { + throw IfcParse::IfcException("Unable to map instance to file"); + } - IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); - copy->set(v); - we->setArgument(i, copy); - } - } - } + IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); + copy->set(eit->second); + we->setArgument(i, copy); + } else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) { + aggregate_of_instance::ptr instances = *attr; + aggregate_of_instance::ptr new_instances(new aggregate_of_instance); + for (aggregate_of_instance::it it = instances->begin(); it != instances->end(); ++it) { + entity_entity_map_t::const_iterator eit = entity_file_map.find((*it)->identity()); + if (eit == entity_file_map.end()) { + throw IfcParse::IfcException("Unable to map instance to file"); + } + new_instances->push(eit->second); + } - // A new entity instance name is generated and - // the instance is pointed to this file. - we->file = this; - if (we->type()->as_entity()) { - if (id == -1) { - we->set_id(FreshId()); - } else { - we->set_id((unsigned int)id); - if ((unsigned) id > MaxId) { - MaxId = (unsigned)id; - } - } - } + IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); + copy->set(new_instances); + we->setArgument(i, copy); + } else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) { + aggregate_of_aggregate_of_instance::ptr instances = *attr; + aggregate_of_aggregate_of_instance::ptr new_instances(new aggregate_of_aggregate_of_instance); + for (aggregate_of_aggregate_of_instance::outer_it it = instances->begin(); it != instances->end(); ++it) { + std::vector list; + for (aggregate_of_aggregate_of_instance::inner_it jt = it->begin(); jt != it->end(); ++jt) { + entity_entity_map_t::const_iterator eit = entity_file_map.find((*jt)->identity()); + if (eit == entity_file_map.end()) { + throw IfcParse::IfcException("Unable to map instance to file"); + } + list.push_back(eit->second); + } + new_instances->push(list); + } - entity_file_map.insert(entity_entity_map_t::value_type(entity->identity(), new_entity)); - } + IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); + copy->set(new_instances); + we->setArgument(i, copy); + } else if (decl && decl->is(*schema()->declaration_by_name("IfcLengthMeasure"))) { + if (boost::math::isnan(conversion_factor)) { + std::pair this_file_unit = {nullptr, 1.0}; + std::pair other_file_unit = {nullptr, 1.0}; + try { + this_file_unit = getUnit("LENGTHUNIT"); + other_file_unit = other_file->getUnit("LENGTHUNIT"); + } catch (IfcParse::IfcException&) { + } + if (this_file_unit.first && other_file_unit.first) { + conversion_factor = other_file_unit.second / this_file_unit.second; + } else { + conversion_factor = 1.; + } + } + if (attr_type == IfcUtil::Argument_DOUBLE) { + double v = *attr; + v *= conversion_factor; - // For subtypes of IfcRoot, the GUID mapping needs to be updated. - if (new_entity->declaration().is(*ifcroot_type_)) { - try { - const std::string guid = *new_entity->data().getArgument(0); - if ( byguid.find(guid) != byguid.end() ) { - std::stringstream ss; - ss << "Overwriting entity with guid " << guid; - Logger::Message(Logger::LOG_WARNING,ss.str()); - } - byguid[guid] = new_entity; - } catch (const IfcException& ex) { - Logger::Message(Logger::LOG_ERROR,ex.what()); - } - } + IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); + copy->set(v); + we->setArgument(i, copy); + } else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) { + std::vector v = *attr; + for (std::vector::iterator it = v.begin(); it != v.end(); ++it) { + (*it) *= conversion_factor; + } - // The mapping by entity type is updated. - const IfcParse::declaration* ty = &new_entity->declaration(); + IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); + copy->set(v); + we->setArgument(i, copy); + } else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE) { + std::vector> v = *attr; + for (std::vector>::iterator it = v.begin(); it != v.end(); ++it) { + std::vector& v2 = (*it); + for (std::vector::iterator jt = v2.begin(); jt != v2.end(); ++jt) { + (*jt) *= conversion_factor; + } + } - if (ty->as_entity()) { - aggregate_of_instance::ptr insts = instances_by_type_excl_subtypes(ty); - if (!insts) { - insts = aggregate_of_instance::ptr(new aggregate_of_instance()); - bytype_excl[ty] = insts; - } - insts->push(new_entity); - } + IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); + copy->set(v); + we->setArgument(i, copy); + } + } + } - for (; ty->as_entity();) { - aggregate_of_instance::ptr insts = instances_by_type(ty); - if (!insts) { - insts = aggregate_of_instance::ptr(new aggregate_of_instance()); - bytype[ty] = insts; - } - insts->push(new_entity); + // A new entity instance name is generated and + // the instance is pointed to this file. + we->file = this; + if (we->type()->as_entity()) { + if (id == -1) { + we->set_id(FreshId()); + } else { + we->set_id((unsigned int)id); + if ((unsigned)id > MaxId) { + MaxId = (unsigned)id; + } + } + } - const IfcParse::declaration* pt = ty->as_entity()->supertype(); - if (pt) { - ty = pt; - } - else { - break; - } - } + entity_file_map.insert(entity_entity_map_t::value_type(entity->identity(), new_entity)); + } - if (ty->as_entity()) { - int new_id = -1; - if (!new_entity->data().file) { - // For newly created entities ensure a valid ENTITY_INSTANCE_NAME is set - new_entity->data().file = this; - boost::optional id_value; - if (id != -1) { - id_value = (unsigned)id; - if ((unsigned)id > MaxId) { - MaxId = (unsigned)id; - } - } - new_id = new_entity->data().set_id(id_value); - } else { - new_id = new_entity->data().id(); - } + // For subtypes of IfcRoot, the GUID mapping needs to be updated. + if (new_entity->declaration().is(*ifcroot_type_)) { + try { + const std::string guid = *new_entity->data().getArgument(0); + if (byguid.find(guid) != byguid.end()) { + std::stringstream ss; + ss << "Overwriting entity with guid " << guid; + Logger::Message(Logger::LOG_WARNING, ss.str()); + } + byguid[guid] = new_entity; + } catch (const IfcException& ex) { + Logger::Message(Logger::LOG_ERROR, ex.what()); + } + } - if (byid.find(new_id) != byid.end()) { - // This should not happen - std::stringstream ss; - ss << "Overwriting entity with id " << new_id; - Logger::Message(Logger::LOG_WARNING, ss.str()); - } + // The mapping by entity type is updated. + const IfcParse::declaration* ty = &new_entity->declaration(); - // The mapping by entity instance name is updated. - byid[new_id] = new_entity; - } else if (!new_entity->data().file) { - // For non-entity instances, no mappings are updated, but the file - // pointer has to be set, so that actual copies are created in subsequent - // times. - new_entity->data().file = this; + if (ty->as_entity()) { + aggregate_of_instance::ptr insts = instances_by_type_excl_subtypes(ty); + if (!insts) { + insts = aggregate_of_instance::ptr(new aggregate_of_instance()); + bytype_excl[ty] = insts; + } + insts->push(new_entity); + } - // While not a mapping that can be queried, we do need to free the instance - byidentity[new_entity->identity()] = new_entity; - } + for (; ty->as_entity();) { + aggregate_of_instance::ptr insts = instances_by_type(ty); + if (!insts) { + insts = aggregate_of_instance::ptr(new aggregate_of_instance()); + bytype[ty] = insts; + } + insts->push(new_entity); - if (parsing_complete_ && ty->as_entity()) { - build_inverses_(new_entity); - } + const IfcParse::declaration* pt = ty->as_entity()->supertype(); + if (pt) { + ty = pt; + } else { + break; + } + } - return new_entity; + if (ty->as_entity()) { + int new_id = -1; + if (!new_entity->data().file) { + // For newly created entities ensure a valid ENTITY_INSTANCE_NAME is set + new_entity->data().file = this; + boost::optional id_value; + if (id != -1) { + id_value = (unsigned)id; + if ((unsigned)id > MaxId) { + MaxId = (unsigned)id; + } + } + new_id = new_entity->data().set_id(id_value); + } else { + new_id = new_entity->data().id(); + } + + if (byid.find(new_id) != byid.end()) { + // This should not happen + std::stringstream ss; + ss << "Overwriting entity with id " << new_id; + Logger::Message(Logger::LOG_WARNING, ss.str()); + } + + // The mapping by entity instance name is updated. + byid[new_id] = new_entity; + } else if (!new_entity->data().file) { + // For non-entity instances, no mappings are updated, but the file + // pointer has to be set, so that actual copies are created in subsequent + // times. + new_entity->data().file = this; + + // While not a mapping that can be queried, we do need to free the instance + byidentity[new_entity->identity()] = new_entity; + } + + if (parsing_complete_ && ty->as_entity()) { + build_inverses_(new_entity); + } + + return new_entity; } void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) { - const unsigned id = entity->data().id(); + const unsigned id = entity->data().id(); - IfcUtil::IfcBaseClass* file_entity = instance_by_id(id); + IfcUtil::IfcBaseClass* file_entity = instance_by_id(id); - // Attention when running removeEntity inside a loop over a list of entities to be removed. - // This invalidates the iterator. A workaround is to reverse the loop: - // boost::shared_ptr entities = ...; - // for (auto it = entities->end() - 1; it >= entities->begin(); --it) { - // IfcUtil::IfcBaseClass *const inst = *it; - // model->removeEntity(inst); - // } + // Attention when running removeEntity inside a loop over a list of entities to be removed. + // This invalidates the iterator. A workaround is to reverse the loop: + // boost::shared_ptr entities = ...; + // for (auto it = entities->end() - 1; it >= entities->begin(); --it) { + // IfcUtil::IfcBaseClass *const inst = *it; + // model->removeEntity(inst); + // } - // TODO: Create a set of weak relations. Inverse relations that do not dictate an - // instance to be retained. For example: when deleting an IfcRepresentation, the - // individual IfcRepresentationItems can not be deleted if an IfcStyledItem is - // related. Hence, the IfcRepresentationItem::StyledByItem relation could be - // characterized as weak. - // std::set weak_roots; + // TODO: Create a set of weak relations. Inverse relations that do not dictate an + // instance to be retained. For example: when deleting an IfcRepresentation, the + // individual IfcRepresentationItems can not be deleted if an IfcStyledItem is + // related. Hence, the IfcRepresentationItem::StyledByItem relation could be + // characterized as weak. + // std::set weak_roots; - if (entity != file_entity) { - throw IfcParse::IfcException("Instance not part of this file"); - } + if (entity != file_entity) { + throw IfcParse::IfcException("Instance not part of this file"); + } - batch_deletion_ids_.push_back(id); + batch_deletion_ids_.push_back(id); - if (!batch_mode_) { - process_deletion_(); - } + if (!batch_mode_) { + process_deletion_(); + } } void IfcFile::process_deletion_() { - for (auto& id : batch_deletion_ids_.get<0>()) { - auto entity = instance_by_id(id); + for (auto& id : batch_deletion_ids_.get<0>()) { + auto entity = instance_by_id(id); - aggregate_of_instance::ptr references = instances_by_reference(id); + aggregate_of_instance::ptr references = instances_by_reference(id); - // Alter entity instances with INVERSE relations to the entity being - // deleted. This is necessary to maintain a valid IFC file, because - // dangling references to it's entities name should be removed. At this - // moment, inversely related instances affected by the removal of the - // entity being deleted are not deleted themselves. - if (references) { - for (aggregate_of_instance::it iit = references->begin(); iit != references->end(); ++iit) { - IfcUtil::IfcBaseEntity* related_instance = (IfcUtil::IfcBaseEntity*) *iit; + // Alter entity instances with INVERSE relations to the entity being + // deleted. This is necessary to maintain a valid IFC file, because + // dangling references to it's entities name should be removed. At this + // moment, inversely related instances affected by the removal of the + // entity being deleted are not deleted themselves. + if (references) { + for (aggregate_of_instance::it iit = references->begin(); iit != references->end(); ++iit) { + IfcUtil::IfcBaseEntity* related_instance = (IfcUtil::IfcBaseEntity*)*iit; - if (std::find(batch_deletion_ids_.begin(), batch_deletion_ids_.end(), related_instance->data().id()) != batch_deletion_ids_.end()) { - continue; - } + if (std::find(batch_deletion_ids_.begin(), batch_deletion_ids_.end(), related_instance->data().id()) != batch_deletion_ids_.end()) { + continue; + } - for (size_t i = 0; i < related_instance->data().getArgumentCount(); ++i) { - Argument* attr = related_instance->data().getArgument(i); - if (attr->isNull()) continue; + for (size_t i = 0; i < related_instance->data().getArgumentCount(); ++i) { + Argument* attr = related_instance->data().getArgument(i); + if (attr->isNull()) { + continue; + } - IfcUtil::ArgumentType attr_type = attr->type(); - switch (attr_type) { - case IfcUtil::Argument_ENTITY_INSTANCE: { - IfcUtil::IfcBaseClass* instance_attribute = *attr; - if (instance_attribute == entity) { - IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); - copy->set(boost::blank()); - related_instance->data().setArgument(i, copy); - } } - break; - case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: { - aggregate_of_instance::ptr instance_list = *attr; - if (instance_list->contains(entity)) { - IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); - instance_list->remove(entity); - if (!instance_list->size() && related_instance->declaration().as_entity()->attribute_by_index(i)->optional()) { - // @todo we can also check the lower bound of the attribute type before setting to null. - copy->set(boost::blank()); - } else { - copy->set(instance_list); - } - related_instance->data().setArgument(i, copy); - } } - break; - case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE: { - aggregate_of_aggregate_of_instance::ptr instance_list_list = *attr; - if (instance_list_list->contains(entity)) { - aggregate_of_aggregate_of_instance::ptr new_list(new aggregate_of_aggregate_of_instance); - for (aggregate_of_aggregate_of_instance::outer_it it = instance_list_list->begin(); it != instance_list_list->end(); ++it) { - std::vector instances = *it; - std::vector::iterator jt; - while ((jt = std::find(instances.begin(), instances.end(), entity)) != instances.end()) { - instances.erase(jt); - } - new_list->push(instances); - } + IfcUtil::ArgumentType attr_type = attr->type(); + switch (attr_type) { + case IfcUtil::Argument_ENTITY_INSTANCE: { + IfcUtil::IfcBaseClass* instance_attribute = *attr; + if (instance_attribute == entity) { + IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); + copy->set(boost::blank()); + related_instance->data().setArgument(i, copy); + } + } break; + case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: { + aggregate_of_instance::ptr instance_list = *attr; + if (instance_list->contains(entity)) { + IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); + instance_list->remove(entity); + if (!instance_list->size() && related_instance->declaration().as_entity()->attribute_by_index(i)->optional()) { + // @todo we can also check the lower bound of the attribute type before setting to null. + copy->set(boost::blank()); + } else { + copy->set(instance_list); + } + related_instance->data().setArgument(i, copy); + } + } break; + case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE: { + aggregate_of_aggregate_of_instance::ptr instance_list_list = *attr; + if (instance_list_list->contains(entity)) { + aggregate_of_aggregate_of_instance::ptr new_list(new aggregate_of_aggregate_of_instance); + for (aggregate_of_aggregate_of_instance::outer_it it = instance_list_list->begin(); it != instance_list_list->end(); ++it) { + std::vector instances = *it; + std::vector::iterator jt; + while ((jt = std::find(instances.begin(), instances.end(), entity)) != instances.end()) { + instances.erase(jt); + } + new_list->push(instances); + } - IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); - copy->set(new_list); - related_instance->data().setArgument(i, copy); - } } - break; - default: break; - } - } - } - } + IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument(); + copy->set(new_list); + related_instance->data().setArgument(i, copy); + } + } break; + default: + break; + } + } + } + } - if (!batch_mode_) { - byref.erase( - byref.lower_bound({ id,-1,-1 }), - byref.upper_bound({ id, std::numeric_limits::max(), std::numeric_limits::max() }) - ); + if (!batch_mode_) { + byref.erase( + byref.lower_bound({id, -1, -1}), + byref.upper_bound({id, std::numeric_limits::max(), std::numeric_limits::max()})); - byref_excl.erase(id); + byref_excl.erase(id); - // This is based on traversal which needs instances to still be contained in the map. - // another option would be to keep byid intact for the remainder of this loop - aggregate_of_instance::ptr entity_attributes = traverse(entity, 1); - for (aggregate_of_instance::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) { - IfcUtil::IfcBaseClass* entity_attribute = *it; - if (entity_attribute == entity) continue; - const unsigned int name = entity_attribute->data().id(); - // Do not update inverses for simple types (which have id()==0 in IfcOpenShell). - if (name != 0) { - { - auto lower = byref.lower_bound({ name,-1,-1 }); - auto upper = byref.upper_bound({ name, std::numeric_limits::max(), std::numeric_limits::max() }); + // This is based on traversal which needs instances to still be contained in the map. + // another option would be to keep byid intact for the remainder of this loop + aggregate_of_instance::ptr entity_attributes = traverse(entity, 1); + for (aggregate_of_instance::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) { + IfcUtil::IfcBaseClass* entity_attribute = *it; + if (entity_attribute == entity) { + continue; + } + const unsigned int name = entity_attribute->data().id(); + // Do not update inverses for simple types (which have id()==0 in IfcOpenShell). + if (name != 0) { + { + auto lower = byref.lower_bound({name, -1, -1}); + auto upper = byref.upper_bound({name, std::numeric_limits::max(), std::numeric_limits::max()}); - for (auto byref_it = lower; byref_it != upper; ++byref_it) { - auto& ids = byref_it->second; - ids.erase(std::remove(ids.begin(), ids.end(), id), ids.end()); - } - } - { - auto byref_it = byref_excl.find(name); - if (byref_it != byref_excl.end()) { - auto& ids = byref_it->second; - ids.erase(std::remove(ids.begin(), ids.end(), id), ids.end()); - } - } - } - } - } + for (auto byref_it = lower; byref_it != upper; ++byref_it) { + auto& ids = byref_it->second; + ids.erase(std::remove(ids.begin(), ids.end(), id), ids.end()); + } + } + { + auto byref_it = byref_excl.find(name); + if (byref_it != byref_excl.end()) { + auto& ids = byref_it->second; + ids.erase(std::remove(ids.begin(), ids.end(), id), ids.end()); + } + } + } + } + } - if (entity->declaration().is(*ifcroot_type_)) { - const std::string global_id = *entity->data().getArgument(0); - auto it = byguid.find(global_id); - if (it != byguid.end()) { - byguid.erase(it); - } - else { - Logger::Warning("GlobalId on rooted instance not encountered in map"); - } - } + if (entity->declaration().is(*ifcroot_type_)) { + const std::string global_id = *entity->data().getArgument(0); + auto it = byguid.find(global_id); + if (it != byguid.end()) { + byguid.erase(it); + } else { + Logger::Warning("GlobalId on rooted instance not encountered in map"); + } + } - byid.erase(byid.find(id)); + byid.erase(byid.find(id)); - const IfcParse::declaration* ty = &entity->declaration(); + const IfcParse::declaration* ty = &entity->declaration(); - { - aggregate_of_instance::ptr instances_of_same_type = instances_by_type_excl_subtypes(ty); - instances_of_same_type->remove(entity); - if (instances_of_same_type->size() == 0) { - bytype_excl.erase(ty); - } - } + { + aggregate_of_instance::ptr instances_of_same_type = instances_by_type_excl_subtypes(ty); + instances_of_same_type->remove(entity); + if (instances_of_same_type->size() == 0) { + bytype_excl.erase(ty); + } + } - for (;;) { - aggregate_of_instance::ptr instances_of_same_type = instances_by_type(ty); - if (instances_of_same_type) { - instances_of_same_type->remove(entity); - } - if (instances_of_same_type->size() == 0) { - bytype.erase(ty); - } + for (;;) { + aggregate_of_instance::ptr instances_of_same_type = instances_by_type(ty); + if (instances_of_same_type) { + instances_of_same_type->remove(entity); + } + if (instances_of_same_type->size() == 0) { + bytype.erase(ty); + } - const IfcParse::declaration* pt = ty->as_entity()->supertype(); - if (pt) { - ty = pt; - } - else { - break; - } - } + const IfcParse::declaration* pt = ty->as_entity()->supertype(); + if (pt) { + ty = pt; + } else { + break; + } + } - // entity_file_map is in place to prevent duplicate definitions with usage of add(). - // Upon deletion the pairs need to be erased. - for (auto it = entity_file_map.begin(); it != entity_file_map.end();) { - if (it->second == entity) { - it = entity_file_map.erase(it); - } else { - ++it; - } - } + // entity_file_map is in place to prevent duplicate definitions with usage of add(). + // Upon deletion the pairs need to be erased. + for (auto it = entity_file_map.begin(); it != entity_file_map.end();) { + if (it->second == entity) { + it = entity_file_map.erase(it); + } else { + ++it; + } + } - delete entity; + delete entity; + } - } - - if (batch_mode_) { - for (auto it = byref.begin(); it != byref.end();) { - bool do_delete = batch_deletion_ids_.get<1>().find(std::get(it->first)) != batch_deletion_ids_.get<1>().end(); - if (!do_delete) { - it->second.erase(std::remove_if(it->second.begin(), it->second.end(), [this](int x) { - return batch_deletion_ids_.get<1>().find(x) != batch_deletion_ids_.get<1>().end(); - }), it->second.end()); - do_delete = it->second.empty(); - } - if (do_delete) { - it = byref.erase(it); - } - else { - ++it; - } - } + if (batch_mode_) { + for (auto it = byref.begin(); it != byref.end();) { + bool do_delete = batch_deletion_ids_.get<1>().find(std::get(it->first)) != batch_deletion_ids_.get<1>().end(); + if (!do_delete) { + it->second.erase(std::remove_if(it->second.begin(), it->second.end(), [this](int x) { + return batch_deletion_ids_.get<1>().find(x) != batch_deletion_ids_.get<1>().end(); + }), + it->second.end()); + do_delete = it->second.empty(); + } + if (do_delete) { + it = byref.erase(it); + } else { + ++it; + } + } - for (auto it = byref_excl.begin(); it != byref_excl.end();) { - bool do_delete = batch_deletion_ids_.get<1>().find(it->first) != batch_deletion_ids_.get<1>().end(); - if (!do_delete) { - it->second.erase(std::remove_if(it->second.begin(), it->second.end(), [this](int x) { - return batch_deletion_ids_.get<1>().find(x) != batch_deletion_ids_.get<1>().end(); - }), it->second.end()); - do_delete = it->second.empty(); - } - if (do_delete) { - it = byref_excl.erase(it); - } else { - ++it; - } - } - } + for (auto it = byref_excl.begin(); it != byref_excl.end();) { + bool do_delete = batch_deletion_ids_.get<1>().find(it->first) != batch_deletion_ids_.get<1>().end(); + if (!do_delete) { + it->second.erase(std::remove_if(it->second.begin(), it->second.end(), [this](int x) { + return batch_deletion_ids_.get<1>().find(x) != batch_deletion_ids_.get<1>().end(); + }), + it->second.end()); + do_delete = it->second.empty(); + } + if (do_delete) { + it = byref_excl.erase(it); + } else { + ++it; + } + } + } - batch_deletion_ids_.clear(); + batch_deletion_ids_.clear(); } aggregate_of_instance::ptr IfcFile::instances_by_type(const IfcParse::declaration* t) { - entities_by_type_t::const_iterator it = bytype.find(t); - return (it == bytype.end()) ? aggregate_of_instance::ptr() : it->second; + entities_by_type_t::const_iterator it = bytype.find(t); + return (it == bytype.end()) ? aggregate_of_instance::ptr() : it->second; } aggregate_of_instance::ptr IfcFile::instances_by_type_excl_subtypes(const IfcParse::declaration* t) { - entities_by_type_t::const_iterator it = bytype_excl.find(t); - return (it == bytype_excl.end()) ? aggregate_of_instance::ptr() : it->second; + entities_by_type_t::const_iterator it = bytype_excl.find(t); + return (it == bytype_excl.end()) ? aggregate_of_instance::ptr() : it->second; } aggregate_of_instance::ptr IfcFile::instances_by_type(const std::string& t) { - return instances_by_type(schema()->declaration_by_name(t)); + return instances_by_type(schema()->declaration_by_name(t)); } aggregate_of_instance::ptr IfcFile::instances_by_type_excl_subtypes(const std::string& t) { - return instances_by_type_excl_subtypes(schema()->declaration_by_name(t)); + return instances_by_type_excl_subtypes(schema()->declaration_by_name(t)); } aggregate_of_instance::ptr IfcFile::instances_by_reference(int t) { - aggregate_of_instance::ptr ret(new aggregate_of_instance); - for (auto& i : byref_excl[t]) { - ret->push(instance_by_id(i)); - } - return ret; + aggregate_of_instance::ptr ret(new aggregate_of_instance); + for (auto& i : byref_excl[t]) { + ret->push(instance_by_id(i)); + } + return ret; } IfcUtil::IfcBaseClass* IfcFile::instance_by_id(int id) { - entity_by_id_t::const_iterator it = byid.find(id); - if (it == byid.end()) { - throw IfcException("Instance #" + boost::lexical_cast(id) + " not found"); - } - return it->second; + entity_by_id_t::const_iterator it = byid.find(id); + if (it == byid.end()) { + throw IfcException("Instance #" + boost::lexical_cast(id) + " not found"); + } + return it->second; } IfcUtil::IfcBaseClass* IfcFile::instance_by_guid(const std::string& guid) { - entity_by_guid_t::const_iterator it = byguid.find(guid); - if ( it == byguid.end() ) { - throw IfcException("Instance with GlobalId '" + guid + "' not found"); - } else { - return it->second; - } + entity_by_guid_t::const_iterator it = byguid.find(guid); + if (it == byguid.end()) { + throw IfcException("Instance with GlobalId '" + guid + "' not found"); + } else { + return it->second; + } } // FIXME: Test destructor to delete entity and arg allocations IfcFile::~IfcFile() { - std::set entities_to_delete; - for (const auto& pair : byid) { - entities_to_delete.insert(pair.second); - } - for (const auto& pair : byidentity) { - entities_to_delete.insert(pair.second); - } - for (auto entity : entities_to_delete) { - delete entity; - } - delete stream; - delete tokens; + std::set entities_to_delete; + for (const auto& pair : byid) { + entities_to_delete.insert(pair.second); + } + for (const auto& pair : byidentity) { + entities_to_delete.insert(pair.second); + } + for (auto entity : entities_to_delete) { + delete entity; + } + delete stream; + delete tokens; } IfcFile::entity_by_id_t::const_iterator IfcFile::begin() const { - return byid.begin(); + return byid.begin(); } IfcFile::entity_by_id_t::const_iterator IfcFile::end() const { - return byid.end(); + return byid.end(); } IfcFile::type_iterator IfcFile::types_begin() const { - return bytype_excl.begin(); + return bytype_excl.begin(); } IfcFile::type_iterator IfcFile::types_end() const { - return bytype_excl.end(); + return bytype_excl.end(); } IfcFile::type_iterator IfcFile::types_incl_super_begin() const { - return bytype.begin(); + return bytype.begin(); } IfcFile::type_iterator IfcFile::types_incl_super_end() const { - return bytype.end(); + return bytype.end(); } namespace { - struct id_instance_pair_sorter { - bool operator()(const IfcParse::IfcFile::entity_by_id_t::value_type& a, const IfcParse::IfcFile::entity_by_id_t::value_type& b) const { - return a.first < b.first; - } - }; -} +struct id_instance_pair_sorter { + bool operator()(const IfcParse::IfcFile::entity_by_id_t::value_type& a, const IfcParse::IfcFile::entity_by_id_t::value_type& b) const { + return a.first < b.first; + } +}; +} // namespace -std::ostream& operator<< (std::ostream& os, const IfcParse::IfcFile& f) { - f.header().write(os); +std::ostream& operator<<(std::ostream& os, const IfcParse::IfcFile& f) { + f.header().write(os); - typedef std::vector > vector_t; - vector_t sorted(f.begin(), f.end()); - std::sort(sorted.begin(), sorted.end(), id_instance_pair_sorter()); + typedef std::vector> vector_t; + vector_t sorted(f.begin(), f.end()); + std::sort(sorted.begin(), sorted.end(), id_instance_pair_sorter()); - for (vector_t::const_iterator it = sorted.begin(); it != sorted.end(); ++ it) { - const IfcUtil::IfcBaseClass* e = it->second; - if (e->declaration().as_entity()) { - os << e->data().toString(true) << ";" << std::endl; - } - } + for (vector_t::const_iterator it = sorted.begin(); it != sorted.end(); ++it) { + const IfcUtil::IfcBaseClass* e = it->second; + if (e->declaration().as_entity()) { + os << e->data().toString(true) << ";" << std::endl; + } + } - os << "ENDSEC;" << std::endl; - os << "END-ISO-10303-21;" << std::endl; + os << "ENDSEC;" << std::endl; + os << "END-ISO-10303-21;" << std::endl; - return os; + return os; } std::string IfcFile::createTimestamp() const { - char buf[255]; - - time_t t; - time(&t); - - struct tm* ti = localtime (&t); + char buf[255]; - std::string result = ""; - if (strftime(buf,255,"%Y-%m-%dT%H:%M:%S",ti)) { - result = std::string(buf); - } + time_t t; + time(&t); - return result; + struct tm* ti = localtime(&t); + + std::string result = ""; + if (strftime(buf, 255, "%Y-%m-%dT%H:%M:%S", ti)) { + result = std::string(buf); + } + + return result; } std::vector IfcFile::get_inverse_indices(int instance_id) { - std::vector return_value; - - auto lower = byref.lower_bound({ instance_id, -1, -1 }); - auto upper = byref.upper_bound({ instance_id, std::numeric_limits::max(), std::numeric_limits::max() }); + std::vector return_value; - // Mapping of instance id to attribute offset. - std::map> mapping; - - for (auto it = lower; it != upper; ++it) { - for (auto& i : it->second) { - // We only take the tuple for the type that id=i actually is, in order not - // to count double. Because byref contains mappings for every supertype of id=i. - if (instance_by_id(i)->declaration().index_in_schema() == std::get<1>(it->first)) { - mapping[i].push_back(std::get<2>(it->first)); - } - } - } + auto lower = byref.lower_bound({instance_id, -1, -1}); + auto upper = byref.upper_bound({instance_id, std::numeric_limits::max(), std::numeric_limits::max()}); - auto refs = instances_by_reference(instance_id); + // Mapping of instance id to attribute offset. + std::map> mapping; - for (auto& r : *refs) { - auto it = mapping.find(r->data().id()); - if (it == mapping.end() || it->second.empty()) { - throw IfcException("Internal error"); - } - return_value.push_back(it->second.front()); - it->second.erase(it->second.begin()); - if (it->second.empty()) { - mapping.erase(it); - } - } + for (auto it = lower; it != upper; ++it) { + for (auto& i : it->second) { + // We only take the tuple for the type that id=i actually is, in order not + // to count double. Because byref contains mappings for every supertype of id=i. + if (instance_by_id(i)->declaration().index_in_schema() == std::get<1>(it->first)) { + mapping[i].push_back(std::get<2>(it->first)); + } + } + } - // Test whether all mappings where indeed used. - if (!mapping.empty()) { - throw IfcException("Internal error"); - } + auto refs = instances_by_reference(instance_id); - return return_value; + for (auto& r : *refs) { + auto it = mapping.find(r->data().id()); + if (it == mapping.end() || it->second.empty()) { + throw IfcException("Internal error"); + } + return_value.push_back(it->second.front()); + it->second.erase(it->second.begin()); + if (it->second.empty()) { + mapping.erase(it); + } + } + + // Test whether all mappings where indeed used. + if (!mapping.empty()) { + throw IfcException("Internal error"); + } + + return return_value; } aggregate_of_instance::ptr IfcFile::getInverse(int instance_id, const IfcParse::declaration* type, int attribute_index) { - if (type == nullptr && attribute_index == -1) { - return instances_by_reference(instance_id); - } - - aggregate_of_instance::ptr return_value(new aggregate_of_instance); - - if (attribute_index == -1) { - auto lower = byref.lower_bound({ instance_id, type->index_in_schema(), -1 }); - auto upper = byref.upper_bound({ instance_id, type->index_in_schema(), std::numeric_limits::max() }); + if (type == nullptr && attribute_index == -1) { + return instances_by_reference(instance_id); + } - for (auto it = lower; it != upper; ++it) { - for (auto& i : it->second) { - return_value->push(instance_by_id(i)); - } - } - } else { - auto it = byref.find({ instance_id, type->index_in_schema(), attribute_index }); - if (it != byref.end()) { - for (auto& i : it->second) { - return_value->push(instance_by_id(i)); - } - } - } + aggregate_of_instance::ptr return_value(new aggregate_of_instance); + if (attribute_index == -1) { + auto lower = byref.lower_bound({instance_id, type->index_in_schema(), -1}); + auto upper = byref.upper_bound({instance_id, type->index_in_schema(), std::numeric_limits::max()}); - return return_value; + for (auto it = lower; it != upper; ++it) { + for (auto& i : it->second) { + return_value->push(instance_by_id(i)); + } + } + } else { + auto it = byref.find({instance_id, type->index_in_schema(), attribute_index}); + if (it != byref.end()) { + for (auto& i : it->second) { + return_value->push(instance_by_id(i)); + } + } + } + + return return_value; } - int IfcFile::getTotalInverses(int instance_id) { - return byref_excl[instance_id].size(); + return byref_excl[instance_id].size(); } - void IfcFile::setDefaultHeaderValues() { - const std::string empty_string = ""; - std::vector file_description, schema_identifiers, empty_vector; + const std::string empty_string = ""; + std::vector file_description, schema_identifiers, empty_vector; - file_description.push_back("ViewDefinition [CoordinationView]"); - if (schema()) { - schema_identifiers.push_back(schema()->name()); - } + file_description.push_back("ViewDefinition [CoordinationView]"); + if (schema()) { + schema_identifiers.push_back(schema()->name()); + } - header().file_description().description(file_description); - header().file_description().implementation_level("2;1"); + header().file_description().description(file_description); + header().file_description().implementation_level("2;1"); - header().file_name().name(empty_string); - header().file_name().time_stamp(createTimestamp()); - header().file_name().author(empty_vector); - header().file_name().organization(empty_vector); - header().file_name().preprocessor_version("IfcOpenShell " IFCOPENSHELL_VERSION); - header().file_name().originating_system("IfcOpenShell " IFCOPENSHELL_VERSION); - header().file_name().authorization(empty_string); + header().file_name().name(empty_string); + header().file_name().time_stamp(createTimestamp()); + header().file_name().author(empty_vector); + header().file_name().organization(empty_vector); + header().file_name().preprocessor_version("IfcOpenShell " IFCOPENSHELL_VERSION); + header().file_name().originating_system("IfcOpenShell " IFCOPENSHELL_VERSION); + header().file_name().authorization(empty_string); - header().file_schema().schema_identifiers(schema_identifiers); + header().file_schema().schema_identifiers(schema_identifiers); } std::pair IfcFile::getUnit(const std::string& unit_type) { - std::pair return_value(0, 1.); + std::pair return_value(0, 1.); - aggregate_of_instance::ptr projects = instances_by_type(schema()->declaration_by_name("IfcProject")); - if (!projects || projects->size() == 0) { - try { - projects = instances_by_type(schema()->declaration_by_name("IfcContext")); - } catch ( IfcException& e ) {} - } + aggregate_of_instance::ptr projects = instances_by_type(schema()->declaration_by_name("IfcProject")); + if (!projects || projects->size() == 0) { + try { + projects = instances_by_type(schema()->declaration_by_name("IfcContext")); + } catch (IfcException& e) { + } + } - if (projects && projects->size() == 1) { - IfcUtil::IfcBaseClass* project = *projects->begin(); - - IfcUtil::IfcBaseClass* unit_assignment = *project->data().getArgument( - project->declaration().as_entity()->attribute_index("UnitsInContext") - ); - - aggregate_of_instance::ptr units = *unit_assignment->data().getArgument( - unit_assignment->declaration().as_entity()->attribute_index("Units") - ); + if (projects && projects->size() == 1) { + IfcUtil::IfcBaseClass* project = *projects->begin(); - for (aggregate_of_instance::it it = units->begin(); it != units->end(); ++it) { - IfcUtil::IfcBaseClass* unit = *it; - if (unit->declaration().is("IfcNamedUnit")) { - const std::string file_unit_type = *unit->data().getArgument( - unit->declaration().as_entity()->attribute_index("UnitType") - ); + IfcUtil::IfcBaseClass* unit_assignment = *project->data().getArgument( + project->declaration().as_entity()->attribute_index("UnitsInContext")); - if (file_unit_type != unit_type) { - continue; - } + aggregate_of_instance::ptr units = *unit_assignment->data().getArgument( + unit_assignment->declaration().as_entity()->attribute_index("Units")); - IfcUtil::IfcBaseClass* siunit = 0; - if (unit->declaration().is("IfcConversionBasedUnit")) { - IfcUtil::IfcBaseClass* mu = *unit->data().getArgument( - unit->declaration().as_entity()->attribute_index("ConversionFactor") - ); + for (aggregate_of_instance::it it = units->begin(); it != units->end(); ++it) { + IfcUtil::IfcBaseClass* unit = *it; + if (unit->declaration().is("IfcNamedUnit")) { + const std::string file_unit_type = *unit->data().getArgument( + unit->declaration().as_entity()->attribute_index("UnitType")); - IfcUtil::IfcBaseClass* vlc = *mu->data().getArgument( - mu->declaration().as_entity()->attribute_index("ValueComponent") - ); + if (file_unit_type != unit_type) { + continue; + } - IfcUtil::IfcBaseClass* unc = *mu->data().getArgument( - mu->declaration().as_entity()->attribute_index("UnitComponent") - ); + IfcUtil::IfcBaseClass* siunit = 0; + if (unit->declaration().is("IfcConversionBasedUnit")) { + IfcUtil::IfcBaseClass* mu = *unit->data().getArgument( + unit->declaration().as_entity()->attribute_index("ConversionFactor")); - return_value.second *= static_cast(*vlc->data().getArgument(0)); - return_value.first = unit; + IfcUtil::IfcBaseClass* vlc = *mu->data().getArgument( + mu->declaration().as_entity()->attribute_index("ValueComponent")); - if (unc->declaration().is("IfcSIUnit")) { - siunit = unc; - } + IfcUtil::IfcBaseClass* unc = *mu->data().getArgument( + mu->declaration().as_entity()->attribute_index("UnitComponent")); - } else if (unit->declaration().is("IfcSIUnit")) { - return_value.first = siunit = unit; - } + return_value.second *= static_cast(*vlc->data().getArgument(0)); + return_value.first = unit; - if (siunit) { - Argument* prefix = siunit->data().getArgument( - siunit->declaration().as_entity()->attribute_index("Prefix") - ); + if (unc->declaration().is("IfcSIUnit")) { + siunit = unc; + } - if (!prefix->isNull()) { - return_value.second *= IfcSIPrefixToValue(*prefix); - } - } - } - } - } + } else if (unit->declaration().is("IfcSIUnit")) { + return_value.first = siunit = unit; + } - return return_value; + if (siunit) { + Argument* prefix = siunit->data().getArgument( + siunit->declaration().as_entity()->attribute_index("Prefix")); + + if (!prefix->isNull()) { + return_value.second *= IfcSIPrefixToValue(*prefix); + } + } + } + } + } + + return return_value; } void IfcParse::IfcFile::build_inverses_(IfcUtil::IfcBaseClass* inst) { - std::function fn = [this, inst](IfcUtil::IfcBaseClass* attr, int idx) { - if (attr->declaration().as_entity()) { - unsigned entity_attribute_id = attr->data().id(); - auto decl = inst->declaration().as_entity(); - byref_excl[entity_attribute_id].push_back(inst->data().id()); - while (decl) { - byref[{entity_attribute_id, decl->index_in_schema(), idx}].push_back(inst->data().id()); - decl = decl->supertype(); - } - } - }; - - apply_individual_instance_visitor(&inst->data()).apply(fn); + std::function fn = [this, inst](IfcUtil::IfcBaseClass* attr, int idx) { + if (attr->declaration().as_entity()) { + unsigned entity_attribute_id = attr->data().id(); + auto decl = inst->declaration().as_entity(); + byref_excl[entity_attribute_id].push_back(inst->data().id()); + while (decl) { + byref[{entity_attribute_id, decl->index_in_schema(), idx}].push_back(inst->data().id()); + decl = decl->supertype(); + } + } + }; + + apply_individual_instance_visitor(&inst->data()).apply(fn); } void IfcParse::IfcFile::build_inverses() { - for (auto& pair : *this) { - build_inverses_(pair.second); - } + for (auto& pair : *this) { + build_inverses_(pair.second); + } } std::atomic_uint32_t IfcUtil::IfcBaseClass::counter_(0); diff --git a/src/ifcparse/IfcParse.h b/src/ifcparse/IfcParse.h index ce774678e2..b19406b4f0 100644 --- a/src/ifcparse/IfcParse.h +++ b/src/ifcparse/IfcParse.h @@ -27,251 +27,254 @@ #ifndef IFCPARSE_H #define IFCPARSE_H -#include "../ifcparse/macros.h" - #if defined(IFCOPENSHELL_BRANCH) && defined(IFCOPENSHELL_COMMIT) #define IFCOPENSHELL_VERSION STRINGIFY(IFCOPENSHELL_BRANCH) "-" STRINGIFY(IFCOPENSHELL_COMMIT) #else -#define IFCOPENSHELL_VERSION "0.7.0" +#define IFCOPENSHELL_VERSION "0.8.0" #endif -#include -#include -#include -#include -#include -#include -#include - -#include -#include - +#include "aggregate_of_instance.h" +#include "Argument.h" #include "ifc_parse_api.h" +#include "IfcBaseClass.h" +#include "IfcCharacterDecoder.h" +#include "IfcLogger.h" +#include "IfcSpfStream.h" +#include "macros.h" -#include "../ifcparse/IfcCharacterDecoder.h" -#include "../ifcparse/IfcBaseClass.h" -#include "../ifcparse/IfcLogger.h" -#include "../ifcparse/Argument.h" -#include "../ifcparse/aggregate_of_instance.h" - -#include "../ifcparse/IfcSpfStream.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace IfcParse { - class IfcFile; - class IfcSpfLexer; +class IfcFile; +class IfcSpfLexer; - enum TokenType { - Token_NONE, - Token_STRING, - Token_IDENTIFIER, - Token_OPERATOR, - Token_ENUMERATION, - Token_KEYWORD, - Token_INT, - Token_BOOL, - Token_FLOAT, - Token_BINARY - }; +enum TokenType { + Token_NONE, + Token_STRING, + Token_IDENTIFIER, + Token_OPERATOR, + Token_ENUMERATION, + Token_KEYWORD, + Token_INT, + Token_BOOL, + Token_FLOAT, + Token_BINARY +}; - struct Token { - IfcSpfLexer* lexer; //TODO: remove it from here - unsigned startPos; - TokenType type; - union { - char value_char; //types: OPERATOR - int value_int; //types: INT, IDENTIFIER - double value_double; //types: FLOAT - }; +struct Token { + IfcSpfLexer* lexer; //TODO: remove it from here + unsigned startPos; + TokenType type; + union { + char value_char; //types: OPERATOR + int value_int; //types: INT, IDENTIFIER + double value_double; //types: FLOAT + }; - Token() : lexer(0), startPos(0), type(Token_NONE) {} - Token(IfcSpfLexer* _lexer, unsigned _startPos, unsigned /*_endPos*/, TokenType _type) - : lexer(_lexer), startPos(_startPos), type(_type) {} - }; + Token() : lexer(0), + startPos(0), + type(Token_NONE) {} + Token(IfcSpfLexer* _lexer, unsigned _startPos, unsigned /*_endPos*/, TokenType _type) + : lexer(_lexer), + startPos(_startPos), + type(_type) {} +}; - /// Provides functions to convert Tokens to binary data - /// Tokens are merely offsets to where they can be read in the file - class IFC_PARSE_API TokenFunc { - private: - static bool startsWith(const Token& t, char c); - public: - /// Returns the offset at which the token is read from the file - // static unsigned int Offset(const Token& t); - /// Returns whether the token can be interpreted as a string - static bool isString(const Token& t); - /// Returns whether the token can be interpreted as an identifier - static bool isIdentifier(const Token& t); - /// Returns whether the token can be interpreted as a syntactical operator - static bool isOperator(const Token& t); - /// Returns whether the token is a given operator - static bool isOperator(const Token& t, char op); - /// Returns whether the token can be interpreted as an enumerated value - static bool isEnumeration(const Token& t); - /// Returns whether the token can be interpreted as a datatype name - static bool isKeyword(const Token& t); - /// Returns whether the token can be interpreted as an integer - static bool isInt(const Token& t); - /// Returns whether the token can be interpreted as a boolean - static bool isBool(const Token& t); - /// Returns whether the token can be interpreted as a logical - static bool isLogical(const Token& t); - /// Returns whether the token can be interpreted as a floating point number - static bool isFloat(const Token& t); - /// Returns whether the token can be interpreted as a binary type - static bool isBinary(const Token& t); - /// Returns the token interpreted as an integer - static int asInt(const Token& t); - /// Returns the token interpreted as an identifier - static int asIdentifier(const Token& t); - /// Returns the token interpreted as an boolean (.T. or .F.) - static bool asBool(const Token& t); - /// Returns the token interpreted as an logical (.T. or .F. or .U.) - static boost::logic::tribool asLogical(const Token& t); - /// Returns the token as a floating point number - static double asFloat(const Token& t); - /// Returns the token as a string (without the dot or apostrophe) - static std::string asString(const Token& t); - /// Returns the token as a string in internal buffer (for optimization purposes) - static const std::string &asStringRef(const Token& t); - /// Returns the token as a string (without the dot or apostrophe) - static boost::dynamic_bitset<> asBinary(const Token& t); - /// Returns a string representation of the token (including the dot or apostrophe) - static std::string toString(const Token& t); - }; +/// Provides functions to convert Tokens to binary data +/// Tokens are merely offsets to where they can be read in the file +class IFC_PARSE_API TokenFunc { + private: + static bool startsWith(const Token& t, char c); - // - // Functions for creating Tokens from an arbitary file offset - // The first 4 bits are reserved for Tokens of type ()=,;$* - // - Token OperatorTokenPtr(IfcSpfLexer* tokens, unsigned start, unsigned end); - Token GeneralTokenPtr(IfcSpfLexer* tokens, unsigned start, unsigned end); - Token NoneTokenPtr(); + public: + /// Returns the offset at which the token is read from the file + // static unsigned int Offset(const Token& t); + /// Returns whether the token can be interpreted as a string + static bool isString(const Token& t); + /// Returns whether the token can be interpreted as an identifier + static bool isIdentifier(const Token& t); + /// Returns whether the token can be interpreted as a syntactical operator + static bool isOperator(const Token& t); + /// Returns whether the token is a given operator + static bool isOperator(const Token& t, char op); + /// Returns whether the token can be interpreted as an enumerated value + static bool isEnumeration(const Token& t); + /// Returns whether the token can be interpreted as a datatype name + static bool isKeyword(const Token& t); + /// Returns whether the token can be interpreted as an integer + static bool isInt(const Token& t); + /// Returns whether the token can be interpreted as a boolean + static bool isBool(const Token& t); + /// Returns whether the token can be interpreted as a logical + static bool isLogical(const Token& t); + /// Returns whether the token can be interpreted as a floating point number + static bool isFloat(const Token& t); + /// Returns whether the token can be interpreted as a binary type + static bool isBinary(const Token& t); + /// Returns the token interpreted as an integer + static int asInt(const Token& t); + /// Returns the token interpreted as an identifier + static int asIdentifier(const Token& t); + /// Returns the token interpreted as an boolean (.T. or .F.) + static bool asBool(const Token& t); + /// Returns the token interpreted as an logical (.T. or .F. or .U.) + static boost::logic::tribool asLogical(const Token& t); + /// Returns the token as a floating point number + static double asFloat(const Token& t); + /// Returns the token as a string (without the dot or apostrophe) + static std::string asString(const Token& t); + /// Returns the token as a string in internal buffer (for optimization purposes) + static const std::string& asStringRef(const Token& t); + /// Returns the token as a string (without the dot or apostrophe) + static boost::dynamic_bitset<> asBinary(const Token& t); + /// Returns a string representation of the token (including the dot or apostrophe) + static std::string toString(const Token& t); +}; - /// A stream of tokens to be read from a IfcSpfStream. - class IFC_PARSE_API IfcSpfLexer { - private: - IfcCharacterDecoder* decoder; - unsigned int skipWhitespace(); - unsigned int skipComment(); - public: - std::string &GetTempString() const { - static my_thread_local std::string s; - return s; - } - IfcSpfStream* stream; - IfcFile* file; - IfcSpfLexer(IfcSpfStream* s, IfcFile* f); - Token Next(); - ~IfcSpfLexer(); - void TokenString(unsigned int offset, std::string &result); - }; +// +// Functions for creating Tokens from an arbitary file offset +// The first 4 bits are reserved for Tokens of type ()=,;$* +// +Token OperatorTokenPtr(IfcSpfLexer* tokens, unsigned start, unsigned end); +Token GeneralTokenPtr(IfcSpfLexer* tokens, unsigned start, unsigned end); +Token NoneTokenPtr(); - /// Argument of type list, e.g. - /// #1=IfcDirection((1.,0.,0.)); - /// ========== - class IFC_PARSE_API ArgumentList: public Argument { - private: - size_t size_; - Argument** list_; +/// A stream of tokens to be read from a IfcSpfStream. +class IFC_PARSE_API IfcSpfLexer { + private: + IfcCharacterDecoder* decoder; + unsigned int skipWhitespace(); + unsigned int skipComment(); - public: - ArgumentList() : size_(0), list_(0) {} - ArgumentList(size_t n) : size_(n), list_(new Argument*[size_] {0}) {} - ~ArgumentList(); + public: + std::string& GetTempString() const { + static my_thread_local std::string s; + return s; + } + IfcSpfStream* stream; + IfcFile* file; + IfcSpfLexer(IfcSpfStream* s, IfcFile* f); + Token Next(); + ~IfcSpfLexer(); + void TokenString(unsigned int offset, std::string& result); +}; - void read(IfcSpfLexer* t, std::vector& ids); +/// Argument of type list, e.g. +/// #1=IfcDirection((1.,0.,0.)); +/// ========== +class IFC_PARSE_API ArgumentList : public Argument { + private: + size_t size_; + Argument** list_; - IfcUtil::ArgumentType type() const; - - operator std::vector() const; - operator std::vector() const; - operator std::vector() const; - operator std::vector >() const; - operator aggregate_of_instance::ptr() const; + public: + ArgumentList() : size_(0), + list_(0) {} + ArgumentList(size_t n) : size_(n), + list_(new Argument* [size_] { 0 }) {} + ~ArgumentList(); - operator std::vector< std::vector >() const; - operator std::vector< std::vector >() const; - operator aggregate_of_aggregate_of_instance::ptr() const; + void read(IfcSpfLexer* t, std::vector& ids); - bool isNull() const; - unsigned int size() const; + IfcUtil::ArgumentType type() const; - Argument* operator [] (unsigned int i) const; + operator std::vector() const; + operator std::vector() const; + operator std::vector() const; + operator std::vector>() const; + operator aggregate_of_instance::ptr() const; - std::string toString(bool upper=false) const; + operator std::vector>() const; + operator std::vector>() const; + operator aggregate_of_aggregate_of_instance::ptr() const; - Argument**& arguments() { return list_; } - size_t& size() { return size_; } - }; + bool isNull() const; + unsigned int size() const; + Argument* operator[](unsigned int i) const; - /// Argument being null, e.g. '$' - /// == === - class IFC_PARSE_API NullArgument : public Argument { - public: - NullArgument() {} - IfcUtil::ArgumentType type() const { return IfcUtil::Argument_NULL; } - bool isNull() const { return true; } - unsigned int size() const { return 1; } - Argument* operator [] (unsigned int /*i*/) const { throw IfcException("Argument is not a list of attributes"); } - std::string toString(bool /*upper=false*/) const { return "$"; } - }; + std::string toString(bool upper = false) const; - /// Argument of type scalar or string, e.g. - /// #1=IfcVector(#2,1.0); - /// == === - class IFC_PARSE_API TokenArgument : public Argument { - private: - - public: - Token token; - TokenArgument(const Token& t); + Argument**& arguments() { return list_; } + size_t& size() { return size_; } +}; - IfcUtil::ArgumentType type() const; +/// Argument being null, e.g. '$' +/// == === +class IFC_PARSE_API NullArgument : public Argument { + public: + NullArgument() {} + IfcUtil::ArgumentType type() const { return IfcUtil::Argument_NULL; } + bool isNull() const { return true; } + unsigned int size() const { return 1; } + Argument* operator[](unsigned int /*i*/) const { throw IfcException("Argument is not a list of attributes"); } + std::string toString(bool /*upper=false*/) const { return "$"; } +}; - operator int() const; - operator bool() const; - operator boost::logic::tribool() const; - operator double() const; - operator std::string() const; - operator boost::dynamic_bitset<>() const; - operator IfcUtil::IfcBaseClass*() const; +/// Argument of type scalar or string, e.g. +/// #1=IfcVector(#2,1.0); +/// == === +class IFC_PARSE_API TokenArgument : public Argument { + private: + public: + Token token; + TokenArgument(const Token& t); - bool isNull() const; - unsigned int size() const; + IfcUtil::ArgumentType type() const; - Argument* operator [] (unsigned int i) const; - std::string toString(bool upper=false) const; - }; + operator int() const; + operator bool() const; + operator boost::logic::tribool() const; + operator double() const; + operator std::string() const; + operator boost::dynamic_bitset<>() const; + operator IfcUtil::IfcBaseClass*() const; - /// Argument of an IFC simple type - /// #1=IfcTrimmedCurve(#2,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.)),.T.,.PARAMETER.); - /// ===================== ===================== - class IFC_PARSE_API EntityArgument : public Argument { - private: - IfcUtil::IfcBaseClass* entity; - public: - EntityArgument(const Token& t); - ~EntityArgument(); + bool isNull() const; + unsigned int size() const; - IfcUtil::ArgumentType type() const; + Argument* operator[](unsigned int i) const; + std::string toString(bool upper = false) const; +}; - operator IfcUtil::IfcBaseClass*() const; +/// Argument of an IFC simple type +/// #1=IfcTrimmedCurve(#2,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.)),.T.,.PARAMETER.); +/// ===================== ===================== +class IFC_PARSE_API EntityArgument : public Argument { + private: + IfcUtil::IfcBaseClass* entity; - bool isNull() const; - unsigned int size() const; + public: + EntityArgument(const Token& t); + ~EntityArgument(); - Argument* operator [] (unsigned int i) const; - std::string toString(bool upper=false) const; - }; - - IFC_PARSE_API IfcEntityInstanceData* read(unsigned int i, IfcFile* t, boost::optional offset = boost::none); + IfcUtil::ArgumentType type() const; - IFC_PARSE_API aggregate_of_instance::ptr traverse(IfcUtil::IfcBaseClass* instance, int max_level = -1); + operator IfcUtil::IfcBaseClass*() const; - IFC_PARSE_API aggregate_of_instance::ptr traverse_breadth_first(IfcUtil::IfcBaseClass* instance, int max_level = -1); -} + bool isNull() const; + unsigned int size() const; -IFC_PARSE_API std::ostream& operator<< (std::ostream& os, const IfcParse::IfcFile& f); + Argument* operator[](unsigned int i) const; + std::string toString(bool upper = false) const; +}; + +IFC_PARSE_API IfcEntityInstanceData* read(unsigned int i, IfcFile* t, boost::optional offset = boost::none); + +IFC_PARSE_API aggregate_of_instance::ptr traverse(IfcUtil::IfcBaseClass* instance, int max_level = -1); + +IFC_PARSE_API aggregate_of_instance::ptr traverse_breadth_first(IfcUtil::IfcBaseClass* instance, int max_level = -1); +} // namespace IfcParse + +IFC_PARSE_API std::ostream& operator<<(std::ostream& os, const IfcParse::IfcFile& f); #endif diff --git a/src/ifcparse/IfcSIPrefix.cpp b/src/ifcparse/IfcSIPrefix.cpp index 032580f90a..d2dc91cb9d 100644 --- a/src/ifcparse/IfcSIPrefix.cpp +++ b/src/ifcparse/IfcSIPrefix.cpp @@ -20,85 +20,103 @@ #include "IfcSIPrefix.h" #ifdef HAS_SCHEMA_2x3 -#include "../ifcparse/Ifc2x3.h" +#include "Ifc2x3.h" #endif #ifdef HAS_SCHEMA_4 -#include "../ifcparse/Ifc4.h" +#include "Ifc4.h" #endif #ifdef HAS_SCHEMA_4x1 -#include "../ifcparse/Ifc4x1.h" +#include "Ifc4x1.h" #endif #ifdef HAS_SCHEMA_4x2 -#include "../ifcparse/Ifc4x2.h" +#include "Ifc4x2.h" #endif #ifdef HAS_SCHEMA_4x3_rc1 -#include "../ifcparse/Ifc4x3_rc1.h" +#include "Ifc4x3_rc1.h" #endif #ifdef HAS_SCHEMA_4x3_rc2 -#include "../ifcparse/Ifc4x3_rc2.h" +#include "Ifc4x3_rc2.h" #endif #ifdef HAS_SCHEMA_4x3_rc3 -#include "../ifcparse/Ifc4x3_rc3.h" +#include "Ifc4x3_rc3.h" #endif #ifdef HAS_SCHEMA_4x3_rc4 -#include "../ifcparse/Ifc4x3_rc4.h" +#include "Ifc4x3_rc4.h" #endif #ifdef HAS_SCHEMA_4x3 -#include "../ifcparse/Ifc4x3.h" +#include "Ifc4x3.h" #endif #ifdef HAS_SCHEMA_4x3_tc1 -#include "../ifcparse/Ifc4x3_tc1.h" +#include "Ifc4x3_tc1.h" #endif #ifdef HAS_SCHEMA_4x3_add1 -#include "../ifcparse/Ifc4x3_add1.h" +#include "Ifc4x3_add1.h" #endif double IfcParse::IfcSIPrefixToValue(const std::string& v) { - if ( v == "EXA" ) return 1.e18; - else if ( v == "PETA" ) return 1.e15; - else if ( v == "TERA" ) return 1.e12; - else if ( v == "GIGA" ) return 1.e9; - else if ( v == "MEGA" ) return 1.e6; - else if ( v == "KILO" ) return 1.e3; - else if ( v == "HECTO" ) return 1.e2; - else if ( v == "DECA" ) return 1.e1; - else if ( v == "DECI" ) return 1.e-1; - else if ( v == "CENTI" ) return 1.e-2; - else if ( v == "MILLI" ) return 1.e-3; - else if ( v == "MICRO" ) return 1.e-6; - else if ( v == "NANO" ) return 1.e-9; - else if ( v == "PICO" ) return 1.e-12; - else if ( v == "FEMTO" ) return 1.e-15; - else if ( v == "ATTO" ) return 1.e-18; - else return 1.; + if (v == "EXA") { + return 1.e18; + } else if (v == "PETA") { + return 1.e15; + } else if (v == "TERA") { + return 1.e12; + } else if (v == "GIGA") { + return 1.e9; + } else if (v == "MEGA") { + return 1.e6; + } else if (v == "KILO") { + return 1.e3; + } else if (v == "HECTO") { + return 1.e2; + } else if (v == "DECA") { + return 1.e1; + } else if (v == "DECI") { + return 1.e-1; + } else if (v == "CENTI") { + return 1.e-2; + } else if (v == "MILLI") { + return 1.e-3; + } else if (v == "MICRO") { + return 1.e-6; + } else if (v == "NANO") { + return 1.e-9; + } else if (v == "PICO") { + return 1.e-12; + } else if (v == "FEMTO") { + return 1.e-15; + } else if (v == "ATTO") { + return 1.e-18; + } else { + return 1.; + } } template double IfcParse::get_SI_equivalent(typename Schema::IfcNamedUnit* named_unit) { - double scale = 1.; - typename Schema::IfcSIUnit* si_unit = 0; + double scale = 1.; + typename Schema::IfcSIUnit* si_unit = 0; - if (named_unit->declaration().is(Schema::IfcConversionBasedUnit::Class())) { - typename Schema::IfcConversionBasedUnit* conv_unit = named_unit->template as(); - typename Schema::IfcMeasureWithUnit* factor = conv_unit->ConversionFactor(); - typename Schema::IfcUnit* component = factor->UnitComponent(); - if (component->declaration().is(Schema::IfcSIUnit::Class())) { - si_unit = component->template as(); - typename Schema::IfcValue* v = factor->ValueComponent(); - scale = *v->data().getArgument(0); - } - } else if (named_unit->declaration().is(Schema::IfcSIUnit::Class())) { - si_unit = named_unit->template as(); - } - if (si_unit) { - if (si_unit->Prefix()) { - scale *= IfcSIPrefixToValue(Schema::IfcSIPrefix::ToString(*si_unit->Prefix())); - } - } else { - scale = 0.; - } + if (named_unit->declaration().is(Schema::IfcConversionBasedUnit::Class())) { + typename Schema::IfcConversionBasedUnit* conv_unit = named_unit->template as(); + typename Schema::IfcMeasureWithUnit* factor = conv_unit->ConversionFactor(); + typename Schema::IfcUnit* component = factor->UnitComponent(); + if (component->declaration().is(Schema::IfcSIUnit::Class())) { + si_unit = component->template as(); + typename Schema::IfcValue* v = factor->ValueComponent(); + scale = *v->data().getArgument(0); + } + } else if (named_unit->declaration().is(Schema::IfcSIUnit::Class())) { + si_unit = named_unit->template as(); + } + if (si_unit) { + if (si_unit->Prefix()) { + scale *= IfcSIPrefixToValue(Schema::IfcSIPrefix::ToString(*si_unit->Prefix())); + } + } else { + scale = 0.; + } - return scale; + return scale; } #if defined(_MSC_VER) && _MSC_VER < 1900 diff --git a/src/ifcparse/IfcSIPrefix.h b/src/ifcparse/IfcSIPrefix.h index 0fd9c99d84..2285d61661 100644 --- a/src/ifcparse/IfcSIPrefix.h +++ b/src/ifcparse/IfcSIPrefix.h @@ -20,14 +20,14 @@ #ifndef IFCSIPREFIX #define IFCSIPREFIX -#include "../ifcparse/IfcParse.h" #include "ifc_parse_api.h" +#include "IfcParse.h" namespace IfcParse { - IFC_PARSE_API double IfcSIPrefixToValue(const std::string& prefix); +IFC_PARSE_API double IfcSIPrefixToValue(const std::string& prefix); - template - IFC_PARSE_API double get_SI_equivalent(typename Schema::IfcNamedUnit*); -} +template +IFC_PARSE_API double get_SI_equivalent(typename Schema::IfcNamedUnit*); +} // namespace IfcParse #endif diff --git a/src/ifcparse/IfcSchema.cpp b/src/ifcparse/IfcSchema.cpp index a21023a865..48b1cfae20 100644 --- a/src/ifcparse/IfcSchema.cpp +++ b/src/ifcparse/IfcSchema.cpp @@ -1,226 +1,261 @@ +/******************************************************************************** +* * +* 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 . * +* * +********************************************************************************/ + #include "IfcSchema.h" -#include "../ifcparse/IfcBaseClass.h" + +#include "IfcBaseClass.h" + +#ifdef HAS_SCHEMA_2x3 +#include "Ifc2x3.h" +#endif +#ifdef HAS_SCHEMA_4 +#include "Ifc4.h" +#endif +#ifdef HAS_SCHEMA_4x1 +#include "Ifc4x1.h" +#endif +#ifdef HAS_SCHEMA_4x2 +#include "Ifc4x2.h" +#endif +#ifdef HAS_SCHEMA_4x3_rc1 +#include "Ifc4x3_rc1.h" +#endif +#ifdef HAS_SCHEMA_4x3_rc2 +#include "Ifc4x3_rc2.h" +#endif +#ifdef HAS_SCHEMA_4x3_rc3 +#include "Ifc4x3_rc3.h" +#endif +#ifdef HAS_SCHEMA_4x3_rc4 +#include "Ifc4x3_rc4.h" +#endif +#ifdef HAS_SCHEMA_4x3 +#include "Ifc4x3.h" +#endif +#ifdef HAS_SCHEMA_4x3_tc1 +#include "Ifc4x3_tc1.h" +#endif +#ifdef HAS_SCHEMA_4x3_add1 +#include "Ifc4x3_add1.h" +#endif #include bool IfcParse::declaration::is(const std::string& name) const { - const std::string* name_ptr = &name; - if (std::any_of(name.begin(), name.end(), [](char c) { return std::islower(c); })) { - temp_string_() = name; - boost::to_upper(temp_string_()); - name_ptr = &temp_string_(); - } + const std::string* name_ptr = &name; + if (std::any_of(name.begin(), name.end(), [](char c) { return std::islower(c); })) { + temp_string_() = name; + boost::to_upper(temp_string_()); + name_ptr = &temp_string_(); + } - if (name_upper_ == *name_ptr) return true; + if (name_upper_ == *name_ptr) { + return true; + } - if (this->as_entity() && this->as_entity()->supertype()) { - return this->as_entity()->supertype()->is(name); - } else if (this->as_type_declaration()) { - const IfcParse::named_type* nt = this->as_type_declaration()->declared_type()->as_named_type(); - if (nt) return nt->is(name); - } + if (this->as_entity() && this->as_entity()->supertype()) { + return this->as_entity()->supertype()->is(name); + } else if (this->as_type_declaration()) { + const IfcParse::named_type* nt = this->as_type_declaration()->declared_type()->as_named_type(); + if (nt) { + return nt->is(name); + } + } - return false; + return false; } bool IfcParse::declaration::is(const IfcParse::declaration& decl) const { - if (this == &decl) return true; + if (this == &decl) { + return true; + } - if (this->as_entity() && this->as_entity()->supertype()) { - return this->as_entity()->supertype()->is(decl); - } else if (this->as_type_declaration()) { - const IfcParse::named_type* nt = this->as_type_declaration()->declared_type()->as_named_type(); - if (nt) return nt->is(decl); - } + if (this->as_entity() && this->as_entity()->supertype()) { + return this->as_entity()->supertype()->is(decl); + } else if (this->as_type_declaration()) { + const IfcParse::named_type* nt = this->as_type_declaration()->declared_type()->as_named_type(); + if (nt) { + return nt->is(decl); + } + } - return false; + return false; } bool IfcParse::named_type::is(const std::string& name) const { - return declared_type()->is(name); + return declared_type()->is(name); } bool IfcParse::named_type::is(const IfcParse::declaration& decl) const { - return declared_type()->is(decl); + return declared_type()->is(decl); } IfcParse::entity::~entity() { - for (auto attribute : attributes_) { - delete attribute; - } - for (auto inverse_attribute : inverse_attributes_) { - delete inverse_attribute; - } + for (auto attribute : attributes_) { + delete attribute; + } + for (auto inverse_attribute : inverse_attributes_) { + delete inverse_attribute; + } } static std::map schemas; IfcParse::schema_definition::schema_definition(const std::string& name, const std::vector& declarations, instance_factory* factory) - : name_(name) - , declarations_(declarations) - , factory_(factory) -{ - std::sort(declarations_.begin(), declarations_.end(), declaration_by_index_sort()); - for (std::vector::iterator it = declarations_.begin(); it != declarations_.end(); ++it) { - (**it).schema_ = this; + : name_(name), + declarations_(declarations), + factory_(factory) { + std::sort(declarations_.begin(), declarations_.end(), declaration_by_index_sort()); + for (std::vector::iterator it = declarations_.begin(); it != declarations_.end(); ++it) { + (**it).schema_ = this; - if ((**it).as_type_declaration()) type_declarations_.push_back((**it).as_type_declaration()); - if ((**it).as_select_type()) select_types_.push_back((**it).as_select_type()); - if ((**it).as_enumeration_type()) enumeration_types_.push_back((**it).as_enumeration_type()); - if ((**it).as_entity()) entities_.push_back((**it).as_entity()); - } - schemas[name_] = this; + if ((**it).as_type_declaration()) { + type_declarations_.push_back((**it).as_type_declaration()); + } + if ((**it).as_select_type()) { + select_types_.push_back((**it).as_select_type()); + } + if ((**it).as_enumeration_type()) { + enumeration_types_.push_back((**it).as_enumeration_type()); + } + if ((**it).as_entity()) { + entities_.push_back((**it).as_entity()); + } + } + schemas[name_] = this; } IfcParse::schema_definition::~schema_definition() { - for (std::vector::const_iterator it = declarations_.begin(); it != declarations_.end(); ++it) { - delete *it; - } - delete factory_; + for (std::vector::const_iterator it = declarations_.begin(); it != declarations_.end(); ++it) { + delete *it; + } + delete factory_; } -IfcUtil::IfcBaseClass* IfcParse::schema_definition::instantiate(IfcEntityInstanceData * data) const { - if (factory_) { - return (*factory_)(data); - } else { - return new IfcUtil::IfcLateBoundEntity(data->type(), data); - } +IfcUtil::IfcBaseClass* IfcParse::schema_definition::instantiate(IfcEntityInstanceData* data) const { + if (factory_) { + return (*factory_)(data); + } else { + return new IfcUtil::IfcLateBoundEntity(data->type(), data); + } } void IfcParse::register_schema(schema_definition* s) { - schemas.insert({ boost::to_upper_copy(s->name()), s }); + schemas.insert({boost::to_upper_copy(s->name()), s}); } - -#ifdef HAS_SCHEMA_2x3 -#include "../ifcparse/Ifc2x3.h" -#endif -#ifdef HAS_SCHEMA_4 -#include "../ifcparse/Ifc4.h" -#endif -#ifdef HAS_SCHEMA_4x1 -#include "../ifcparse/Ifc4x1.h" -#endif -#ifdef HAS_SCHEMA_4x2 -#include "../ifcparse/Ifc4x2.h" -#endif -#ifdef HAS_SCHEMA_4x3_rc1 -#include "../ifcparse/Ifc4x3_rc1.h" -#endif -#ifdef HAS_SCHEMA_4x3_rc2 -#include "../ifcparse/Ifc4x3_rc2.h" -#endif -#ifdef HAS_SCHEMA_4x3_rc3 -#include "../ifcparse/Ifc4x3_rc3.h" -#endif -#ifdef HAS_SCHEMA_4x3_rc4 -#include "../ifcparse/Ifc4x3_rc4.h" -#endif -#ifdef HAS_SCHEMA_4x3 -#include "../ifcparse/Ifc4x3.h" -#endif -#ifdef HAS_SCHEMA_4x3_tc1 -#include "../ifcparse/Ifc4x3_tc1.h" -#endif -#ifdef HAS_SCHEMA_4x3_add1 -#include "../ifcparse/Ifc4x3_add1.h" -#endif - const IfcParse::schema_definition* IfcParse::schema_by_name(const std::string& name) { - // TODO: initialize automatically somehow + // TODO: initialize automatically somehow #ifdef HAS_SCHEMA_2x3 - Ifc2x3::get_schema(); + Ifc2x3::get_schema(); #endif #ifdef HAS_SCHEMA_4 - Ifc4::get_schema(); + Ifc4::get_schema(); #endif #ifdef HAS_SCHEMA_4x1 - Ifc4x1::get_schema(); + Ifc4x1::get_schema(); #endif #ifdef HAS_SCHEMA_4x2 - Ifc4x2::get_schema(); + Ifc4x2::get_schema(); #endif #ifdef HAS_SCHEMA_4x3_rc1 - Ifc4x3_rc1::get_schema(); + Ifc4x3_rc1::get_schema(); #endif #ifdef HAS_SCHEMA_4x3_rc2 - Ifc4x3_rc2::get_schema(); + Ifc4x3_rc2::get_schema(); #endif #ifdef HAS_SCHEMA_4x3_rc3 - Ifc4x3_rc3::get_schema(); + Ifc4x3_rc3::get_schema(); #endif #ifdef HAS_SCHEMA_4x3_rc4 - Ifc4x3_rc4::get_schema(); + Ifc4x3_rc4::get_schema(); #endif #ifdef HAS_SCHEMA_4x3 - Ifc4x3::get_schema(); + Ifc4x3::get_schema(); #endif #ifdef HAS_SCHEMA_4x3_tc1 - Ifc4x3_tc1::get_schema(); + Ifc4x3_tc1::get_schema(); #endif #ifdef HAS_SCHEMA_4x3_add1 - Ifc4x3_add1::get_schema(); + Ifc4x3_add1::get_schema(); #endif - std::map::const_iterator it = schemas.find(boost::to_upper_copy(name)); - if (it == schemas.end()) { - throw IfcParse::IfcException("No schema named " + name); - } - return it->second; + std::map::const_iterator it = schemas.find(boost::to_upper_copy(name)); + if (it == schemas.end()) { + throw IfcParse::IfcException("No schema named " + name); + } + return it->second; } std::vector IfcParse::schema_names() { - // Load schema modules - try { - IfcParse::schema_by_name("IFC2X3"); - } catch (IfcParse::IfcException&) {} + // Load schema modules + try { + IfcParse::schema_by_name("IFC2X3"); + } catch (IfcParse::IfcException&) { + } - // Populate vector with map keys - std::vector return_value; - for (auto& pair : schemas) { - return_value.push_back(pair.first); - } + // Populate vector with map keys + std::vector return_value; + for (auto& pair : schemas) { + return_value.push_back(pair.first); + } - return return_value; + return return_value; } void IfcParse::clear_schemas() { #ifdef HAS_SCHEMA_2x3 - Ifc2x3::clear_schema(); + Ifc2x3::clear_schema(); #endif #ifdef HAS_SCHEMA_4 - Ifc4::clear_schema(); + Ifc4::clear_schema(); #endif #ifdef HAS_SCHEMA_4x1 - Ifc4x1::clear_schema(); + Ifc4x1::clear_schema(); #endif #ifdef HAS_SCHEMA_4x2 - Ifc4x2::clear_schema(); + Ifc4x2::clear_schema(); #endif #ifdef HAS_SCHEMA_4x3_rc1 - Ifc4x3_rc1::clear_schema(); + Ifc4x3_rc1::clear_schema(); #endif #ifdef HAS_SCHEMA_4x3_rc2 - Ifc4x3_rc2::clear_schema(); + Ifc4x3_rc2::clear_schema(); #endif #ifdef HAS_SCHEMA_4x3_rc3 - Ifc4x3_rc3::clear_schema(); + Ifc4x3_rc3::clear_schema(); #endif #ifdef HAS_SCHEMA_4x3_rc4 - Ifc4x3_rc4::clear_schema(); + Ifc4x3_rc4::clear_schema(); #endif #ifdef HAS_SCHEMA_4x3 - Ifc4x3::clear_schema(); + Ifc4x3::clear_schema(); #endif #ifdef HAS_SCHEMA_4x3_tc1 - Ifc4x3_tc1::clear_schema(); + Ifc4x3_tc1::clear_schema(); #endif #ifdef HAS_SCHEMA_4x3_add1 - Ifc4x3_add1::clear_schema(); + Ifc4x3_add1::clear_schema(); #endif - // clear any remaining registered schemas - // we pop schemas until map is empty, because map iteration is invalidated after each erasure - while (!schemas.empty()) { - delete schemas.begin()->second; - } + // clear any remaining registered schemas + // we pop schemas until map is empty, because map iteration is invalidated after each erasure + while (!schemas.empty()) { + delete schemas.begin()->second; + } } diff --git a/src/ifcparse/IfcSchema.h b/src/ifcparse/IfcSchema.h index eebdf40fe4..5fbc2cceb1 100644 --- a/src/ifcparse/IfcSchema.h +++ b/src/ifcparse/IfcSchema.h @@ -20,474 +20,497 @@ #ifndef IFCSCHEMA_H #define IFCSCHEMA_H +#include "IfcException.h" + +#include +#include +#include +#include #include #include -#include -#include -#include - -#include - -#include "../ifcparse/IfcException.h" // Forward declarations class IfcEntityInstanceData; namespace IfcUtil { - class IfcBaseClass; - class IfcBaseEntity; - class IfcBaseType; -} +class IfcBaseClass; +class IfcBaseEntity; +class IfcBaseType; +} // namespace IfcUtil namespace IfcParse { - class declaration; - - class type_declaration; - class select_type; - class enumeration_type; - class entity; - - class named_type; - class simple_type; - class aggregation_type; - - class schema_definition; - - class IFC_PARSE_API parameter_type { - public: - virtual ~parameter_type() {} - - virtual const named_type* as_named_type() const { return static_cast(0); } - virtual const simple_type* as_simple_type() const { return static_cast(0); } - virtual const aggregation_type* as_aggregation_type() const { return static_cast(0); } - - virtual bool is(const std::string& /*name*/) const { return false; } - virtual bool is(const IfcParse::declaration& /*decl*/) const { return false; } - }; - - class IFC_PARSE_API named_type : public parameter_type { - protected: - declaration* declared_type_; - public: - named_type(declaration* declared_type) - : declared_type_(declared_type) {} - - declaration* declared_type() const { return declared_type_; } +class declaration; + +class type_declaration; +class select_type; +class enumeration_type; +class entity; + +class named_type; +class simple_type; +class aggregation_type; + +class schema_definition; + +class IFC_PARSE_API parameter_type { + public: + virtual ~parameter_type() {} + + virtual const named_type* as_named_type() const { return static_cast(0); } + virtual const simple_type* as_simple_type() const { return static_cast(0); } + virtual const aggregation_type* as_aggregation_type() const { return static_cast(0); } + + virtual bool is(const std::string& /*name*/) const { return false; } + virtual bool is(const IfcParse::declaration& /*decl*/) const { return false; } +}; + +class IFC_PARSE_API named_type : public parameter_type { + protected: + declaration* declared_type_; + + public: + named_type(declaration* declared_type) + : declared_type_(declared_type) {} + + declaration* declared_type() const { return declared_type_; } - virtual const named_type* as_named_type() const { return this; } + virtual const named_type* as_named_type() const { return this; } - virtual bool is(const std::string& name) const; - virtual bool is(const IfcParse::declaration& decl) const; - }; - - class IFC_PARSE_API simple_type : public parameter_type { - public: - typedef enum { binary_type, boolean_type, integer_type, logical_type, number_type, real_type, string_type, datatype_COUNT } data_type; - protected: - data_type declared_type_; - public: - simple_type(data_type declared_type) - : declared_type_(declared_type) {} + virtual bool is(const std::string& name) const; + virtual bool is(const IfcParse::declaration& decl) const; +}; - data_type declared_type() const { return declared_type_; } +class IFC_PARSE_API simple_type : public parameter_type { + public: + typedef enum { + binary_type, + boolean_type, + integer_type, + logical_type, + number_type, + real_type, + string_type, + datatype_COUNT + } data_type; - virtual const simple_type* as_simple_type() const { return this; } - }; - - class IFC_PARSE_API aggregation_type : public parameter_type { - public: - typedef enum { array_type, bag_type, list_type, set_type } aggregate_type; - protected: - aggregate_type type_of_aggregation_; - int bound1_, bound2_; - parameter_type* type_of_element_; - public: - aggregation_type(aggregate_type type_of_aggregation, int bound1, int bound2, parameter_type* type_of_element) - : type_of_aggregation_(type_of_aggregation) - , bound1_(bound1) - , bound2_(bound2) - , type_of_element_(type_of_element) - {} - - virtual ~aggregation_type() { delete type_of_element_; } - - aggregate_type type_of_aggregation() const { return type_of_aggregation_; } - int bound1() const { return bound1_; } - int bound2() const { return bound2_; } - parameter_type* type_of_element() const { return type_of_element_; } - - virtual const aggregation_type* as_aggregation_type() const { return this; } - }; - - class IFC_PARSE_API declaration { - friend class schema_definition; - - protected: - std::string name_, name_upper_; - int index_in_schema_; - mutable const schema_definition* schema_; - - std::string& temp_string_() const { - static my_thread_local std::string s; - return s; - } - - public: - declaration(const std::string& name, int index_in_schema) - : name_(name) - , name_upper_(boost::to_upper_copy(name)) - , index_in_schema_(index_in_schema) - , schema_(0) - {} - - virtual ~declaration() {} - - const std::string& name() const { return name_; } - const std::string& name_uc() const { return name_upper_; } - - virtual const type_declaration* as_type_declaration() const { return static_cast(0); } - virtual const select_type* as_select_type() const { return static_cast(0); } - virtual const enumeration_type* as_enumeration_type() const { return static_cast(0); } - virtual const entity* as_entity() const { return static_cast(0); } - - bool is(const std::string& name) const; - bool is(const IfcParse::declaration& decl) const; - - int index_in_schema() const { return index_in_schema_; } - - int type() const { return index_in_schema_; } - - const schema_definition* schema() const { return schema_; } - }; - - class IFC_PARSE_API type_declaration : public declaration { - protected: - const parameter_type* declared_type_; - - public: - type_declaration(const std::string& name, int index_in_schema, const parameter_type* declared_type) - : declaration(name, index_in_schema) - , declared_type_(declared_type) {} - - virtual ~type_declaration() { delete declared_type_; } - - const parameter_type* declared_type() const { return declared_type_; } - - virtual const type_declaration* as_type_declaration() const { return this; } - }; - - class IFC_PARSE_API select_type : public declaration { - protected: - std::vector select_list_; - public: - select_type(const std::string& name, int index_in_schema, const std::vector& select_list) - : declaration(name, index_in_schema) - , select_list_(select_list) {} - - const std::vector& select_list() const { return select_list_; } - - virtual const select_type* as_select_type() const { return this; } - }; - - class IFC_PARSE_API enumeration_type : public declaration { - protected: - std::vector enumeration_items_; - public: - enumeration_type(const std::string& name, int index_in_schema, const std::vector& enumeration_items) - : declaration(name, index_in_schema) - , enumeration_items_(enumeration_items) {} - - const std::vector& enumeration_items() const { return enumeration_items_; } - - const char* lookup_enum_value(size_t i) const { - if (i >= enumeration_items_.size()) { - throw IfcParse::IfcException("Unable to find keyword in schema for index " + std::to_string(i)); - } - return enumeration_items_[i].c_str(); - } - - size_t lookup_enum_offset(const std::string& s) const { - size_t i = 0; - for (auto it = enumeration_items_.begin(); it != enumeration_items_.end(); ++it, ++i) { - if (s == *it) { - return i; - } - } - throw IfcParse::IfcException("Unable to find keyword in schema: " + s); - } - - virtual const enumeration_type* as_enumeration_type() const { return this; } - }; - - class IFC_PARSE_API attribute { - protected: - std::string name_; - const parameter_type* type_of_attribute_; - bool optional_; - - public: - attribute(const std::string& name, parameter_type* type_of_attribute, bool optional) - : name_(name) - , type_of_attribute_(type_of_attribute) - , optional_(optional) {} - - ~attribute() { delete type_of_attribute_; } - - const std::string& name() const { return name_; } - const parameter_type* type_of_attribute() const { return type_of_attribute_; } - bool optional() const { return optional_; } - }; - - class IFC_PARSE_API inverse_attribute { - public: - typedef enum { bag_type, set_type, unspecified_type } aggregate_type; - protected: - std::string name_; - aggregate_type type_of_aggregation_; - int bound1_, bound2_; - const entity* entity_reference_; - const attribute* attribute_reference_; - public: - inverse_attribute(const std::string& name, aggregate_type type_of_aggregation, int bound1, int bound2, const entity* entity_reference, const attribute* attribute_reference) - : name_(name) - , type_of_aggregation_(type_of_aggregation) - , bound1_(bound1) - , bound2_(bound2) - , entity_reference_(entity_reference) - , attribute_reference_(attribute_reference) {} - - const std::string& name() const { return name_; } - aggregate_type type_of_aggregation() const { return type_of_aggregation_; } - int bound1() const { return bound1_; } - int bound2() const { return bound2_; } - const entity* entity_reference() const { return entity_reference_; } - const attribute* attribute_reference() const { return attribute_reference_; } - }; - - class IFC_PARSE_API entity : public declaration { - protected: - bool is_abstract_; - const entity* supertype_; /* NB: IFC explicitly allows only single inheritance */ - std::vector subtypes_; - - std::vector attributes_; - std::vector derived_; - - std::vector inverse_attributes_; - - class attribute_by_name_cmp { - private: - std::string name_; - public: - attribute_by_name_cmp(const std::string name) - : name_(name) {} - bool operator()(const attribute* attr) { - return attr->name() == name_; - } - }; - - const attribute* attribute_by_index_(size_t& index) const { - const attribute* attr = 0; - if (supertype_) { - attr = supertype_->attribute_by_index_(index); - } - if (attr == 0) { - if (index < attributes_.size()) { - attr = attributes_[index]; - } - index -= attributes_.size(); - } - return attr; - } - - public: - entity(const std::string& name, bool is_abstract, int index_in_schema, entity* supertype) - : declaration(name, index_in_schema) - , is_abstract_(is_abstract) - , supertype_(supertype) - {} - - virtual ~entity(); - - bool is_abstract() const { return is_abstract_; } - - void set_subtypes(const std::vector& subtypes) { - subtypes_ = subtypes; - } - - void set_attributes(const std::vector& attributes, const std::vector& derived) { - attributes_ = attributes; - derived_ = derived; - } - - void set_inverse_attributes(const std::vector& inverse_attributes) { - inverse_attributes_ = inverse_attributes; - } - - const std::vector& subtypes() const { return subtypes_; } - const std::vector& attributes() const { return attributes_; } - const std::vector& derived() const { return derived_; } - - const std::vector all_attributes() const { - std::vector attrs; - attrs.reserve(derived_.size()); - if (supertype_) { - const std::vector supertype_attrs = supertype_->all_attributes(); - std::copy(supertype_attrs.begin(), supertype_attrs.end(), std::back_inserter(attrs)); - } - std::copy(attributes_.begin(), attributes_.end(), std::back_inserter(attrs)); - return attrs; - } - - const std::vector all_inverse_attributes() const { - std::vector attrs; - if (supertype_) { - const std::vector supertype_inv_attrs = supertype_->all_inverse_attributes(); - std::copy(supertype_inv_attrs.begin(), supertype_inv_attrs.end(), std::back_inserter(attrs)); - } - std::copy(inverse_attributes_.begin(), inverse_attributes_.end(), std::back_inserter(attrs)); - return attrs; - } - - const attribute* attribute_by_index(size_t index) const { - const attribute* attr = attribute_by_index_(index); - if (attr == 0) { - throw IfcParse::IfcException("Attribute index out of bounds"); - } - return attr; - } - - size_t attribute_count() const { - size_t super_count = 0; - if (supertype_) { - super_count = supertype_->attribute_count(); - } - return super_count + attributes_.size(); - } - - ptrdiff_t attribute_index(const attribute* attr) const { - const entity* current = this; - ptrdiff_t index = -1; - do { - if (index > -1) { - index += current->attributes().size(); - } else { - std::vector::const_iterator it; - it = std::find(current->attributes().begin(), current->attributes().end(), attr); - if (it != current->attributes().end()) { - index = std::distance(current->attributes().begin(), it); - } - } - } while ((current = current->supertype_) != 0); - return index; - } - - ptrdiff_t attribute_index(const std::string& attr_name) const { - const entity* current = this; - ptrdiff_t index = -1; - attribute_by_name_cmp cmp(attr_name); - do { - if (index > -1) { - index += current->attributes().size(); - } else { - std::vector::const_iterator it; - it = std::find_if(current->attributes().begin(), current->attributes().end(), cmp); - if (it != current->attributes().end()) { - index = std::distance(current->attributes().begin(), it); - } - } - } while ((current = current->supertype_) != 0); - return index; - } - - const entity* supertype() const { return supertype_; } - - virtual const entity* as_entity() const { return this; } - }; - - class IFC_PARSE_API instance_factory { - public: - virtual ~instance_factory() {} - - virtual IfcUtil::IfcBaseClass* operator()(IfcEntityInstanceData* data) const = 0; - }; - - class IFC_PARSE_API schema_definition { - private: - std::string name_; - - std::vector declarations_; - - std::vector type_declarations_; - std::vector select_types_; - std::vector enumeration_types_; - std::vector entities_; - - class declaration_by_name_cmp { - public: - bool operator()(const declaration* decl, const std::string& name) { - return decl->name_uc() < name; - } - }; - - class declaration_by_index_sort { - public: - bool operator()(const declaration* a, const declaration* b) { - return a->index_in_schema() < b->index_in_schema(); - } - }; - - instance_factory* factory_; - - std::string& temp_string_() const { - static my_thread_local std::string s; - return s; - } - - public: - - schema_definition(const std::string& name, const std::vector& declarations, instance_factory* factory); - - ~schema_definition(); - - const declaration* declaration_by_name(const std::string& name) const { - const std::string* name_ptr = &name; - if (std::any_of(name.begin(), name.end(), [](char c) { return std::islower(c); })) { - temp_string_() = name; - boost::to_upper(temp_string_()); - name_ptr = &temp_string_(); - } - std::vector::const_iterator it = std::lower_bound(declarations_.begin(), declarations_.end(), *name_ptr, declaration_by_name_cmp()); - if (it == declarations_.end() || (**it).name_uc() != *name_ptr) { - throw IfcParse::IfcException("Entity with name '" + name + "' not found in schema '" + name_ + "'"); - } else { - return *it; - } - } - - const declaration* declaration_by_name(int name) const { - return declarations_[name]; - } - - const std::vector& declarations() const { return declarations_; } - const std::vector& type_declarations() const { return type_declarations_; } - const std::vector& select_types() const { return select_types_; } - const std::vector& enumeration_types() const { return enumeration_types_; } - const std::vector& entities() const { return entities_; } - - const std::string& name() const { return name_; } - - IfcUtil::IfcBaseClass* instantiate(IfcEntityInstanceData* data) const; - }; - - IFC_PARSE_API const schema_definition* schema_by_name(const std::string&); - - IFC_PARSE_API std::vector schema_names(); - - IFC_PARSE_API void register_schema(schema_definition*); - - IFC_PARSE_API void clear_schemas(); -} + protected: + data_type declared_type_; + + public: + simple_type(data_type declared_type) + : declared_type_(declared_type) {} + + data_type declared_type() const { return declared_type_; } + + virtual const simple_type* as_simple_type() const { return this; } +}; + +class IFC_PARSE_API aggregation_type : public parameter_type { + public: + typedef enum { + array_type, + bag_type, + list_type, + set_type + } aggregate_type; + + protected: + aggregate_type type_of_aggregation_; + int bound1_, bound2_; + parameter_type* type_of_element_; + + public: + aggregation_type(aggregate_type type_of_aggregation, int bound1, int bound2, parameter_type* type_of_element) + : type_of_aggregation_(type_of_aggregation), + bound1_(bound1), + bound2_(bound2), + type_of_element_(type_of_element) {} + + virtual ~aggregation_type() { delete type_of_element_; } + + aggregate_type type_of_aggregation() const { return type_of_aggregation_; } + int bound1() const { return bound1_; } + int bound2() const { return bound2_; } + parameter_type* type_of_element() const { return type_of_element_; } + + virtual const aggregation_type* as_aggregation_type() const { return this; } +}; + +class IFC_PARSE_API declaration { + friend class schema_definition; + + protected: + std::string name_, name_upper_; + int index_in_schema_; + mutable const schema_definition* schema_; + + std::string& temp_string_() const { + static my_thread_local std::string s; + return s; + } + + public: + declaration(const std::string& name, int index_in_schema) + : name_(name), + name_upper_(boost::to_upper_copy(name)), + index_in_schema_(index_in_schema), + schema_(0) {} + + virtual ~declaration() {} + + const std::string& name() const { return name_; } + const std::string& name_uc() const { return name_upper_; } + + virtual const type_declaration* as_type_declaration() const { return static_cast(0); } + virtual const select_type* as_select_type() const { return static_cast(0); } + virtual const enumeration_type* as_enumeration_type() const { return static_cast(0); } + virtual const entity* as_entity() const { return static_cast(0); } + + bool is(const std::string& name) const; + bool is(const IfcParse::declaration& decl) const; + + int index_in_schema() const { return index_in_schema_; } + + int type() const { return index_in_schema_; } + + const schema_definition* schema() const { return schema_; } +}; + +class IFC_PARSE_API type_declaration : public declaration { + protected: + const parameter_type* declared_type_; + + public: + type_declaration(const std::string& name, int index_in_schema, const parameter_type* declared_type) + : declaration(name, index_in_schema), + declared_type_(declared_type) {} + + virtual ~type_declaration() { delete declared_type_; } + + const parameter_type* declared_type() const { return declared_type_; } + + virtual const type_declaration* as_type_declaration() const { return this; } +}; + +class IFC_PARSE_API select_type : public declaration { + protected: + std::vector select_list_; + + public: + select_type(const std::string& name, int index_in_schema, const std::vector& select_list) + : declaration(name, index_in_schema), + select_list_(select_list) {} + + const std::vector& select_list() const { return select_list_; } + + virtual const select_type* as_select_type() const { return this; } +}; + +class IFC_PARSE_API enumeration_type : public declaration { + protected: + std::vector enumeration_items_; + + public: + enumeration_type(const std::string& name, int index_in_schema, const std::vector& enumeration_items) + : declaration(name, index_in_schema), + enumeration_items_(enumeration_items) {} + + const std::vector& enumeration_items() const { return enumeration_items_; } + + const char* lookup_enum_value(size_t i) const { + if (i >= enumeration_items_.size()) { + throw IfcParse::IfcException("Unable to find keyword in schema for index " + std::to_string(i)); + } + return enumeration_items_[i].c_str(); + } + + size_t lookup_enum_offset(const std::string& s) const { + size_t i = 0; + for (auto it = enumeration_items_.begin(); it != enumeration_items_.end(); ++it, ++i) { + if (s == *it) { + return i; + } + } + throw IfcParse::IfcException("Unable to find keyword in schema: " + s); + } + + virtual const enumeration_type* as_enumeration_type() const { return this; } +}; + +class IFC_PARSE_API attribute { + protected: + std::string name_; + const parameter_type* type_of_attribute_; + bool optional_; + + public: + attribute(const std::string& name, parameter_type* type_of_attribute, bool optional) + : name_(name), + type_of_attribute_(type_of_attribute), + optional_(optional) {} + + ~attribute() { delete type_of_attribute_; } + + const std::string& name() const { return name_; } + const parameter_type* type_of_attribute() const { return type_of_attribute_; } + bool optional() const { return optional_; } +}; + +class IFC_PARSE_API inverse_attribute { + public: + typedef enum { + bag_type, + set_type, + unspecified_type + } aggregate_type; + + protected: + std::string name_; + aggregate_type type_of_aggregation_; + int bound1_, bound2_; + const entity* entity_reference_; + const attribute* attribute_reference_; + + public: + inverse_attribute(const std::string& name, aggregate_type type_of_aggregation, int bound1, int bound2, const entity* entity_reference, const attribute* attribute_reference) + : name_(name), + type_of_aggregation_(type_of_aggregation), + bound1_(bound1), + bound2_(bound2), + entity_reference_(entity_reference), + attribute_reference_(attribute_reference) {} + + const std::string& name() const { return name_; } + aggregate_type type_of_aggregation() const { return type_of_aggregation_; } + int bound1() const { return bound1_; } + int bound2() const { return bound2_; } + const entity* entity_reference() const { return entity_reference_; } + const attribute* attribute_reference() const { return attribute_reference_; } +}; + +class IFC_PARSE_API entity : public declaration { + protected: + bool is_abstract_; + const entity* supertype_; /* NB: IFC explicitly allows only single inheritance */ + std::vector subtypes_; + + std::vector attributes_; + std::vector derived_; + + std::vector inverse_attributes_; + + class attribute_by_name_cmp { + private: + std::string name_; + + public: + attribute_by_name_cmp(const std::string name) + : name_(name) {} + bool operator()(const attribute* attr) { + return attr->name() == name_; + } + }; + + const attribute* attribute_by_index_(size_t& index) const { + const attribute* attr = 0; + if (supertype_) { + attr = supertype_->attribute_by_index_(index); + } + if (attr == 0) { + if (index < attributes_.size()) { + attr = attributes_[index]; + } + index -= attributes_.size(); + } + return attr; + } + + public: + entity(const std::string& name, bool is_abstract, int index_in_schema, entity* supertype) + : declaration(name, index_in_schema), + is_abstract_(is_abstract), + supertype_(supertype) {} + + virtual ~entity(); + + bool is_abstract() const { return is_abstract_; } + + void set_subtypes(const std::vector& subtypes) { + subtypes_ = subtypes; + } + + void set_attributes(const std::vector& attributes, const std::vector& derived) { + attributes_ = attributes; + derived_ = derived; + } + + void set_inverse_attributes(const std::vector& inverse_attributes) { + inverse_attributes_ = inverse_attributes; + } + + const std::vector& subtypes() const { return subtypes_; } + const std::vector& attributes() const { return attributes_; } + const std::vector& derived() const { return derived_; } + + const std::vector all_attributes() const { + std::vector attrs; + attrs.reserve(derived_.size()); + if (supertype_) { + const std::vector supertype_attrs = supertype_->all_attributes(); + std::copy(supertype_attrs.begin(), supertype_attrs.end(), std::back_inserter(attrs)); + } + std::copy(attributes_.begin(), attributes_.end(), std::back_inserter(attrs)); + return attrs; + } + + const std::vector all_inverse_attributes() const { + std::vector attrs; + if (supertype_) { + const std::vector supertype_inv_attrs = supertype_->all_inverse_attributes(); + std::copy(supertype_inv_attrs.begin(), supertype_inv_attrs.end(), std::back_inserter(attrs)); + } + std::copy(inverse_attributes_.begin(), inverse_attributes_.end(), std::back_inserter(attrs)); + return attrs; + } + + const attribute* attribute_by_index(size_t index) const { + const attribute* attr = attribute_by_index_(index); + if (attr == 0) { + throw IfcParse::IfcException("Attribute index out of bounds"); + } + return attr; + } + + size_t attribute_count() const { + size_t super_count = 0; + if (supertype_) { + super_count = supertype_->attribute_count(); + } + return super_count + attributes_.size(); + } + + ptrdiff_t attribute_index(const attribute* attr) const { + const entity* current = this; + ptrdiff_t index = -1; + do { + if (index > -1) { + index += current->attributes().size(); + } else { + std::vector::const_iterator it; + it = std::find(current->attributes().begin(), current->attributes().end(), attr); + if (it != current->attributes().end()) { + index = std::distance(current->attributes().begin(), it); + } + } + } while ((current = current->supertype_) != 0); + return index; + } + + ptrdiff_t attribute_index(const std::string& attr_name) const { + const entity* current = this; + ptrdiff_t index = -1; + attribute_by_name_cmp cmp(attr_name); + do { + if (index > -1) { + index += current->attributes().size(); + } else { + std::vector::const_iterator it; + it = std::find_if(current->attributes().begin(), current->attributes().end(), cmp); + if (it != current->attributes().end()) { + index = std::distance(current->attributes().begin(), it); + } + } + } while ((current = current->supertype_) != 0); + return index; + } + + const entity* supertype() const { return supertype_; } + + virtual const entity* as_entity() const { return this; } +}; + +class IFC_PARSE_API instance_factory { + public: + virtual ~instance_factory() {} + + virtual IfcUtil::IfcBaseClass* operator()(IfcEntityInstanceData* data) const = 0; +}; + +class IFC_PARSE_API schema_definition { + private: + std::string name_; + + std::vector declarations_; + + std::vector type_declarations_; + std::vector select_types_; + std::vector enumeration_types_; + std::vector entities_; + + class declaration_by_name_cmp { + public: + bool operator()(const declaration* decl, const std::string& name) { + return decl->name_uc() < name; + } + }; + + class declaration_by_index_sort { + public: + bool operator()(const declaration* a, const declaration* b) { + return a->index_in_schema() < b->index_in_schema(); + } + }; + + instance_factory* factory_; + + std::string& temp_string_() const { + static my_thread_local std::string s; + return s; + } + + public: + schema_definition(const std::string& name, const std::vector& declarations, instance_factory* factory); + + ~schema_definition(); + + const declaration* declaration_by_name(const std::string& name) const { + const std::string* name_ptr = &name; + if (std::any_of(name.begin(), name.end(), [](char c) { return std::islower(c); })) { + temp_string_() = name; + boost::to_upper(temp_string_()); + name_ptr = &temp_string_(); + } + std::vector::const_iterator it = std::lower_bound(declarations_.begin(), declarations_.end(), *name_ptr, declaration_by_name_cmp()); + if (it == declarations_.end() || (**it).name_uc() != *name_ptr) { + throw IfcParse::IfcException("Entity with name '" + name + "' not found in schema '" + name_ + "'"); + } else { + return *it; + } + } + + const declaration* declaration_by_name(int name) const { + return declarations_[name]; + } + + const std::vector& declarations() const { return declarations_; } + const std::vector& type_declarations() const { return type_declarations_; } + const std::vector& select_types() const { return select_types_; } + const std::vector& enumeration_types() const { return enumeration_types_; } + const std::vector& entities() const { return entities_; } + + const std::string& name() const { return name_; } + + IfcUtil::IfcBaseClass* instantiate(IfcEntityInstanceData* data) const; +}; + +IFC_PARSE_API const schema_definition* schema_by_name(const std::string&); + +IFC_PARSE_API std::vector schema_names(); + +IFC_PARSE_API void register_schema(schema_definition*); + +IFC_PARSE_API void clear_schemas(); +} // namespace IfcParse #endif diff --git a/src/ifcparse/IfcSpfHeader.cpp b/src/ifcparse/IfcSpfHeader.cpp index 4f17ecaeee..78749101c6 100644 --- a/src/ifcparse/IfcSpfHeader.cpp +++ b/src/ifcparse/IfcSpfHeader.cpp @@ -17,17 +17,17 @@ * * ********************************************************************************/ -#include "../ifcparse/IfcFile.h" - #include "IfcSpfHeader.h" -static const char * const ISO_10303_21 = "ISO-10303-21"; -static const char * const HEADER = "HEADER"; -static const char * const FILE_DESCRIPTION = "FILE_DESCRIPTION"; -static const char * const FILE_NAME = "FILE_NAME"; -static const char * const FILE_SCHEMA = "FILE_SCHEMA"; -static const char * const ENDSEC = "ENDSEC"; -static const char * const DATA = "DATA"; +#include "IfcFile.h" + +static const char* const ISO_10303_21 = "ISO-10303-21"; +static const char* const HEADER = "HEADER"; +static const char* const FILE_DESCRIPTION = "FILE_DESCRIPTION"; +static const char* const FILE_NAME = "FILE_NAME"; +static const char* const FILE_SCHEMA = "FILE_SCHEMA"; +static const char* const ENDSEC = "ENDSEC"; +static const char* const DATA = "DATA"; // The following header entities are not normally encountered in IFC files and are not parsed. // static const char * const FILE_POPULATION = "FILE_POPULATION"; // static const char * const SECTION_LANGUAGE = "SECTION_LANGUAGE"; @@ -35,143 +35,148 @@ static const char * const DATA = "DATA"; using namespace IfcParse; -HeaderEntity::HeaderEntity(const char * const datatype, size_t size, IfcFile* file) - : IfcEntityInstanceData(file, size) - , _datatype(datatype) - , size_(size) -{ - if (file) { - offset_in_file_ = file->stream->Tell(); - load(); - } +HeaderEntity::HeaderEntity(const char* const datatype, size_t size, IfcFile* file) + : IfcEntityInstanceData(file, size), + _datatype(datatype), + size_(size) { + if (file) { + offset_in_file_ = file->stream->Tell(); + load(); + } } -HeaderEntity::~HeaderEntity() -{ - clearArguments(); +HeaderEntity::~HeaderEntity() { + clearArguments(); } void IfcSpfHeader::readSemicolon() { - if (!TokenFunc::isOperator(file_->tokens->Next(), ';')) { - throw IfcException(std::string("Expected ;")); - } + if (!TokenFunc::isOperator(file_->tokens->Next(), ';')) { + throw IfcException(std::string("Expected ;")); + } } void IfcSpfHeader::readParen() { - if (!TokenFunc::isOperator(file_->tokens->Next(), '(')) { - throw IfcException(std::string("Expected (")); - } + if (!TokenFunc::isOperator(file_->tokens->Next(), '(')) { + throw IfcException(std::string("Expected (")); + } } void IfcSpfHeader::readTerminal(const std::string& term, Trail trail) { - if (TokenFunc::asStringRef(file_->tokens->Next()) != term) { - throw IfcException(std::string("Expected " + term)); - } - if (trail == TRAILING_SEMICOLON) { - readSemicolon(); - } else if (trail == TRAILING_PAREN) { - readParen(); - } + if (TokenFunc::asStringRef(file_->tokens->Next()) != term) { + throw IfcException(std::string("Expected " + term)); + } + if (trail == TRAILING_SEMICOLON) { + readSemicolon(); + } else if (trail == TRAILING_PAREN) { + readParen(); + } } void IfcSpfHeader::read() { - readTerminal(ISO_10303_21, TRAILING_SEMICOLON); - readTerminal(HEADER, TRAILING_SEMICOLON); + readTerminal(ISO_10303_21, TRAILING_SEMICOLON); + readTerminal(HEADER, TRAILING_SEMICOLON); - // | The header section of every exchange structure shall contain one - // | instance of each of the following entities: file_description, file_name, - // | and file_schema, and they shall appear in that order. Instances of - // | file_population, section_language and section_context may appear after - // | file_schema. If instances of user-defined header section entities are - // | present, they shall appear after the header section entity instances - // | defined in this section. - // - // ISO 10303-21 Second edition 2002-01-15 p. 16 + // | The header section of every exchange structure shall contain one + // | instance of each of the following entities: file_description, file_name, + // | and file_schema, and they shall appear in that order. Instances of + // | file_population, section_language and section_context may appear after + // | file_schema. If instances of user-defined header section entities are + // | present, they shall appear after the header section entity instances + // | defined in this section. + // + // ISO 10303-21 Second edition 2002-01-15 p. 16 - readTerminal(FILE_DESCRIPTION, NONE); - delete _file_description; - _file_description = new FileDescription(file_); - // readSemicolon(); + readTerminal(FILE_DESCRIPTION, NONE); + delete _file_description; + _file_description = new FileDescription(file_); + // readSemicolon(); - readTerminal(FILE_NAME, NONE); - delete _file_name; - _file_name = new FileName(file_); - // readSemicolon(); + readTerminal(FILE_NAME, NONE); + delete _file_name; + _file_name = new FileName(file_); + // readSemicolon(); - readTerminal(FILE_SCHEMA, NONE); - delete _file_schema; - _file_schema = new FileSchema(file_); - // readSemicolon(); + readTerminal(FILE_SCHEMA, NONE); + delete _file_schema; + _file_schema = new FileSchema(file_); + // readSemicolon(); } bool IfcSpfHeader::tryRead() { - try { - read(); - return true; - } catch (const std::exception& e) { - Logger::Error(e); - return false; - } + try { + read(); + return true; + } catch (const std::exception& e) { + Logger::Error(e); + return false; + } } void IfcSpfHeader::write(std::ostream& os) const { - os << ISO_10303_21 << ";" << "\n"; - os << HEADER << ";" << "\n"; - os << file_description().toString(true) << ";" << "\n"; - os << file_name().toString(true) << ";" << "\n"; - os << file_schema().toString(true) << ";" << "\n"; - os << ENDSEC << ";" << "\n"; - os << DATA << ";" << "\n"; + os << ISO_10303_21 << ";" + << "\n"; + os << HEADER << ";" + << "\n"; + os << file_description().toString(true) << ";" + << "\n"; + os << file_name().toString(true) << ";" + << "\n"; + os << file_schema().toString(true) << ";" + << "\n"; + os << ENDSEC << ";" + << "\n"; + os << DATA << ";" + << "\n"; } const FileDescription& IfcSpfHeader::file_description() const { - if (_file_description) { - return *_file_description; - } else { - throw IfcException("File description not set"); - } + if (_file_description) { + return *_file_description; + } else { + throw IfcException("File description not set"); + } } const FileName& IfcSpfHeader::file_name() const { - if (_file_name) { - return *_file_name; - } else { - throw IfcException("File name not set"); - } + if (_file_name) { + return *_file_name; + } else { + throw IfcException("File name not set"); + } } const FileSchema& IfcSpfHeader::file_schema() const { - if (_file_schema) { - return *_file_schema; - } else { - throw IfcException("File schema not set"); - } + if (_file_schema) { + return *_file_schema; + } else { + throw IfcException("File schema not set"); + } } FileDescription& IfcSpfHeader::file_description() { - if (_file_description) { - return *_file_description; - } else { - throw IfcException("File description not set"); - } + if (_file_description) { + return *_file_description; + } else { + throw IfcException("File description not set"); + } } FileName& IfcSpfHeader::file_name() { - if (_file_name) { - return *_file_name; - } else { - throw IfcException("File name not set"); - } + if (_file_name) { + return *_file_name; + } else { + throw IfcException("File name not set"); + } } FileSchema& IfcSpfHeader::file_schema() { - if (_file_schema) { - return *_file_schema; - } else { - throw IfcException("File schema not set"); - } + if (_file_schema) { + return *_file_schema; + } else { + throw IfcException("File schema not set"); + } } 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) {} \ No newline at end of file +FileSchema::FileSchema(IfcFile* file) : HeaderEntity(FILE_SCHEMA, 1, file) {} diff --git a/src/ifcparse/IfcSpfHeader.h b/src/ifcparse/IfcSpfHeader.h index c979699fbf..8c26c8d2b2 100644 --- a/src/ifcparse/IfcSpfHeader.h +++ b/src/ifcparse/IfcSpfHeader.h @@ -16,140 +16,141 @@ * along with this program. If not, see . * * * ********************************************************************************/ - + #ifndef IFCSPFHEADER_H #define IFCSPFHEADER_H #include "ifc_parse_api.h" - -#include "../ifcparse/IfcSpfStream.h" -#include "../ifcparse/IfcWrite.h" +#include "IfcSpfStream.h" +#include "IfcWrite.h" namespace IfcParse { class IFC_PARSE_API HeaderEntity : public IfcEntityInstanceData { -private: - const char * const _datatype; - size_t size_; + 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, size_t size, IfcParse::IfcFile* file); - virtual ~HeaderEntity(); + HeaderEntity(const HeaderEntity&); //N/A + HeaderEntity& operator=(const HeaderEntity&); //N/A + protected: + HeaderEntity(const char* const datatype, size_t size, IfcParse::IfcFile* file); + virtual ~HeaderEntity(); - void setValue(unsigned int i, const std::string& s) { - IfcWrite::IfcWriteArgument* argument = new IfcWrite::IfcWriteArgument; - argument->set(s); - setArgument(i, argument); - } + void setValue(unsigned int i, const std::string& s) { + IfcWrite::IfcWriteArgument* argument = new IfcWrite::IfcWriteArgument; + argument->set(s); + setArgument(i, argument); + } - void setValue(unsigned int i, const std::vector& s) { - IfcWrite::IfcWriteArgument* argument = new IfcWrite::IfcWriteArgument; - argument->set(s); - setArgument(i, argument); - } + void setValue(unsigned int i, const std::vector& s) { + IfcWrite::IfcWriteArgument* argument = new IfcWrite::IfcWriteArgument; + argument->set(s); + setArgument(i, argument); + } -public: - virtual size_t getArgumentCount() const { - return size_; - } + public: + virtual size_t getArgumentCount() const { + return size_; + } - std::string toString(bool upper=false) const { - std::stringstream ss; - ss << _datatype << IfcEntityInstanceData::toString(upper); - return ss.str(); - } + std::string toString(bool upper = false) const { + std::stringstream ss; + ss << _datatype << IfcEntityInstanceData::toString(upper); + return ss.str(); + } }; class IFC_PARSE_API FileDescription : public HeaderEntity { -public: - explicit FileDescription(IfcFile* = 0); + public: + explicit FileDescription(IfcFile* = 0); - std::vector description() const { return *getArgument(0); } - std::string implementation_level() const { return *getArgument(1); } + std::vector description() const { return *getArgument(0); } + std::string implementation_level() const { return *getArgument(1); } - void description(const std::vector& value) { setValue(0, value); } - void implementation_level(const std::string& value) { setValue(1, value); } + void description(const std::vector& value) { setValue(0, value); } + void implementation_level(const std::string& value) { setValue(1, value); } }; -class IFC_PARSE_API FileName : public HeaderEntity { -public: - explicit FileName(IfcFile* = 0); +class IFC_PARSE_API FileName : public HeaderEntity { + public: + explicit FileName(IfcFile* = 0); - std::string name() const { return *getArgument(0); } - std::string time_stamp() const { return *getArgument(1); } - std::vector author() const { return *getArgument(2); } - std::vector organization() const { return *getArgument(3); } - std::string preprocessor_version() const { return *getArgument(4); } - std::string originating_system() const { return *getArgument(5); } - std::string authorization() const { return *getArgument(6); } + std::string name() const { return *getArgument(0); } + std::string time_stamp() const { return *getArgument(1); } + std::vector author() const { return *getArgument(2); } + std::vector organization() const { return *getArgument(3); } + std::string preprocessor_version() const { return *getArgument(4); } + std::string originating_system() const { return *getArgument(5); } + std::string authorization() const { return *getArgument(6); } - void name(const std::string& value) { setValue(0, value); } - void time_stamp(const std::string& value) { setValue(1, value); } - void author(const std::vector& value) { setValue(2, value); } - void organization(const std::vector& value) { setValue(3, value); } - void preprocessor_version(const std::string& value) { setValue(4, value); } - void originating_system(const std::string& value) { setValue(5, value); } - void authorization(const std::string& value) { setValue(6, value); } + void name(const std::string& value) { setValue(0, value); } + void time_stamp(const std::string& value) { setValue(1, value); } + void author(const std::vector& value) { setValue(2, value); } + void organization(const std::vector& value) { setValue(3, value); } + void preprocessor_version(const std::string& value) { setValue(4, value); } + void originating_system(const std::string& value) { setValue(5, value); } + void authorization(const std::string& value) { setValue(6, value); } }; -class IFC_PARSE_API FileSchema : public HeaderEntity { -public: - explicit FileSchema(IfcFile* = 0); +class IFC_PARSE_API FileSchema : public HeaderEntity { + public: + explicit FileSchema(IfcFile* = 0); - std::vector schema_identifiers() const { return *getArgument(0); } + std::vector schema_identifiers() const { return *getArgument(0); } - void schema_identifiers(const std::vector& value) { setValue(0, value); } + void schema_identifiers(const std::vector& value) { setValue(0, value); } }; class IFC_PARSE_API IfcSpfHeader { -private: - IfcFile* file_; - FileDescription* _file_description; - FileName* _file_name; - FileSchema* _file_schema; - void readParen(); - void readSemicolon(); - enum Trail { - TRAILING_SEMICOLON, - TRAILING_PAREN, - NONE - }; - void readTerminal(const std::string& term, Trail trail); -public: - explicit IfcSpfHeader(IfcParse::IfcFile* file = 0) - : file_(file), _file_description(0), _file_name(0), _file_schema(0) - { - _file_description = new FileDescription(file_); - _file_name = new FileName(file_); - _file_schema = new FileSchema(file_); - } + private: + IfcFile* file_; + FileDescription* _file_description; + FileName* _file_name; + FileSchema* _file_schema; + void readParen(); + void readSemicolon(); + enum Trail { + TRAILING_SEMICOLON, + TRAILING_PAREN, + NONE + }; + void readTerminal(const std::string& term, Trail trail); - ~IfcSpfHeader() - { - delete _file_schema; - delete _file_name; - delete _file_description; - } + public: + explicit IfcSpfHeader(IfcParse::IfcFile* file = 0) + : file_(file), + _file_description(0), + _file_name(0), + _file_schema(0) { + _file_description = new FileDescription(file_); + _file_name = new FileName(file_); + _file_schema = new FileSchema(file_); + } - IfcParse::IfcFile* file() { return file_; } - void file(IfcParse::IfcFile * file) { file_ = file; } + ~IfcSpfHeader() { + delete _file_schema; + delete _file_name; + delete _file_description; + } - void read(); - bool tryRead(); - - void write(std::ostream& os) const; + IfcParse::IfcFile* file() { return file_; } + void file(IfcParse::IfcFile* file) { file_ = file; } - const FileDescription& file_description() const; - const FileName& file_name() const; - const FileSchema& file_schema() const; + void read(); + bool tryRead(); - FileDescription& file_description(); - FileName& file_name(); - FileSchema& file_schema(); + void write(std::ostream& os) const; + + const FileDescription& file_description() const; + const FileName& file_name() const; + const FileSchema& file_schema() const; + + FileDescription& file_description(); + FileName& file_name(); + FileSchema& file_schema(); }; -} +} // namespace IfcParse #endif diff --git a/src/ifcparse/IfcSpfStream.h b/src/ifcparse/IfcSpfStream.h index 2172842a9f..d049cfc305 100644 --- a/src/ifcparse/IfcSpfStream.h +++ b/src/ifcparse/IfcSpfStream.h @@ -16,17 +16,19 @@ * along with this program. If not, see . * * * ********************************************************************************/ - + /********************************************************************************* * * * Reads a file and provides functions to access its * * contents randomly and character by character * * * ********************************************************************************/ - + #ifndef IFCSPFSTREAM_H #define IFCSPFSTREAM_H +#include "ifc_parse_api.h" + #include #include @@ -34,49 +36,48 @@ #include #endif -#include "ifc_parse_api.h" - namespace IfcParse { - /// The IfcSpfStream class represents a ISO 10303-21 IFC-SPF file in memory. - /// The file is interpreted as a sequence of tokens which are lazily - /// interpreted only when requested. - class IFC_PARSE_API IfcSpfStream { - private: +/// The IfcSpfStream class represents a ISO 10303-21 IFC-SPF file in memory. +/// The file is interpreted as a sequence of tokens which are lazily +/// interpreted only when requested. +class IFC_PARSE_API IfcSpfStream { + private: #ifdef USE_MMAP - boost::iostreams::mapped_file_source mfs; + boost::iostreams::mapped_file_source mfs; #endif - FILE* stream; - const char* buffer; - unsigned int ptr; - unsigned int len; - public: - bool valid; - bool eof; - unsigned int size; + FILE* stream; + const char* buffer; + unsigned int ptr; + unsigned int len; + + public: + bool valid; + bool eof; + unsigned int size; #ifdef USE_MMAP - IfcSpfStream(const std::string& fn, bool mmap=false); + IfcSpfStream(const std::string& fn, bool mmap = false); #else - IfcSpfStream(const std::string& fn); + IfcSpfStream(const std::string& fn); #endif - IfcSpfStream(std::istream& f, int len); - IfcSpfStream(void* data, int len); - ~IfcSpfStream(); - /// Returns the character at the cursor - char Peek(); - /// Returns the character at specified offset - char Read(unsigned int offset); - /// Increment the file cursor and reads new page if necessary - void Inc(); - void Close(); - /// Moves the file cursor to an arbitrary offset in the file - void Seek(unsigned int offset); - /// Returns the cursor position - unsigned int Tell(); + IfcSpfStream(std::istream& f, int len); + IfcSpfStream(void* data, int len); + ~IfcSpfStream(); + /// Returns the character at the cursor + char Peek(); + /// Returns the character at specified offset + char Read(unsigned int offset); + /// Increment the file cursor and reads new page if necessary + void Inc(); + void Close(); + /// Moves the file cursor to an arbitrary offset in the file + void Seek(unsigned int offset); + /// Returns the cursor position + unsigned int Tell(); - bool is_eof_at(unsigned int); - void increment_at(unsigned int&); - char peek_at(unsigned int); - }; -} + bool is_eof_at(unsigned int); + void increment_at(unsigned int&); + char peek_at(unsigned int); +}; +} // namespace IfcParse #endif diff --git a/src/ifcparse/IfcUtil.cpp b/src/ifcparse/IfcUtil.cpp index 3cc0915284..64e9582ae1 100644 --- a/src/ifcparse/IfcUtil.cpp +++ b/src/ifcparse/IfcUtil.cpp @@ -34,7 +34,7 @@ #define NOGDI NOGDI #endif #ifndef NOSERVICE -#define NOSERVICE NOSERVICE +#define NOSERVICE NOSERVICE #endif #ifndef NOKERNEL #define NOKERNEL NOKERNEL @@ -51,75 +51,75 @@ #include #endif -#include "../ifcparse/IfcBaseClass.h" -#include "../ifcparse/Argument.h" -#include "../ifcparse/utils.h" -#include "../ifcparse/IfcException.h" -#include "../ifcparse/aggregate_of_instance.h" +#include "aggregate_of_instance.h" +#include "Argument.h" +#include "IfcBaseClass.h" +#include "IfcException.h" +#include "utils.h" +#include #include #include - #include -#include - void aggregate_of_instance::push(IfcUtil::IfcBaseClass* l) { - if (l) { - ls.push_back(l); - } + if (l) { + ls.push_back(l); + } } void aggregate_of_instance::push(const aggregate_of_instance::ptr& l) { - if (l) { - for( it i = l->begin(); i != l->end(); ++i ) { - if ( *i ) ls.push_back(*i); - } - } + if (l) { + for (it i = l->begin(); i != l->end(); ++i) { + if (*i) { + ls.push_back(*i); + } + } + } } -unsigned int aggregate_of_instance::size() const { return (unsigned int) ls.size(); } +unsigned int aggregate_of_instance::size() const { return (unsigned int)ls.size(); } void aggregate_of_instance::reserve(unsigned capacity) { ls.reserve((size_t)capacity); } aggregate_of_instance::it aggregate_of_instance::begin() { return ls.begin(); } aggregate_of_instance::it aggregate_of_instance::end() { return ls.end(); } -IfcUtil::IfcBaseClass* aggregate_of_instance::operator[] (int i) { - return ls[i]; +IfcUtil::IfcBaseClass* aggregate_of_instance::operator[](int i) { + return ls[i]; } bool aggregate_of_instance::contains(IfcUtil::IfcBaseClass* instance) const { - return std::find(ls.begin(), ls.end(), instance) != ls.end(); + return std::find(ls.begin(), ls.end(), instance) != ls.end(); } void aggregate_of_instance::remove(IfcUtil::IfcBaseClass* instance) { - std::vector::iterator it; - while ((it = std::find(ls.begin(), ls.end(), instance)) != ls.end()) { - ls.erase(it); - } + std::vector::iterator it; + while ((it = std::find(ls.begin(), ls.end(), instance)) != ls.end()) { + ls.erase(it); + } } aggregate_of_instance::ptr aggregate_of_instance::filtered(const std::set& entities) { - aggregate_of_instance::ptr return_value(new aggregate_of_instance); - for (it it = begin(); it != end(); ++it) { - bool contained = false; - for (std::set::const_iterator jt = entities.begin(); jt != entities.end(); ++jt) { - if ((*it)->declaration().is(**jt)) { - contained = true; - break; - } - } - if (!contained) { - return_value->push(*it); - } - } - return return_value; + aggregate_of_instance::ptr return_value(new aggregate_of_instance); + for (it it = begin(); it != end(); ++it) { + bool contained = false; + for (std::set::const_iterator jt = entities.begin(); jt != entities.end(); ++jt) { + if ((*it)->declaration().is(**jt)) { + contained = true; + break; + } + } + if (!contained) { + return_value->push(*it); + } + } + return return_value; } aggregate_of_instance::ptr aggregate_of_instance::unique() { - std::set encountered; - aggregate_of_instance::ptr return_value(new aggregate_of_instance); - for (it it = begin(); it != end(); ++it) { - if (encountered.find(*it) == encountered.end()) { - return_value->push(*it); - encountered.insert(*it); - } - } - return return_value; + std::set encountered; + aggregate_of_instance::ptr return_value(new aggregate_of_instance); + for (it it = begin(); it != end(); ++it) { + if (encountered.find(*it) == encountered.end()) { + return_value->push(*it); + encountered.insert(*it); + } + } + return return_value; } //Note: some of these methods are overloaded in derived classes @@ -133,70 +133,67 @@ Argument::operator IfcUtil::IfcBaseClass*() const { throw IfcParse::IfcException Argument::operator std::vector() const { throw IfcParse::IfcException("Argument is not a list of floats"); } Argument::operator std::vector() const { throw IfcParse::IfcException("Argument is not a list of ints"); } Argument::operator std::vector() const { throw IfcParse::IfcException("Argument is not a list of strings"); } -Argument::operator std::vector >() const { throw IfcParse::IfcException("Argument is not a list of binaries"); } +Argument::operator std::vector>() const { throw IfcParse::IfcException("Argument is not a list of binaries"); } Argument::operator aggregate_of_instance::ptr() const { throw IfcParse::IfcException("Argument is not a list of entity instances"); } -Argument::operator std::vector< std::vector >() const { throw IfcParse::IfcException("Argument is not a list of list of ints"); } -Argument::operator std::vector< std::vector >() const { throw IfcParse::IfcException("Argument is not a list of list of floats"); } +Argument::operator std::vector>() const { throw IfcParse::IfcException("Argument is not a list of list of ints"); } +Argument::operator std::vector>() const { throw IfcParse::IfcException("Argument is not a list of list of floats"); } Argument::operator aggregate_of_aggregate_of_instance::ptr() const { throw IfcParse::IfcException("Argument is not a list of list of entity instances"); } - static const char* const argument_type_string[] = { - "NULL", - "DERIVED", - "INT", - "BOOL", - "LOGICAL", - "DOUBLE", - "STRING", - "BINARY", - "ENUMERATION", - "ENTITY INSTANCE", + "NULL", + "DERIVED", + "INT", + "BOOL", + "LOGICAL", + "DOUBLE", + "STRING", + "BINARY", + "ENUMERATION", + "ENTITY INSTANCE", - "EMPTY AGGREGATE", - "AGGREGATE OF INT", - "AGGREGATE OF DOUBLE", - "AGGREGATE OF STRING", - "AGGREGATE OF BINARY", - "AGGREGATE OF ENTITY INSTANCE", + "EMPTY AGGREGATE", + "AGGREGATE OF INT", + "AGGREGATE OF DOUBLE", + "AGGREGATE OF STRING", + "AGGREGATE OF BINARY", + "AGGREGATE OF ENTITY INSTANCE", - "AGGREGATE OF EMPTY AGGREGATE", - "AGGREGATE OF AGGREGATE OF INT", - "AGGREGATE OF AGGREGATE OF DOUBLE", - "AGGREGATE OF AGGREGATE OF ENTITY INSTANCE", + "AGGREGATE OF EMPTY AGGREGATE", + "AGGREGATE OF AGGREGATE OF INT", + "AGGREGATE OF AGGREGATE OF DOUBLE", + "AGGREGATE OF AGGREGATE OF ENTITY INSTANCE", - "UNKNOWN" -}; + "UNKNOWN"}; const char* IfcUtil::ArgumentTypeToString(ArgumentType argument_type) { - return argument_type_string[static_cast(argument_type)]; + return argument_type_string[static_cast(argument_type)]; } bool IfcUtil::valid_binary_string(const std::string& s) { - for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) { - if (*it != '0' && *it != '1') return false; - } - return true; + for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) { + if (*it != '0' && *it != '1') { + return false; + } + } + return true; } -void IfcUtil::sanitate_material_name(std::string &str) -{ +void IfcUtil::sanitate_material_name(std::string& str) { // Spaces in material names have been observed to cause problems with obj and dae importers. // Handle other potential problematic characters here too if observing problems. boost::replace_all(str, " ", "_"); } -void IfcUtil::escape_xml(std::string &str) -{ - boost::replace_all(str, "&", "&"); +void IfcUtil::escape_xml(std::string& str) { + boost::replace_all(str, "&", "&"); boost::replace_all(str, "\"", """); boost::replace_all(str, "'", "'"); boost::replace_all(str, "<", "<"); boost::replace_all(str, ">", ">"); } -void IfcUtil::unescape_xml(std::string &str) -{ - boost::replace_all(str, "&", "&"); +void IfcUtil::unescape_xml(std::string& str) { + boost::replace_all(str, "&", "&"); boost::replace_all(str, """, "\""); boost::replace_all(str, "'", "'"); boost::replace_all(str, "<", "<"); @@ -204,138 +201,138 @@ void IfcUtil::unescape_xml(std::string &str) } Argument* IfcUtil::IfcBaseEntity::get(const std::string& name) const { - return data().getArgument(declaration().attribute_index(name)); + return data().getArgument(declaration().attribute_index(name)); } aggregate_of_instance::ptr IfcUtil::IfcBaseEntity::get_inverse(const std::string& name) const { - const std::vector attrs = declaration().as_entity()->all_inverse_attributes(); - std::vector::const_iterator it = attrs.begin(); - for (; it != attrs.end(); ++it) { - if ((*it)->name() == name) { - return data().getInverse( - (*it)->entity_reference(), - (int) (*it)->entity_reference()->attribute_index((*it)->attribute_reference())); - } - } - throw IfcParse::IfcException(name + " not found on " + declaration().name()); + const std::vector attrs = declaration().as_entity()->all_inverse_attributes(); + std::vector::const_iterator it = attrs.begin(); + for (; it != attrs.end(); ++it) { + if ((*it)->name() == name) { + return data().getInverse( + (*it)->entity_reference(), + (int)(*it)->entity_reference()->attribute_index((*it)->attribute_reference())); + } + } + throw IfcParse::IfcException(name + " not found on " + declaration().name()); } void IfcUtil::IfcBaseClass::data(IfcEntityInstanceData* d) { - delete data_; - data_ = d; + delete data_; + data_ = d; } IfcUtil::ArgumentType IfcUtil::make_aggregate(IfcUtil::ArgumentType elem_type) { - if (elem_type == IfcUtil::Argument_INT) { - return IfcUtil::Argument_AGGREGATE_OF_INT; - } else if (elem_type == IfcUtil::Argument_DOUBLE) { - return IfcUtil::Argument_AGGREGATE_OF_DOUBLE; - } else if (elem_type == IfcUtil::Argument_STRING) { - return IfcUtil::Argument_AGGREGATE_OF_STRING; - } else if (elem_type == IfcUtil::Argument_BINARY) { - return IfcUtil::Argument_AGGREGATE_OF_BINARY; - } else if (elem_type == IfcUtil::Argument_ENTITY_INSTANCE) { - return IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE; - } else if (elem_type == IfcUtil::Argument_AGGREGATE_OF_INT) { - return IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT; - } else if (elem_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) { - return IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE; - } else if (elem_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) { - return IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE; - } else if (elem_type == IfcUtil::Argument_EMPTY_AGGREGATE) { - return IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE; - } else { - return IfcUtil::Argument_UNKNOWN; - } + if (elem_type == IfcUtil::Argument_INT) { + return IfcUtil::Argument_AGGREGATE_OF_INT; + } else if (elem_type == IfcUtil::Argument_DOUBLE) { + return IfcUtil::Argument_AGGREGATE_OF_DOUBLE; + } else if (elem_type == IfcUtil::Argument_STRING) { + return IfcUtil::Argument_AGGREGATE_OF_STRING; + } else if (elem_type == IfcUtil::Argument_BINARY) { + return IfcUtil::Argument_AGGREGATE_OF_BINARY; + } else if (elem_type == IfcUtil::Argument_ENTITY_INSTANCE) { + return IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE; + } else if (elem_type == IfcUtil::Argument_AGGREGATE_OF_INT) { + return IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT; + } else if (elem_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) { + return IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE; + } else if (elem_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) { + return IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE; + } else if (elem_type == IfcUtil::Argument_EMPTY_AGGREGATE) { + return IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE; + } else { + return IfcUtil::Argument_UNKNOWN; + } } IfcUtil::ArgumentType IfcUtil::from_parameter_type(const IfcParse::parameter_type* pt) { - // TODO: How to detect derived types here without a reference to the refering entity? + // TODO: How to detect derived types here without a reference to the refering entity? - const IfcParse::aggregation_type* at = pt->as_aggregation_type(); - const IfcParse::named_type* nt = pt->as_named_type(); - const IfcParse::simple_type* st = pt->as_simple_type(); - - if (at) { - return make_aggregate(from_parameter_type(at->type_of_element())); - } else if (nt) { - if (nt->declared_type()->as_entity()) { - return IfcUtil::Argument_ENTITY_INSTANCE; - } else if (nt->declared_type()->as_enumeration_type()) { - return IfcUtil::Argument_ENUMERATION; - } else if (nt->declared_type()->as_select_type()) { - return IfcUtil::Argument_ENTITY_INSTANCE; - } else if (nt->declared_type()->as_type_declaration()) { - return from_parameter_type(nt->declared_type()->as_type_declaration()->declared_type()); - } - } else if (st) { - switch (st->declared_type()) { - case IfcParse::simple_type::binary_type: - return IfcUtil::Argument_BINARY; - case IfcParse::simple_type::boolean_type: - return IfcUtil::Argument_BOOL; - case IfcParse::simple_type::integer_type: - return IfcUtil::Argument_INT; - case IfcParse::simple_type::logical_type: - return IfcUtil::Argument_LOGICAL; - case IfcParse::simple_type::number_type: - return IfcUtil::Argument_DOUBLE; - case IfcParse::simple_type::real_type: - return IfcUtil::Argument_DOUBLE; - case IfcParse::simple_type::string_type: - return IfcUtil::Argument_STRING; - case IfcParse::simple_type::datatype_COUNT: - throw IfcParse::IfcException("Invalid simple type encountered"); - } - } + const IfcParse::aggregation_type* at = pt->as_aggregation_type(); + const IfcParse::named_type* nt = pt->as_named_type(); + const IfcParse::simple_type* st = pt->as_simple_type(); - return IfcUtil::Argument_UNKNOWN; + if (at) { + return make_aggregate(from_parameter_type(at->type_of_element())); + } else if (nt) { + if (nt->declared_type()->as_entity()) { + return IfcUtil::Argument_ENTITY_INSTANCE; + } else if (nt->declared_type()->as_enumeration_type()) { + return IfcUtil::Argument_ENUMERATION; + } else if (nt->declared_type()->as_select_type()) { + return IfcUtil::Argument_ENTITY_INSTANCE; + } else if (nt->declared_type()->as_type_declaration()) { + return from_parameter_type(nt->declared_type()->as_type_declaration()->declared_type()); + } + } else if (st) { + switch (st->declared_type()) { + case IfcParse::simple_type::binary_type: + return IfcUtil::Argument_BINARY; + case IfcParse::simple_type::boolean_type: + return IfcUtil::Argument_BOOL; + case IfcParse::simple_type::integer_type: + return IfcUtil::Argument_INT; + case IfcParse::simple_type::logical_type: + return IfcUtil::Argument_LOGICAL; + case IfcParse::simple_type::number_type: + return IfcUtil::Argument_DOUBLE; + case IfcParse::simple_type::real_type: + return IfcUtil::Argument_DOUBLE; + case IfcParse::simple_type::string_type: + return IfcUtil::Argument_STRING; + case IfcParse::simple_type::datatype_COUNT: + throw IfcParse::IfcException("Invalid simple type encountered"); + } + } + + return IfcUtil::Argument_UNKNOWN; } #ifdef _MSC_VER std::string IfcUtil::path::to_utf8(const std::wstring& str) { - int buffer_size = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, 0, 0, 0, 0); - char* buffer = new char[buffer_size]; - WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, buffer, buffer_size, 0, 0); - std::string str_utf8(buffer); - delete[] buffer; - return str_utf8; + int buffer_size = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, 0, 0, 0, 0); + char* buffer = new char[buffer_size]; + WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, buffer, buffer_size, 0, 0); + std::string str_utf8(buffer); + delete[] buffer; + return str_utf8; } std::wstring IfcUtil::path::from_utf8(const std::string& str) { - int buffer_size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, 0, 0); - wchar_t* buffer = new wchar_t[buffer_size]; - MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, buffer, buffer_size); - std::wstring str_wide(buffer); - delete[] buffer; - return str_wide; + int buffer_size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, 0, 0); + wchar_t* buffer = new wchar_t[buffer_size]; + MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, buffer, buffer_size); + std::wstring str_wide(buffer); + delete[] buffer; + return str_wide; } IFC_PARSE_API bool IfcUtil::path::rename_file(const std::string& old_filename, const std::string& new_filename) { - std::wstring old_filename_w = from_utf8(old_filename); - std::wstring new_filename_w = from_utf8(new_filename); - delete_file(new_filename); - const bool success = !!MoveFileW(old_filename_w.c_str(), new_filename_w.c_str()); - return success; + std::wstring old_filename_w = from_utf8(old_filename); + std::wstring new_filename_w = from_utf8(new_filename); + delete_file(new_filename); + const bool success = !!MoveFileW(old_filename_w.c_str(), new_filename_w.c_str()); + return success; } IFC_PARSE_API bool IfcUtil::path::delete_file(const std::string& filename) { - std::wstring filename_w = from_utf8(filename); - const bool success = !!DeleteFileW(filename_w.c_str()); - return success; + std::wstring filename_w = from_utf8(filename); + const bool success = !!DeleteFileW(filename_w.c_str()); + return success; } #else IFC_PARSE_API bool IfcUtil::path::rename_file(const std::string& old_filename, const std::string& new_filename) { - // Whether or not rename() replaces an existing file is implementation-specific, - // so remove() possible existing file always. - delete_file(new_filename); - return std::rename(old_filename.c_str(), new_filename.c_str()) == 0; + // Whether or not rename() replaces an existing file is implementation-specific, + // so remove() possible existing file always. + delete_file(new_filename); + return std::rename(old_filename.c_str(), new_filename.c_str()) == 0; } IFC_PARSE_API bool IfcUtil::path::delete_file(const std::string& filename) { - return std::remove(filename.c_str()); + return std::remove(filename.c_str()); } #endif diff --git a/src/ifcparse/IfcWrite.cpp b/src/ifcparse/IfcWrite.cpp index 2adabed7f8..c92581f965 100644 --- a/src/ifcparse/IfcWrite.cpp +++ b/src/ifcparse/IfcWrite.cpp @@ -17,282 +17,304 @@ * * ********************************************************************************/ -#include -#include -#include +#include "IfcWrite.h" + +#include "IfcCharacterDecoder.h" +#include "IfcFile.h" +#include "IfcParse.h" #include - -#include "../ifcparse/IfcParse.h" -#include "../ifcparse/IfcWrite.h" -#include "../ifcparse/IfcCharacterDecoder.h" -#include "../ifcparse/IfcFile.h" +#include +#include +#include using namespace IfcWrite; class SizeVisitor : public boost::static_visitor { -public: - int operator()(const boost::blank& /*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 boost::logic::tribool& /*i*/) const { return -1; } - int operator()(const double& /*i*/) const { return -1; } - int operator()(const std::string& /*i*/) const { return -1; } - int operator()(const boost::dynamic_bitset<>& /*i*/) const { return -1; } - int operator()(const IfcWriteArgument::empty_aggregate_t&) const { return 0; } - int operator()(const IfcWriteArgument::empty_aggregate_of_aggregate_t&) const { return 0; } - int operator()(const std::vector& i) const { return (int)i.size(); } - int operator()(const std::vector& i) const { return (int)i.size(); } - int operator()(const std::vector< std::vector >& i) const { return (int)i.size(); } - int operator()(const std::vector< std::vector >& i) const { return (int)i.size(); } - int operator()(const std::vector& i) const { return (int)i.size(); } - int operator()(const std::vector< boost::dynamic_bitset<> >& i) const { return (int)i.size(); } - int operator()(const IfcWriteArgument::EnumerationReference& /*i*/) const { return -1; } - int operator()(const IfcUtil::IfcBaseClass* const& /*i*/) const { return -1; } - int operator()(const aggregate_of_instance::ptr& i) const { return i->size(); } - int operator()(const aggregate_of_aggregate_of_instance::ptr& i) const { return i->size(); } + public: + int operator()(const boost::blank& /*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 boost::logic::tribool& /*i*/) const { return -1; } + int operator()(const double& /*i*/) const { return -1; } + int operator()(const std::string& /*i*/) const { return -1; } + int operator()(const boost::dynamic_bitset<>& /*i*/) const { return -1; } + int operator()(const IfcWriteArgument::empty_aggregate_t&) const { return 0; } + int operator()(const IfcWriteArgument::empty_aggregate_of_aggregate_t&) const { return 0; } + int operator()(const std::vector& i) const { return (int)i.size(); } + int operator()(const std::vector& i) const { return (int)i.size(); } + int operator()(const std::vector>& i) const { return (int)i.size(); } + int operator()(const std::vector>& i) const { return (int)i.size(); } + int operator()(const std::vector& i) const { return (int)i.size(); } + int operator()(const std::vector>& i) const { return (int)i.size(); } + int operator()(const IfcWriteArgument::EnumerationReference& /*i*/) const { return -1; } + int operator()(const IfcUtil::IfcBaseClass* const& /*i*/) const { return -1; } + int operator()(const aggregate_of_instance::ptr& i) const { return i->size(); } + int operator()(const aggregate_of_aggregate_of_instance::ptr& i) const { return i->size(); } }; class StringBuilderVisitor : public boost::static_visitor { -private: - StringBuilderVisitor(const StringBuilderVisitor&); //N/A - StringBuilderVisitor& operator =(const StringBuilderVisitor&); //N/A + private: + StringBuilderVisitor(const StringBuilderVisitor&); //N/A + StringBuilderVisitor& operator=(const StringBuilderVisitor&); //N/A - 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.imbue(std::locale::classic()); - oss << std::setprecision(std::numeric_limits::digits10) << 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(); - } + 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.imbue(std::locale::classic()); + oss << std::setprecision(std::numeric_limits::digits10) << 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(); + } - std::string format_binary(const boost::dynamic_bitset<>& b) { - std::ostringstream oss; - oss.imbue(std::locale::classic()); - oss.put('"'); - oss << std::hex << std::setw(1); - unsigned c = (unsigned)b.size(); - unsigned n = (4 - (c % 4)) & 3; - oss << n; - for (unsigned i = 0; i < c + n;) { - unsigned accum = 0; - for (int j = 0; j < 4; ++j, ++i) { - unsigned bit = i < n ? 0 : b.test(c - i + n - 1) ? 1 : 0; - accum |= bit << (3-j); - } - oss << accum; - } - oss.put('"'); - return oss.str(); - } + std::string format_binary(const boost::dynamic_bitset<>& b) { + std::ostringstream oss; + oss.imbue(std::locale::classic()); + oss.put('"'); + oss << std::hex << std::setw(1); + unsigned c = (unsigned)b.size(); + unsigned n = (4 - (c % 4)) & 3; + oss << n; + for (unsigned i = 0; i < c + n;) { + unsigned accum = 0; + for (int j = 0; j < 4; ++j, ++i) { + unsigned bit = i < n ? 0 : b.test(c - i + n - 1) ? 1 + : 0; + accum |= bit << (3 - j); + } + oss << accum; + } + oss.put('"'); + return oss.str(); + } - bool upper; -public: - StringBuilderVisitor(std::ostringstream& stream, bool upper = false) - : data(stream), upper(upper) {} - void operator()(const boost::blank& /*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 boost::logic::tribool& i) { data << (i ? ".T." : (boost::logic::indeterminate(i) ? ".U." : ".F.")); } - void operator()(const double& i) { data << format_double(i); } - void operator()(const boost::dynamic_bitset<>& i) { data << format_binary(i); } - void operator()(const std::string& i) { - std::string s = i; - if (upper) { - data << static_cast(IfcCharacterEncoder(s)); - } else { - data << '\'' << s << '\''; - } - } - void operator()(const std::vector& i); - void operator()(const std::vector& i); - void operator()(const std::vector& i); - void operator()(const std::vector< boost::dynamic_bitset<> >& i); - void operator()(const IfcWriteArgument::EnumerationReference& i) { - data << "." << i.enumeration_value << "."; - } - void operator()(const IfcUtil::IfcBaseClass* const& i) { - const IfcEntityInstanceData& e = i->data(); - if (!e.type()->as_entity()) { - data << e.toString(upper); - } else { - data << "#" << e.id(); - } - } - void operator()(const aggregate_of_instance::ptr& i) { - data << "("; - for (aggregate_of_instance::it it = i->begin(); it != i->end(); ++it) { - if (it != i->begin()) data << ","; - (*this)(*it); - } - data << ")"; - } - void operator()(const std::vector< std::vector >& i); - void operator()(const std::vector< std::vector >& i); - void operator()(const aggregate_of_aggregate_of_instance::ptr& i) { - data << "("; - for (aggregate_of_aggregate_of_instance::outer_it outer_it = i->begin(); outer_it != i->end(); ++outer_it) { - if (outer_it != i->begin()) data << ","; - data << "("; - for (aggregate_of_aggregate_of_instance::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 << ")"; - } - void operator()(const IfcWriteArgument::empty_aggregate_t&) const { data << "()"; } - void operator()(const IfcWriteArgument::empty_aggregate_of_aggregate_t&) const { data << "()"; } - operator std::string() { return data.str(); } + bool upper; + + public: + StringBuilderVisitor(std::ostringstream& stream, bool upper = false) + : data(stream), + upper(upper) {} + void operator()(const boost::blank& /*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 boost::logic::tribool& i) { data << (i ? ".T." : (boost::logic::indeterminate(i) ? ".U." : ".F.")); } + void operator()(const double& i) { data << format_double(i); } + void operator()(const boost::dynamic_bitset<>& i) { data << format_binary(i); } + void operator()(const std::string& i) { + std::string s = i; + if (upper) { + data << static_cast(IfcCharacterEncoder(s)); + } else { + data << '\'' << s << '\''; + } + } + void operator()(const std::vector& i); + void operator()(const std::vector& i); + void operator()(const std::vector& i); + void operator()(const std::vector>& i); + void operator()(const IfcWriteArgument::EnumerationReference& i) { + data << "." << i.enumeration_value << "."; + } + void operator()(const IfcUtil::IfcBaseClass* const& i) { + const IfcEntityInstanceData& e = i->data(); + if (!e.type()->as_entity()) { + data << e.toString(upper); + } else { + data << "#" << e.id(); + } + } + void operator()(const aggregate_of_instance::ptr& i) { + data << "("; + for (aggregate_of_instance::it it = i->begin(); it != i->end(); ++it) { + if (it != i->begin()) { + data << ","; + } + (*this)(*it); + } + data << ")"; + } + void operator()(const std::vector>& i); + void operator()(const std::vector>& i); + void operator()(const aggregate_of_aggregate_of_instance::ptr& i) { + data << "("; + for (aggregate_of_aggregate_of_instance::outer_it outer_it = i->begin(); outer_it != i->end(); ++outer_it) { + if (outer_it != i->begin()) { + data << ","; + } + data << "("; + for (aggregate_of_aggregate_of_instance::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 << ")"; + } + void operator()(const IfcWriteArgument::empty_aggregate_t&) const { data << "()"; } + void operator()(const IfcWriteArgument::empty_aggregate_of_aggregate_t&) const { data << "()"; } + operator std::string() { return data.str(); } }; template <> void StringBuilderVisitor::serialize(const std::vector& i) { - data << "("; - for (std::vector::const_iterator it = i.begin(); it != i.end(); ++it) { - if (it != i.begin()) data << ","; - std::string s = IfcCharacterEncoder(*it); - data << s; - } - data << ")"; + data << "("; + for (std::vector::const_iterator it = i.begin(); it != i.end(); ++it) { + if (it != i.begin()) { + data << ","; + } + std::string s = IfcCharacterEncoder(*it); + data << s; + } + data << ")"; } template <> void StringBuilderVisitor::serialize(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 << ")"; + data << "("; + for (std::vector::const_iterator it = i.begin(); it != i.end(); ++it) { + if (it != i.begin()) { + data << ","; + } + data << format_double(*it); + } + data << ")"; } template <> -void StringBuilderVisitor::serialize(const std::vector< boost::dynamic_bitset<> >& i) { - data << "("; - for (std::vector< boost::dynamic_bitset<> >::const_iterator it = i.begin(); it != i.end(); ++it) { - if (it != i.begin()) data << ","; - data << format_binary(*it); - } - data << ")"; +void StringBuilderVisitor::serialize(const std::vector>& i) { + data << "("; + for (std::vector>::const_iterator it = i.begin(); it != i.end(); ++it) { + if (it != i.begin()) { + data << ","; + } + data << format_binary(*it); + } + data << ")"; } void StringBuilderVisitor::operator()(const std::vector& i) { serialize(i); } void StringBuilderVisitor::operator()(const std::vector& i) { serialize(i); } void StringBuilderVisitor::operator()(const std::vector& i) { serialize(i); } -void StringBuilderVisitor::operator()(const std::vector< boost::dynamic_bitset<> >& i) { serialize(i); } -void StringBuilderVisitor::operator()(const std::vector< std::vector >& i) { - data << "("; - for (std::vector< std::vector >::const_iterator it = i.begin(); it != i.end(); ++it) { - if (it != i.begin()) data << ","; - serialize(*it); - } - data << ")"; +void StringBuilderVisitor::operator()(const std::vector>& i) { serialize(i); } +void StringBuilderVisitor::operator()(const std::vector>& i) { + data << "("; + for (std::vector>::const_iterator it = i.begin(); it != i.end(); ++it) { + if (it != i.begin()) { + data << ","; + } + serialize(*it); + } + data << ")"; } -void StringBuilderVisitor::operator()(const std::vector< std::vector >& i) { - data << "("; - for (std::vector< std::vector >::const_iterator it = i.begin(); it != i.end(); ++it) { - if (it != i.begin()) data << ","; - serialize(*it); - } - data << ")"; +void StringBuilderVisitor::operator()(const std::vector>& i) { + data << "("; + for (std::vector>::const_iterator it = i.begin(); it != i.end(); ++it) { + if (it != i.begin()) { + data << ","; + } + serialize(*it); + } + data << ")"; } IfcWriteArgument::operator int() const { return as(); } IfcWriteArgument::operator bool() const { return as(); } IfcWriteArgument::operator boost::logic::tribool() const { return as(); } IfcWriteArgument::operator double() const { return as(); } -IfcWriteArgument::operator std::string() const { - if (type() == IfcUtil::Argument_ENUMERATION) { - return as().enumeration_value; - } - return as(); +IfcWriteArgument::operator std::string() const { + if (type() == IfcUtil::Argument_ENUMERATION) { + return as().enumeration_value; + } + return as(); } IfcWriteArgument::operator IfcUtil::IfcBaseClass*() const { return as(); } -IfcWriteArgument::operator boost::dynamic_bitset<>() const { return as< boost::dynamic_bitset<> >(); } -IfcWriteArgument::operator std::vector() const { return as >(); } -IfcWriteArgument::operator std::vector() const { return as >(); } -IfcWriteArgument::operator std::vector() const { return as >(); } -IfcWriteArgument::operator std::vector< boost::dynamic_bitset<> >() const { return as< std::vector< boost::dynamic_bitset<> > >(); } +IfcWriteArgument::operator boost::dynamic_bitset<>() 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 std::vector>() const { return as>>(); } IfcWriteArgument::operator aggregate_of_instance::ptr() const { return as(); } -IfcWriteArgument::operator std::vector< std::vector >() const { return as > >(); } -IfcWriteArgument::operator std::vector< std::vector >() const { return as > >(); } +IfcWriteArgument::operator std::vector>() const { return as>>(); } +IfcWriteArgument::operator std::vector>() const { return as>>(); } IfcWriteArgument::operator aggregate_of_aggregate_of_instance::ptr() const { return as(); } bool IfcWriteArgument::isNull() const { return type() == IfcUtil::Argument_NULL; } -Argument* IfcWriteArgument::operator [] (unsigned int /*i*/) const { throw IfcParse::IfcException("Invalid cast"); } +Argument* IfcWriteArgument::operator[](unsigned int /*i*/) const { throw IfcParse::IfcException("Invalid cast"); } std::string IfcWriteArgument::toString(bool upper) const { - std::ostringstream str; - str.imbue(std::locale::classic()); - StringBuilderVisitor v(str, upper); - container.apply_visitor(v); - return v; + std::ostringstream str; + str.imbue(std::locale::classic()); + StringBuilderVisitor v(str, upper); + container.apply_visitor(v); + return v; } 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; - } + SizeVisitor v; + const int size = container.apply_visitor(v); + if (size == -1) { + throw IfcParse::IfcException("Invalid cast"); + } else { + return size; + } } IfcUtil::ArgumentType IfcWriteArgument::type() const { - return static_cast(container.which()); + return static_cast(container.which()); } // Overload to detect null values void IfcWriteArgument::set(const aggregate_of_instance::ptr& v) { - if (v) { - container = v; - } else { - container = boost::blank(); - } + if (v) { + container = v; + } else { + container = boost::blank(); + } } // Overload to detect null values void IfcWriteArgument::set(const aggregate_of_aggregate_of_instance::ptr& v) { - if (v) { - container = v; - } else { - container = boost::blank(); - } + if (v) { + container = v; + } else { + container = boost::blank(); + } } // Overload to detect null values -void IfcWriteArgument::set(IfcUtil::IfcBaseInterface*const& v) { - if (v) { - container = v->as(); - } else { - container = boost::blank(); - } -} \ No newline at end of file +void IfcWriteArgument::set(IfcUtil::IfcBaseInterface* const& v) { + if (v) { + container = v->as(); + } else { + container = boost::blank(); + } +} diff --git a/src/ifcparse/IfcWrite.h b/src/ifcparse/IfcWrite.h index c69ca6052b..7be4ada1af 100644 --- a/src/ifcparse/IfcWrite.h +++ b/src/ifcparse/IfcWrite.h @@ -28,148 +28,147 @@ #ifndef IFCWRITE_H #define IFCWRITE_H -#include -#include -#include -// #include +#include "ifc_parse_api.h" +#include "IfcBaseClass.h" +#include "IfcParse.h" -#include +#include +#include #include #include - -#include "ifc_parse_api.h" - -#include "../ifcparse/IfcBaseClass.h" -#include "../ifcparse/IfcParse.h" +#include +#include +// #include namespace IfcWrite { - /// 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 IFC_PARSE_API IfcWriteArgument : public Argument { - 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 {}; - class empty_aggregate_t {}; - class empty_aggregate_of_aggregate_t {}; - private: - boost::variant< - // A null argument, it will always serialize to $ - boost::blank, - // A derived argument, it will always serialize to * - Derived, - // An integer argument, e.g. 123 +/// 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 IFC_PARSE_API IfcWriteArgument : public Argument { + 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 {}; + class empty_aggregate_t {}; + class empty_aggregate_of_aggregate_t {}; - // SCALARS: - int, - // A boolean argument, it will serialize to either .T. or .F. - bool, - // A logical argument, it will serialize to either .T. or .F. or .U. - boost::logic::tribool, - // A floating point argument, e.g. 12.3 - double, - // A character string argument, e.g. 'IfcOpenShell' - std::string, - // A binary argument, e.g. "092A" -> 100100101010 - boost::dynamic_bitset<>, - // An enumeration argument, e.g. .USERDEFINED. - // To initialize the argument a string representation - // has to be explicitly 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::IfcBaseClass*, + private: + boost::variant< + // A null argument, it will always serialize to $ + boost::blank, + // A derived argument, it will always serialize to * + Derived, + // An integer argument, e.g. 123 - // AGGREGATES: - empty_aggregate_t, - // An aggregate of integers, e.g. (1,2,3) - std::vector, - // An aggregate of floats, e.g. (12.3,4.) - std::vector, - // An aggregate of strings, e.g. ('Ifc','Open','Shell') - std::vector, - // An aggregate of binaries, e.g. ("23B", "092A") -> (111011, 100100101010) - std::vector >, - // An aggregate of entity instances. It will either serialize to - // e.g. (#1,#2,#3) or datatype identifier for simple types, - // e.g. (IFCREAL(1.2),IFCINTEGER(3.)) - aggregate_of_instance::ptr, + // SCALARS: + int, + // A boolean argument, it will serialize to either .T. or .F. + bool, + // A logical argument, it will serialize to either .T. or .F. or .U. + boost::logic::tribool, + // A floating point argument, e.g. 12.3 + double, + // A character string argument, e.g. 'IfcOpenShell' + std::string, + // A binary argument, e.g. "092A" -> 100100101010 + boost::dynamic_bitset<>, + // An enumeration argument, e.g. .USERDEFINED. + // To initialize the argument a string representation + // has to be explicitly 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::IfcBaseClass*, - // AGGREGATES OF AGGREGATES: - empty_aggregate_of_aggregate_t, - // An aggregate of an aggregate of ints. E.g. ((1, 2), (3)) - std::vector< std::vector >, - // An aggregate of an aggregate of floats. E.g. ((1., 2.3), (4.)) - std::vector< std::vector >, - // An aggregate of an aggregate of entities. E.g. ((#1, #2), (#3)) - aggregate_of_aggregate_of_instance::ptr - > container; - public: + // AGGREGATES: + empty_aggregate_t, + // An aggregate of integers, e.g. (1,2,3) + std::vector, + // An aggregate of floats, e.g. (12.3,4.) + std::vector, + // An aggregate of strings, e.g. ('Ifc','Open','Shell') + std::vector, + // An aggregate of binaries, e.g. ("23B", "092A") -> (111011, 100100101010) + std::vector>, + // An aggregate of entity instances. It will either serialize to + // e.g. (#1,#2,#3) or datatype identifier for simple types, + // e.g. (IFCREAL(1.2),IFCINTEGER(3.)) + aggregate_of_instance::ptr, - template - const T& as() const { - if (const T* val = boost::get(&container)) { - return *val; - } else { - throw IfcParse::IfcException("Invalid cast"); - } - } + // AGGREGATES OF AGGREGATES: + empty_aggregate_of_aggregate_t, + // An aggregate of an aggregate of ints. E.g. ((1, 2), (3)) + std::vector>, + // An aggregate of an aggregate of floats. E.g. ((1., 2.3), (4.)) + std::vector>, + // An aggregate of an aggregate of entities. E.g. ((#1, #2), (#3)) + aggregate_of_aggregate_of_instance::ptr> + container; - template - typename boost::disable_if::type>, void>::type - set(const T& t) { - container = t; - } + public: + template + const T& as() const { + if (const T* val = boost::get(&container)) { + return *val; + } else { + throw IfcParse::IfcException("Invalid cast"); + } + } - // Overload to detect null values - void set(const aggregate_of_instance::ptr& v); + template + typename boost::disable_if::type>, void>::type + set(const T& t) { + container = t; + } - // Overload to detect null values - void set(const aggregate_of_aggregate_of_instance::ptr& v); + // Overload to detect null values + void set(const aggregate_of_instance::ptr& v); - // Overload to detect null values - void set(IfcUtil::IfcBaseInterface*const & v); - - operator int() const; - operator bool() const; - operator boost::logic::tribool() const; + // Overload to detect null values + void set(const aggregate_of_aggregate_of_instance::ptr& v); - operator double() const; - operator std::string() const; - operator boost::dynamic_bitset<>() const; - operator IfcUtil::IfcBaseClass*() const; + // Overload to detect null values + void set(IfcUtil::IfcBaseInterface* const& v); - operator std::vector() const; - operator std::vector() const; - operator std::vector() const; - operator std::vector >() const; - operator aggregate_of_instance::ptr() const; + operator int() const; + operator bool() const; + operator boost::logic::tribool() const; - operator std::vector< std::vector >() const; - operator std::vector< std::vector >() const; - operator aggregate_of_aggregate_of_instance::ptr() const; + operator double() const; + operator std::string() const; + operator boost::dynamic_bitset<>() const; + operator IfcUtil::IfcBaseClass*() const; - bool isNull() const; - Argument* operator [] (unsigned int i) const; - std::string toString(bool upper=false) const; - unsigned int size() const; - IfcUtil::ArgumentType type() const; - }; + operator std::vector() const; + operator std::vector() const; + operator std::vector() const; + operator std::vector>() const; + operator aggregate_of_instance::ptr() const; -} + operator std::vector>() const; + operator std::vector>() const; + operator aggregate_of_aggregate_of_instance::ptr() const; + bool isNull() const; + Argument* operator[](unsigned int i) const; + std::string toString(bool upper = false) const; + unsigned int size() const; + IfcUtil::ArgumentType type() const; +}; + +} // namespace IfcWrite #endif diff --git a/src/ifcparse/aggregate_of_instance.h b/src/ifcparse/aggregate_of_instance.h index c6bf8f5921..0be8b8ed0e 100644 --- a/src/ifcparse/aggregate_of_instance.h +++ b/src/ifcparse/aggregate_of_instance.h @@ -20,170 +20,191 @@ #ifndef IFCENTITYLIST_H #define IFCENTITYLIST_H -#include "../ifcparse/IfcBaseClass.h" +#include "IfcBaseClass.h" #include - #include template class aggregate_of; class IFC_PARSE_API aggregate_of_instance { - std::vector ls; -public: - typedef boost::shared_ptr ptr; - typedef std::vector::const_iterator it; - void push(IfcUtil::IfcBaseClass* l); - void push(const ptr& l); - it begin(); - it end(); - IfcUtil::IfcBaseClass* operator[] (int i); - unsigned int size() const; + std::vector ls; + + public: + typedef boost::shared_ptr ptr; + typedef std::vector::const_iterator it; + void push(IfcUtil::IfcBaseClass* l); + void push(const ptr& l); + it begin(); + it end(); + IfcUtil::IfcBaseClass* operator[](int i); + unsigned int size() const; void reserve(unsigned capacity); - bool contains(IfcUtil::IfcBaseClass*) const; - template - typename U::list::ptr as() { - typename U::list::ptr r(new typename U::list); - for (it i = begin(); i != end(); ++i) { - if ((*i)->as()) { - r->push((*i)->as()); - } - } - return r; - } - void remove(IfcUtil::IfcBaseClass*); - aggregate_of_instance::ptr filtered(const std::set& entities); - aggregate_of_instance::ptr unique(); + bool contains(IfcUtil::IfcBaseClass*) const; + template + typename U::list::ptr as() { + typename U::list::ptr r(new typename U::list); + for (it i = begin(); i != end(); ++i) { + if ((*i)->as()) { + r->push((*i)->as()); + } + } + return r; + } + void remove(IfcUtil::IfcBaseClass*); + aggregate_of_instance::ptr filtered(const std::set& entities); + aggregate_of_instance::ptr unique(); }; template class aggregate_of { - std::vector ls; -public: - typedef boost::shared_ptr< aggregate_of > ptr; - typedef typename std::vector::const_iterator it; - void push(T* t) { if (t) { ls.push_back(t); } } - void push(ptr t) { if (t) { for (typename T::list::it it = t->begin(); it != t->end(); ++it) push(*it); } } - it begin() { return ls.begin(); } - it end() { return ls.end(); } - unsigned int size() const { return (unsigned int)ls.size(); } - aggregate_of_instance::ptr generalize() { - aggregate_of_instance::ptr r(new aggregate_of_instance()); - for (it i = begin(); i != end(); ++i) r->push((*i)->template as()); - return r; - } - bool contains(T* t) const { return std::find(ls.begin(), ls.end(), t) != ls.end(); } - template - typename U::list::ptr as() { - typename U::list::ptr r(new typename U::list); - const bool all = !U::Class().as_entity(); - for (it i = begin(); i != end(); ++i) if (all || (*i)->declaration().is(U::Class())) r->push((U*)*i); - return r; - } - void remove(T* t) { - typename std::vector::iterator it; - while ((it = std::find(ls.begin(), ls.end(), t)) != ls.end()) { - ls.erase(it); - } - } + std::vector ls; + + public: + typedef boost::shared_ptr> ptr; + typedef typename std::vector::const_iterator it; + void push(T* t) { + if (t) { + ls.push_back(t); + } + } + void push(ptr t) { + if (t) { + for (typename T::list::it it = t->begin(); it != t->end(); ++it) { + push(*it); + } + } + } + it begin() { return ls.begin(); } + it end() { return ls.end(); } + unsigned int size() const { return (unsigned int)ls.size(); } + aggregate_of_instance::ptr generalize() { + aggregate_of_instance::ptr r(new aggregate_of_instance()); + for (it i = begin(); i != end(); ++i) { + r->push((*i)->template as()); + } + return r; + } + bool contains(T* t) const { return std::find(ls.begin(), ls.end(), t) != ls.end(); } + template + typename U::list::ptr as() { + typename U::list::ptr r(new typename U::list); + const bool all = !U::Class().as_entity(); + for (it i = begin(); i != end(); ++i) { + if (all || (*i)->declaration().is(U::Class())) { + r->push((U*)*i); + } + } + return r; + } + void remove(T* t) { + typename std::vector::iterator it; + while ((it = std::find(ls.begin(), ls.end(), t)) != ls.end()) { + ls.erase(it); + } + } }; template class aggregate_of_aggregate_of; class IFC_PARSE_API aggregate_of_aggregate_of_instance { - std::vector< std::vector > ls; -public: - typedef boost::shared_ptr< aggregate_of_aggregate_of_instance > ptr; - typedef std::vector< std::vector >::const_iterator outer_it; - typedef std::vector::const_iterator inner_it; - void push(const std::vector& l) { - ls.push_back(l); - } - void push(const aggregate_of_instance::ptr& l) { - if (l) { - std::vector li; - for (std::vector::const_iterator jt = l->begin(); jt != l->end(); ++jt) { - li.push_back(*jt); - } - push(li); - } - } - outer_it begin() const { return ls.begin(); } - outer_it end() const { return ls.end(); } - int size() const { return (int)ls.size(); } - int totalSize() const { - int accum = 0; - for (outer_it it = begin(); it != end(); ++it) { - accum += (int)it->size(); - } - return accum; - } - bool contains(IfcUtil::IfcBaseClass* instance) const { - for (outer_it it = begin(); it != end(); ++it) { - const std::vector& inner = *it; - if (std::find(inner.begin(), inner.end(), instance) != inner.end()) { - return true; - } - } - return false; - } - template - typename aggregate_of_aggregate_of::ptr as() { - typename aggregate_of_aggregate_of::ptr r(new aggregate_of_aggregate_of); - const bool all = !U::Class().as_entity(); - for (outer_it outer = begin(); outer != end(); ++outer) { - const std::vector& from = *outer; - typename std::vector to; - for (inner_it inner = from.begin(); inner != from.end(); ++inner) { - if (all || (*inner)->declaration().is(U::Class())) to.push_back((U*)*inner); - } - r->push(to); - } - return r; - } + std::vector> ls; + + public: + typedef boost::shared_ptr ptr; + typedef std::vector>::const_iterator outer_it; + typedef std::vector::const_iterator inner_it; + void push(const std::vector& l) { + ls.push_back(l); + } + void push(const aggregate_of_instance::ptr& l) { + if (l) { + std::vector li; + for (std::vector::const_iterator jt = l->begin(); jt != l->end(); ++jt) { + li.push_back(*jt); + } + push(li); + } + } + outer_it begin() const { return ls.begin(); } + outer_it end() const { return ls.end(); } + int size() const { return (int)ls.size(); } + int totalSize() const { + int accum = 0; + for (outer_it it = begin(); it != end(); ++it) { + accum += (int)it->size(); + } + return accum; + } + bool contains(IfcUtil::IfcBaseClass* instance) const { + for (outer_it it = begin(); it != end(); ++it) { + const std::vector& inner = *it; + if (std::find(inner.begin(), inner.end(), instance) != inner.end()) { + return true; + } + } + return false; + } + template + typename aggregate_of_aggregate_of::ptr as() { + typename aggregate_of_aggregate_of::ptr r(new aggregate_of_aggregate_of); + const bool all = !U::Class().as_entity(); + for (outer_it outer = begin(); outer != end(); ++outer) { + const std::vector& from = *outer; + typename std::vector to; + for (inner_it inner = from.begin(); inner != from.end(); ++inner) { + if (all || (*inner)->declaration().is(U::Class())) { + to.push_back((U*)*inner); + } + } + r->push(to); + } + return r; + } }; template class aggregate_of_aggregate_of { - std::vector< std::vector > ls; -public: - typedef typename boost::shared_ptr< aggregate_of_aggregate_of > ptr; - typedef typename std::vector< std::vector >::const_iterator outer_it; - typedef typename std::vector::const_iterator inner_it; - void push(const std::vector& t) { ls.push_back(t); } - outer_it begin() { return ls.begin(); } - outer_it end() { return ls.end(); } - int size() const { return (int)ls.size(); } - int totalSize() const { - int accum = 0; - for (outer_it it = begin(); it != end(); ++it) { - accum += it->size(); - } - return accum; - } - bool contains(T* t) const { - for (outer_it it = begin(); it != end(); ++it) { - const std::vector& inner = *it; - if (std::find(inner.begin(), inner.end(), t) != inner.end()) { - return true; - } - } - return false; - } - aggregate_of_aggregate_of_instance::ptr generalize() { - aggregate_of_aggregate_of_instance::ptr r(new aggregate_of_aggregate_of_instance()); - for (outer_it outer = begin(); outer != end(); ++outer) { - const std::vector& from = *outer; - std::vector to; - for (inner_it inner = from.begin(); inner != from.end(); ++inner) { - to.push_back(*inner); - } - r->push(to); - } - return r; - } + std::vector> ls; + + public: + typedef typename boost::shared_ptr> ptr; + typedef typename std::vector>::const_iterator outer_it; + typedef typename std::vector::const_iterator inner_it; + void push(const std::vector& t) { ls.push_back(t); } + outer_it begin() { return ls.begin(); } + outer_it end() { return ls.end(); } + int size() const { return (int)ls.size(); } + int totalSize() const { + int accum = 0; + for (outer_it it = begin(); it != end(); ++it) { + accum += it->size(); + } + return accum; + } + bool contains(T* t) const { + for (outer_it it = begin(); it != end(); ++it) { + const std::vector& inner = *it; + if (std::find(inner.begin(), inner.end(), t) != inner.end()) { + return true; + } + } + return false; + } + aggregate_of_aggregate_of_instance::ptr generalize() { + aggregate_of_aggregate_of_instance::ptr r(new aggregate_of_aggregate_of_instance()); + for (outer_it outer = begin(); outer != end(); ++outer) { + const std::vector& from = *outer; + std::vector to; + for (inner_it inner = from.begin(); inner != from.end(); ++inner) { + to.push_back(*inner); + } + r->push(to); + } + return r; + } }; #endif diff --git a/src/ifcparse/ifc_parse_api.h b/src/ifcparse/ifc_parse_api.h index 6a92c6d152..98c8278341 100644 --- a/src/ifcparse/ifc_parse_api.h +++ b/src/ifcparse/ifc_parse_api.h @@ -21,30 +21,30 @@ #define IFC_PARSE_API_H #ifdef IFC_SHARED_BUILD - #ifdef _WIN32 - #ifdef IFC_PARSE_EXPORTS - #define IFC_PARSE_API __declspec(dllexport) - #else - #define IFC_PARSE_API __declspec(dllimport) - #endif - #else // simply assume *nix + GCC-like compiler - #define IFC_PARSE_API __attribute__((visibility("default"))) - #endif +#ifdef _WIN32 +#ifdef IFC_PARSE_EXPORTS +#define IFC_PARSE_API __declspec(dllexport) #else - #define IFC_PARSE_API +#define IFC_PARSE_API __declspec(dllimport) +#endif +#else // simply assume *nix + GCC-like compiler +#define IFC_PARSE_API __attribute__((visibility("default"))) +#endif +#else +#define IFC_PARSE_API #endif #if defined(__clang__) -# define my_thread_local thread_local +#define my_thread_local thread_local #elif defined(__GNUC__) -# define my_thread_local __thread +#define my_thread_local __thread #elif __STDC_VERSION__ >= 201112L -# define my_thread_local _Thread_local +#define my_thread_local _Thread_local #elif defined(_MSC_VER) -# define my_thread_local __declspec(thread) +#define my_thread_local __declspec(thread) #elif defined(SWIG) #else -# error Cannot define thread_local +#error Cannot define thread_local #endif #endif diff --git a/src/ifcparse/macros.h b/src/ifcparse/macros.h index cbf801243f..aeebe7c4fd 100644 --- a/src/ifcparse/macros.h +++ b/src/ifcparse/macros.h @@ -20,17 +20,15 @@ #ifndef IFCOPENSHELL_MACROS_H #define IFCOPENSHELL_MACROS_H -#define POSTFIX_SCHEMA__(a, b) a ## _ ## b +#define POSTFIX_SCHEMA__(a, b) a##_##b #define POSTFIX_SCHEMA_(a, b) POSTFIX_SCHEMA__(a, b) #define POSTFIX_SCHEMA(t) POSTFIX_SCHEMA_(t, IfcSchema) #define STRINGIFY_(x) #x #define STRINGIFY(x) STRINGIFY_(x) -#define MAKE_INIT_FN__(a, b) init_ ## a ## _ ## b +#define MAKE_INIT_FN__(a, b) init_##a##_##b #define MAKE_INIT_FN_(a, b) MAKE_INIT_FN__(a, b) #define MAKE_INIT_FN(t) MAKE_INIT_FN_(t, IfcSchema) - - -#endif \ No newline at end of file +#endif diff --git a/src/ifcparse/parse_ifcxml.cpp b/src/ifcparse/parse_ifcxml.cpp index bdeea7bd73..8781b7b649 100644 --- a/src/ifcparse/parse_ifcxml.cpp +++ b/src/ifcparse/parse_ifcxml.cpp @@ -1,14 +1,32 @@ +/******************************************************************************** +* * +* 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 . * +* * +********************************************************************************/ + #define BOOST_RESULT_OF_USE_DECLTYPE #ifdef WITH_IFCXML #include "IfcFile.h" -#include - #include #include #include +#include // For debug printing on release builds // #undef NDEBUG @@ -18,657 +36,665 @@ // has attributes in actual XML attributes and may include inverse attributes // to make trees more compact. enum ifcxml_dialect { - ifcxml_dialect_ifc2x3, - ifcxml_dialect_ifc4, - ifcxml_dialect_unknown + ifcxml_dialect_ifc2x3, + ifcxml_dialect_ifc4, + ifcxml_dialect_unknown }; // "Dereferences" a named_attribute. For example: // IfcCompoundPlaneAngleMeasure -> LIST [3:4] OF INTEGER void follow_named(const IfcParse::parameter_type*& pt) { - while (pt->as_named_type()) { - if (pt->as_named_type()->declared_type()->as_type_declaration()) { - pt = pt->as_named_type()->declared_type()->as_type_declaration()->declared_type(); - } else { - break; - } - } + while (pt->as_named_type()) { + if (pt->as_named_type()->declared_type()->as_type_declaration()) { + pt = pt->as_named_type()->declared_type()->as_type_declaration()->declared_type(); + } else { + break; + } + } } // The ifcXML parser uses SAX so we need to keep a stack of where we are in // the file. These different kinds of nodes could be subclasses but aren't // for ease in pushing to std::vector. class stack_node { -public: - enum node_type { stack_empty, node_instance, node_instance_attribute, node_aggregate, node_aggregate_element, node_inverse, node_select, node_header, node_header_entry }; + public: + enum node_type { + stack_empty, + node_instance, + node_instance_attribute, + node_aggregate, + node_aggregate_element, + node_inverse, + node_select, + node_header, + node_header_entry + }; - std::vector aggregate_elements; -protected: - node_type type_; - IfcUtil::IfcBaseClass* inst_; - int idx_; - const IfcParse::inverse_attribute* inv_; - std::string tagname_; - std::string id_in_file_; - const IfcParse::parameter_type* aggregate_elem_type_; - - stack_node() - : type_(stack_empty) - , inst_(nullptr) - , idx_(-1) - , inv_(nullptr) - , aggregate_elem_type_(nullptr) {} + std::vector aggregate_elements; -public: - static stack_node instance(const std::string& id_in_file, IfcUtil::IfcBaseClass* inst) { - stack_node n; - n.type_ = node_instance; - n.inst_ = inst; - n.id_in_file_ = id_in_file; - return n; - } + protected: + node_type type_; + IfcUtil::IfcBaseClass* inst_; + int idx_; + const IfcParse::inverse_attribute* inv_; + std::string tagname_; + std::string id_in_file_; + const IfcParse::parameter_type* aggregate_elem_type_; - static stack_node instance_attribute(IfcUtil::IfcBaseClass* inst, int idx) { - stack_node n; - n.type_ = node_instance_attribute; - n.inst_ = inst; - n.idx_ = idx; - return n; - } + stack_node() + : type_(stack_empty), + inst_(nullptr), + idx_(-1), + inv_(nullptr), + aggregate_elem_type_(nullptr) {} - static stack_node aggregate(IfcUtil::IfcBaseClass* inst, int idx) { - stack_node n; - n.type_ = node_aggregate; - n.inst_ = inst; - n.idx_ = idx; - return n; - } + public: + static stack_node instance(const std::string& id_in_file, IfcUtil::IfcBaseClass* inst) { + stack_node n; + n.type_ = node_instance; + n.inst_ = inst; + n.id_in_file_ = id_in_file; + return n; + } - static stack_node aggregate_element(const IfcParse::parameter_type* aggregate_elem_type, int idx) { - stack_node n; - n.type_ = node_aggregate_element; - n.idx_ = idx; - n.aggregate_elem_type_ = aggregate_elem_type; - return n; - } + static stack_node instance_attribute(IfcUtil::IfcBaseClass* inst, int idx) { + stack_node n; + n.type_ = node_instance_attribute; + n.inst_ = inst; + n.idx_ = idx; + return n; + } - static stack_node inverse(IfcUtil::IfcBaseClass* inst, const IfcParse::inverse_attribute* inv) { - stack_node n; - n.type_ = node_inverse; - n.inst_ = inst; - n.inv_ = inv; - return n; - } + static stack_node aggregate(IfcUtil::IfcBaseClass* inst, int idx) { + stack_node n; + n.type_ = node_aggregate; + n.inst_ = inst; + n.idx_ = idx; + return n; + } - static stack_node select(IfcUtil::IfcBaseClass* inst, int idx) { - stack_node n; - n.type_ = node_select; - n.inst_ = inst; - n.idx_ = idx; - return n; - } + static stack_node aggregate_element(const IfcParse::parameter_type* aggregate_elem_type, int idx) { + stack_node n; + n.type_ = node_aggregate_element; + n.idx_ = idx; + n.aggregate_elem_type_ = aggregate_elem_type; + return n; + } - static stack_node header() { - stack_node n; - n.type_ = node_header; - return n; - }; + static stack_node inverse(IfcUtil::IfcBaseClass* inst, const IfcParse::inverse_attribute* inv) { + stack_node n; + n.type_ = node_inverse; + n.inst_ = inst; + n.inv_ = inv; + return n; + } - static stack_node header_entry(const std::string& tagname) { - stack_node n; - n.type_ = node_header_entry; - n.tagname_ = tagname; - return n; - }; + static stack_node select(IfcUtil::IfcBaseClass* inst, int idx) { + stack_node n; + n.type_ = node_select; + n.inst_ = inst; + n.idx_ = idx; + return n; + } - node_type ntype() const { return type_; } + static stack_node header() { + stack_node n; + n.type_ = node_header; + return n; + }; - IfcUtil::IfcBaseClass* inst() const { return inst_; } - int idx() const { return idx_; } - const IfcParse::inverse_attribute* inv_attr() const { return inv_; } - const std::string& tagname() const { return tagname_; } - const std::string& id_in_file() const { return id_in_file_; } - const IfcParse::parameter_type* aggregate_elem_type() const { return aggregate_elem_type_; } + static stack_node header_entry(const std::string& tagname) { + stack_node n; + n.type_ = node_header_entry; + n.tagname_ = tagname; + return n; + }; - std::string repr() const { - std::stringstream ss; - static const char* const node_type_names[] = { "empty", "inst", "attr", "aggr", "agelem", "inv", "sel", "head", "hdentry" }; - ss << "[" << node_type_names[type_] << "] "; - if (inst_) { - ss << inst_->declaration().name() << " "; - } - if (type_ == node_aggregate) { - ss << "{" << aggregate_elements.size() << " elems} "; - } - if (idx_ != -1) { - ss << idx_ << " "; - } - return ss.str(); - } + node_type ntype() const { return type_; } + + IfcUtil::IfcBaseClass* inst() const { return inst_; } + int idx() const { return idx_; } + const IfcParse::inverse_attribute* inv_attr() const { return inv_; } + const std::string& tagname() const { return tagname_; } + const std::string& id_in_file() const { return id_in_file_; } + const IfcParse::parameter_type* aggregate_elem_type() const { return aggregate_elem_type_; } + + std::string repr() const { + std::stringstream ss; + static const char* const node_type_names[] = {"empty", "inst", "attr", "aggr", "agelem", "inv", "sel", "head", "hdentry"}; + ss << "[" << node_type_names[type_] << "] "; + if (inst_) { + ss << inst_->declaration().name() << " "; + } + if (type_ == node_aggregate) { + ss << "{" << aggregate_elements.size() << " elems} "; + } + if (idx_ != -1) { + ss << idx_ << " "; + } + return ss.str(); + } }; struct ifcxml_parse_state { - IfcParse::IfcFile* file; - std::vector stack; - std::map idmap; - std::vector > forward_references; - ifcxml_dialect dialect; + IfcParse::IfcFile* file; + std::vector stack; + std::map idmap; + std::vector> forward_references; + ifcxml_dialect dialect; }; // ifc4 allows for aggregates to be concatenated using whitespace. template std::vector split(const std::string& value) { - std::vector strs; - boost::split(strs, value, [](char c) { return c == ' '; }, boost::token_compress_on); - std::vector r(strs.size()); - boost::copy(strs | boost::adaptors::transformed([](const std::string& s) { - return boost::lexical_cast(s); - }), r.begin()); - return r; + std::vector strs; + boost::split( + strs, value, [](char c) { return c == ' '; }, boost::token_compress_on); + std::vector r(strs.size()); + boost::copy(strs | boost::adaptors::transformed([](const std::string& s) { + return boost::lexical_cast(s); + }), + r.begin()); + return r; } Argument* parse_attribute_value(const IfcParse::parameter_type* ty, const std::string& value) { - auto v = new IfcWrite::IfcWriteArgument(); + auto v = new IfcWrite::IfcWriteArgument(); - auto cpp_type = IfcUtil::from_parameter_type(ty); - - if (cpp_type == IfcUtil::Argument_STRING) { - v->set(value); - } else if (cpp_type == IfcUtil::Argument_ENUMERATION) { - auto enum_type = ty->as_named_type()->declared_type()->as_enumeration_type(); + auto cpp_type = IfcUtil::from_parameter_type(ty); - std::vector::const_iterator it = std::find( - enum_type->enumeration_items().begin(), - enum_type->enumeration_items().end(), - boost::to_upper_copy(value)); + if (cpp_type == IfcUtil::Argument_STRING) { + v->set(value); + } else if (cpp_type == IfcUtil::Argument_ENUMERATION) { + auto enum_type = ty->as_named_type()->declared_type()->as_enumeration_type(); - if (it != enum_type->enumeration_items().end()) { - v->set(IfcWrite::IfcWriteArgument::EnumerationReference(it - enum_type->enumeration_items().begin(), it->c_str())); - } - } else if (cpp_type == IfcUtil::Argument_INT) { - v->set(boost::lexical_cast(value)); - } else if (cpp_type == IfcUtil::Argument_DOUBLE) { - v->set(boost::lexical_cast(value)); - } else if (cpp_type == IfcUtil::Argument_BOOL) { - v->set(boost::to_lower_copy(value) == "true"); - } else if (cpp_type == IfcUtil::Argument_AGGREGATE_OF_INT) { - v->set(split(value)); - } else if (cpp_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) { - v->set(split(value)); - } + std::vector::const_iterator it = std::find( + enum_type->enumeration_items().begin(), + enum_type->enumeration_items().end(), + boost::to_upper_copy(value)); - if (v->isNull()) { - Logger::Error("Attribute '" + value + "' not succesfully parsed"); - delete v; - v = nullptr; - } + if (it != enum_type->enumeration_items().end()) { + v->set(IfcWrite::IfcWriteArgument::EnumerationReference(it - enum_type->enumeration_items().begin(), it->c_str())); + } + } else if (cpp_type == IfcUtil::Argument_INT) { + v->set(boost::lexical_cast(value)); + } else if (cpp_type == IfcUtil::Argument_DOUBLE) { + v->set(boost::lexical_cast(value)); + } else if (cpp_type == IfcUtil::Argument_BOOL) { + v->set(boost::to_lower_copy(value) == "true"); + } else if (cpp_type == IfcUtil::Argument_AGGREGATE_OF_INT) { + v->set(split(value)); + } else if (cpp_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) { + v->set(split(value)); + } - return v; + if (v->isNull()) { + Logger::Error("Attribute '" + value + "' not succesfully parsed"); + delete v; + v = nullptr; + } + + return v; } static void end_element(void* user, const xmlChar* tag) { - ifcxml_parse_state* state = (ifcxml_parse_state*)user; + ifcxml_parse_state* state = (ifcxml_parse_state*)user; - if (state->file == nullptr) { - return; - } - - if (!state->stack.empty() && state->stack.back().ntype() == stack_node::node_aggregate) { - const auto& back = state->stack.back(); - auto& elems = state->stack.back().aggregate_elements; - auto li = new IfcParse::ArgumentList(elems.size()); - size_t i = 0; - for (auto& elem : elems) { - li->arguments()[i++] = elem; - } - back.inst()->data().attributes()[back.idx()] = li; - } + if (state->file == nullptr) { + return; + } - if (state->dialect == ifcxml_dialect_ifc2x3 && state->stack.back().ntype() == stack_node::node_instance) { - if (state->stack.back().inst() != nullptr) { - state->idmap[state->stack.back().id_in_file()] = state->file->addEntity(state->stack.back().inst())->data().id(); - } - } + if (!state->stack.empty() && state->stack.back().ntype() == stack_node::node_aggregate) { + const auto& back = state->stack.back(); + auto& elems = state->stack.back().aggregate_elements; + auto li = new IfcParse::ArgumentList(elems.size()); + size_t i = 0; + for (auto& elem : elems) { + li->arguments()[i++] = elem; + } + back.inst()->data().attributes()[back.idx()] = li; + } - const std::string tagname = (char*)tag; + if (state->dialect == ifcxml_dialect_ifc2x3 && state->stack.back().ntype() == stack_node::node_instance) { + if (state->stack.back().inst() != nullptr) { + state->idmap[state->stack.back().id_in_file()] = state->file->addEntity(state->stack.back().inst())->data().id(); + } + } - // ignore uos ex:iso_10303_28 (ifc2x3) and ifc:ifcXML (ifc4) - if (tagname != "uos" && tagname != "ex:iso_10303_28" && tagname != "ifc:ifcXML" && tagname != "ifcXML") { - if (state->stack.empty()) { - Logger::Error("Mismatch in parse stack due to previous errors"); - } else { - state->stack.pop_back(); - } - } + const std::string tagname = (char*)tag; + + // ignore uos ex:iso_10303_28 (ifc2x3) and ifc:ifcXML (ifc4) + if (tagname != "uos" && tagname != "ex:iso_10303_28" && tagname != "ifc:ifcXML" && tagname != "ifcXML") { + if (state->stack.empty()) { + Logger::Error("Mismatch in parse stack due to previous errors"); + } else { + state->stack.pop_back(); + } + } } static void process_characters(void* user, const xmlChar* ch, int len) { - ifcxml_parse_state* state = (ifcxml_parse_state*)user; + ifcxml_parse_state* state = (ifcxml_parse_state*)user; - if (state->file == nullptr) { - return; - } + if (state->file == nullptr) { + return; + } - std::string txt((char*) ch, len); + std::string txt((char*)ch, len); - stack_node::node_type state_type = stack_node::stack_empty; - if (!state->stack.empty()) { - state_type = state->stack.back().ntype(); - } + stack_node::node_type state_type = stack_node::stack_empty; + if (!state->stack.empty()) { + state_type = state->stack.back().ntype(); + } - if (!state->stack.empty() && state->stack.back().inst() != nullptr && state->stack.back().inst()->declaration().as_type_declaration()) { - auto pt = state->stack.back().inst()->declaration().as_type_declaration()->declared_type(); - Argument* val = nullptr; - try { - val = parse_attribute_value(pt, txt); - } catch (const std::exception& e) { - Logger::Error(e, state->stack.back().inst()); - } - if (val) { - // type declaration always at idx 0 - state->stack.back().inst()->data().setArgument(0, val); - } - } else if (state_type == stack_node::node_header_entry) { - const std::string tagname = boost::replace_all_copy(state->stack.back().tagname(), "ex:", ""); - auto& header = state->file->header(); - if (tagname == "name") { - header.file_name().name(txt); - } else if (tagname == "time_stamp") { - header.file_name().time_stamp(txt); - } else if (tagname == "author") { - header.file_name().author({ txt }); - } else if (tagname == "organization") { - header.file_name().organization({ txt }); - } else if (tagname == "preprocessor_version") { - header.file_name().preprocessor_version(txt); - } else if (tagname == "originating_system") { - header.file_name().originating_system(txt); - } else if (tagname == "authorization") { - header.file_name().authorization(txt); - } else if (tagname == "documentation") { - header.file_description().description({ txt }); - } else { - Logger::Error("Unrecognized header entry " + tagname); - } - } else if (state_type == stack_node::node_instance_attribute) { - auto pt = state->stack.back().inst()->declaration().as_entity()->attribute_by_index(state->stack.back().idx())->type_of_attribute(); - auto cpp_type = IfcUtil::from_parameter_type(pt); - if (cpp_type != IfcUtil::Argument_ENTITY_INSTANCE) { - auto val = parse_attribute_value(pt, txt); - if (val) { - state->stack.back().inst()->data().setArgument(state->stack.back().idx(), val); - } - } - } else if (state_type == stack_node::node_aggregate_element) { - auto pt = state->stack.back().aggregate_elem_type(); - auto val = parse_attribute_value(pt, txt); - if (val) { - (*(state->stack.rbegin() + 1)).aggregate_elements.push_back(val); - } - } + if (!state->stack.empty() && state->stack.back().inst() != nullptr && state->stack.back().inst()->declaration().as_type_declaration()) { + auto pt = state->stack.back().inst()->declaration().as_type_declaration()->declared_type(); + Argument* val = nullptr; + try { + val = parse_attribute_value(pt, txt); + } catch (const std::exception& e) { + Logger::Error(e, state->stack.back().inst()); + } + if (val) { + // type declaration always at idx 0 + state->stack.back().inst()->data().setArgument(0, val); + } + } else if (state_type == stack_node::node_header_entry) { + const std::string tagname = boost::replace_all_copy(state->stack.back().tagname(), "ex:", ""); + auto& header = state->file->header(); + if (tagname == "name") { + header.file_name().name(txt); + } else if (tagname == "time_stamp") { + header.file_name().time_stamp(txt); + } else if (tagname == "author") { + header.file_name().author({txt}); + } else if (tagname == "organization") { + header.file_name().organization({txt}); + } else if (tagname == "preprocessor_version") { + header.file_name().preprocessor_version(txt); + } else if (tagname == "originating_system") { + header.file_name().originating_system(txt); + } else if (tagname == "authorization") { + header.file_name().authorization(txt); + } else if (tagname == "documentation") { + header.file_description().description({txt}); + } else { + Logger::Error("Unrecognized header entry " + tagname); + } + } else if (state_type == stack_node::node_instance_attribute) { + auto pt = state->stack.back().inst()->declaration().as_entity()->attribute_by_index(state->stack.back().idx())->type_of_attribute(); + auto cpp_type = IfcUtil::from_parameter_type(pt); + if (cpp_type != IfcUtil::Argument_ENTITY_INSTANCE) { + auto val = parse_attribute_value(pt, txt); + if (val) { + state->stack.back().inst()->data().setArgument(state->stack.back().idx(), val); + } + } + } else if (state_type == stack_node::node_aggregate_element) { + auto pt = state->stack.back().aggregate_elem_type(); + auto val = parse_attribute_value(pt, txt); + if (val) { + (*(state->stack.rbegin() + 1)).aggregate_elements.push_back(val); + } + } } static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs) { - ifcxml_parse_state* state = (ifcxml_parse_state*)user; - std::string tagname = (char*) tag; + ifcxml_parse_state* state = (ifcxml_parse_state*)user; + std::string tagname = (char*)tag; #ifndef NDEBUG - std::cout << "stack:" << std::endl; - { - int i = 1; - for (auto& n : state->stack) { - std::cout << " " << (i++) << ":" << n.repr() << std::endl; - } - } - std::cout << std::string(state->stack.size(), ' ') << "<" << tagname << ">"; + std::cout << "stack:" << std::endl; + { + int i = 1; + for (auto& n : state->stack) { + std::cout << " " << (i++) << ":" << n.repr() << std::endl; + } + } + std::cout << std::string(state->stack.size(), ' ') << "<" << tagname << ">"; #endif - std::vector > attributes; + std::vector> attributes; - if (attrs) { - std::string attrname; - int i = 0; - while (attrs[i] != NULL) { - if (i % 2) { - const std::string value = (char*) attrs[i]; + if (attrs) { + std::string attrname; + int i = 0; + while (attrs[i] != NULL) { + if (i % 2) { + const std::string value = (char*)attrs[i]; #ifndef NDEBUG - std::cout << " " << attrname << "='" << value << "'"; + std::cout << " " << attrname << "='" << value << "'"; #endif - attributes.push_back(std::make_pair(attrname, value)); + attributes.push_back(std::make_pair(attrname, value)); - if ((tagname == "ifc:ifcXML" || tagname == "ifcXML") && attrname == "xsi:schemaLocation" && - ( - boost::starts_with(value, "http://www.buildingsmart-tech.org/ifcXML/IFC4") || - boost::starts_with(value, "http://www.buildingsmart-tech.org/ifc/IFC4") - ) - ) - { - // We're expecting a schemaLocation like "http://www.buildingsmart-tech.org/ifcXML/IFC4/Add2 IFC4_ADD2_TC1.xsd" - // With token compression this is split into: - // [0] http: - // [1] www.buildingsmart-tech.org - // [2] ifcXML - // [3] IFC4 - // [4] Add2 - // [5] IFC4_ADD2_TC1.xsd - // The hosstname will likely change though. + if ((tagname == "ifc:ifcXML" || tagname == "ifcXML") && attrname == "xsi:schemaLocation" && + (boost::starts_with(value, "http://www.buildingsmart-tech.org/ifcXML/IFC4") || + boost::starts_with(value, "http://www.buildingsmart-tech.org/ifc/IFC4"))) { + // We're expecting a schemaLocation like "http://www.buildingsmart-tech.org/ifcXML/IFC4/Add2 IFC4_ADD2_TC1.xsd" + // With token compression this is split into: + // [0] http: + // [1] www.buildingsmart-tech.org + // [2] ifcXML + // [3] IFC4 + // [4] Add2 + // [5] IFC4_ADD2_TC1.xsd + // The hosstname will likely change though. auto it = boost::algorithm::make_split_iterator(value, boost::algorithm::token_finder(boost::algorithm::is_any_of("/ "), boost::algorithm::token_compress_on)); - decltype(it) end; - for (int tok = 0; it != end && tok < 3; ++it, ++tok) {} - if (it != end) { - std::string schema_name(&it->front(), it->size()); - boost::to_upper(schema_name); - state->file = new IfcParse::IfcFile(IfcParse::schema_by_name(schema_name)); - state->file->parsing_complete() = false; - state->dialect = ifcxml_dialect_ifc4; - } - goto end; - } else if (tagname == "ex:iso_10303_28" && attrname == "xsi:schemaLocation" && boost::starts_with(value, "http://www.iai-tech.org/ifcXML/IFC2x3")) { - state->file = new IfcParse::IfcFile(IfcParse::schema_by_name("IFC2X3")); - state->file->parsing_complete() = false; - state->dialect = ifcxml_dialect_ifc2x3; - goto end; - } - } else { - attrname = (char*) attrs[i]; - } - i++; - } - } + decltype(it) end; + for (int tok = 0; it != end && tok < 3; ++it, ++tok) { + } + if (it != end) { + std::string schema_name(&it->front(), it->size()); + boost::to_upper(schema_name); + state->file = new IfcParse::IfcFile(IfcParse::schema_by_name(schema_name)); + state->file->parsing_complete() = false; + state->dialect = ifcxml_dialect_ifc4; + } + goto end; + } else if (tagname == "ex:iso_10303_28" && attrname == "xsi:schemaLocation" && boost::starts_with(value, "http://www.iai-tech.org/ifcXML/IFC2x3")) { + state->file = new IfcParse::IfcFile(IfcParse::schema_by_name("IFC2X3")); + state->file->parsing_complete() = false; + state->dialect = ifcxml_dialect_ifc2x3; + goto end; + } + } else { + attrname = (char*)attrs[i]; + } + i++; + } + } - if (state->file == nullptr) { - return; - } + if (state->file == nullptr) { + return; + } - { - // ifcXML id attributes are commonly numeric identifiers prefixed with 'i' (as - // XML identifiers need to start with a alphabetic character). This convention - // is not always followed, so a mapping is kept from XML string attribute to - // numeric index into the IfcParse::IfcFile. - std::string id_in_file; + { + // ifcXML id attributes are commonly numeric identifiers prefixed with 'i' (as + // XML identifiers need to start with a alphabetic character). This convention + // is not always followed, so a mapping is kept from XML string attribute to + // numeric index into the IfcParse::IfcFile. + std::string id_in_file; - // Create an attribute value from an instance. Potentially NULL in case it is a - // forward reference to an instance not yet encountered. - auto instance_to_attribute = [&state](const boost::variant& inst_or_ref, Argument*& attr, IfcUtil::IfcBaseClass*& inst) { - IfcWrite::IfcWriteArgument* wattr = new IfcWrite::IfcWriteArgument; - attr = wattr; - if (inst_or_ref.which() == 0) { - inst = nullptr; - // This attribute is NULL initially and after parsing the complete - // file populated in a subsequent step. - state->forward_references.push_back(std::make_pair((IfcWrite::IfcWriteArgument*) attr, boost::get(inst_or_ref))); - } else { - inst = boost::get(inst_or_ref); - wattr->set(inst); - } - }; + // Create an attribute value from an instance. Potentially NULL in case it is a + // forward reference to an instance not yet encountered. + auto instance_to_attribute = [&state](const boost::variant& inst_or_ref, Argument*& attr, IfcUtil::IfcBaseClass*& inst) { + IfcWrite::IfcWriteArgument* wattr = new IfcWrite::IfcWriteArgument; + attr = wattr; + if (inst_or_ref.which() == 0) { + inst = nullptr; + // This attribute is NULL initially and after parsing the complete + // file populated in a subsequent step. + state->forward_references.push_back(std::make_pair((IfcWrite::IfcWriteArgument*)attr, boost::get(inst_or_ref))); + } else { + inst = boost::get(inst_or_ref); + wattr->set(inst); + } + }; - // Create or reference an instance from the file and set attributes based on XML attributes. - auto create_instance = [&state, &attributes, &id_in_file](const IfcParse::declaration* decl) { - boost::optional id; - boost::variant rv; + // Create or reference an instance from the file and set attributes based on XML attributes. + auto create_instance = [&state, &attributes, &id_in_file](const IfcParse::declaration* decl) { + boost::optional id; + boost::variant rv; - for (auto& pair : attributes) { - if (pair.first == "id" || pair.first == "href" || pair.first == "ref") { - id = id_in_file = pair.second; - if (pair.first == "href" || pair.first == "ref") { - if (state->idmap.find(pair.second) == state->idmap.end()) { - rv = pair.second; - return rv; - } else { - rv = state->file->instance_by_id(state->idmap[pair.second]); - return rv; - } - } - } else if (pair.first == "xsi:type") { - decl = state->file->schema()->declaration_by_name(pair.second)->as_entity(); - } - } + for (auto& pair : attributes) { + if (pair.first == "id" || pair.first == "href" || pair.first == "ref") { + id = id_in_file = pair.second; + if (pair.first == "href" || pair.first == "ref") { + if (state->idmap.find(pair.second) == state->idmap.end()) { + rv = pair.second; + return rv; + } else { + rv = state->file->instance_by_id(state->idmap[pair.second]); + return rv; + } + } + } else if (pair.first == "xsi:type") { + decl = state->file->schema()->declaration_by_name(pair.second)->as_entity(); + } + } - auto untyped = new IfcEntityInstanceData(decl); - - const IfcParse::entity* entity = decl->as_entity(); - if (entity) { - for (auto& pair : attributes) { - if (pair.first == "id" || pair.first == "xsi:type" || pair.first == "pos") { - continue; - } + auto untyped = new IfcEntityInstanceData(decl); - auto idx = entity->attribute_index(pair.first); - if (idx != -1) { - auto attr = entity->attribute_by_index(idx); - auto val = parse_attribute_value(attr->type_of_attribute(), pair.second); - if (val) { - untyped->setArgument(idx, val); - } - } else { - Logger::Error("Unknown attribute '" + pair.first + "' on entity '" + entity->name() + "' with value '" + pair.second + "'"); - } - } - } + const IfcParse::entity* entity = decl->as_entity(); + if (entity) { + for (auto& pair : attributes) { + if (pair.first == "id" || pair.first == "xsi:type" || pair.first == "pos") { + continue; + } - IfcUtil::IfcBaseClass* newinst = state->file->schema()->instantiate(untyped); - - if (state->dialect == ifcxml_dialect_ifc4) { - // In IFC2X3 not added directly because attrs such as GlobalId are in - // subsequent child nodes - newinst = state->file->addEntity(newinst); - if (id) { - state->idmap[*id] = newinst->data().id(); - } - } + auto idx = entity->attribute_index(pair.first); + if (idx != -1) { + auto attr = entity->attribute_by_index(idx); + auto val = parse_attribute_value(attr->type_of_attribute(), pair.second); + if (val) { + untyped->setArgument(idx, val); + } + } else { + Logger::Error("Unknown attribute '" + pair.first + "' on entity '" + entity->name() + "' with value '" + pair.second + "'"); + } + } + } - rv = newinst; - return rv; - }; + IfcUtil::IfcBaseClass* newinst = state->file->schema()->instantiate(untyped); - stack_node::node_type state_type = stack_node::stack_empty; - if (!state->stack.empty()) { - state_type = state->stack.back().ntype(); - } + if (state->dialect == ifcxml_dialect_ifc4) { + // In IFC2X3 not added directly because attrs such as GlobalId are in + // subsequent child nodes + newinst = state->file->addEntity(newinst); + if (id) { + state->idmap[*id] = newinst->data().id(); + } + } - const std::string tagname_copy = boost::replace_all_copy(tagname, "-wrapper", ""); + rv = newinst; + return rv; + }; - if (state_type == stack_node::node_select) { - const IfcParse::declaration* decl = state->file->schema()->declaration_by_name(tagname_copy); - Argument* attr; - IfcUtil::IfcBaseClass* inst; - auto inst_ = create_instance(decl); - instance_to_attribute(inst_, attr, inst); - state->stack.back().inst()->data().setArgument(state->stack.back().idx(), attr); - state->stack.push_back(stack_node::instance(id_in_file, inst)); - } else if (state_type == stack_node::node_aggregate) { - - const IfcParse::parameter_type* attribute_type = state->stack.back().inst()->declaration().as_entity()->attribute_by_index(state->stack.back().idx())->type_of_attribute(); - follow_named(attribute_type); - const IfcParse::parameter_type* element_type = attribute_type->as_aggregation_type()->type_of_element(); - follow_named(element_type); + stack_node::node_type state_type = stack_node::stack_empty; + if (!state->stack.empty()) { + state_type = state->stack.back().ntype(); + } - int aggrpos = -1; - - /* + const std::string tagname_copy = boost::replace_all_copy(tagname, "-wrapper", ""); + + if (state_type == stack_node::node_select) { + const IfcParse::declaration* decl = state->file->schema()->declaration_by_name(tagname_copy); + Argument* attr; + IfcUtil::IfcBaseClass* inst; + auto inst_ = create_instance(decl); + instance_to_attribute(inst_, attr, inst); + state->stack.back().inst()->data().setArgument(state->stack.back().idx(), attr); + state->stack.push_back(stack_node::instance(id_in_file, inst)); + } else if (state_type == stack_node::node_aggregate) { + + const IfcParse::parameter_type* attribute_type = state->stack.back().inst()->declaration().as_entity()->attribute_by_index(state->stack.back().idx())->type_of_attribute(); + follow_named(attribute_type); + const IfcParse::parameter_type* element_type = attribute_type->as_aggregation_type()->type_of_element(); + follow_named(element_type); + + int aggrpos = -1; + + /* auto it = std::find_if(attributes.begin(), attributes.end(), [](const std::pair& p) { return p.first == "pos"; }); boost::lexical_cast(it->second); */ - if (element_type->as_simple_type()) { - state->stack.push_back(stack_node::aggregate_element(element_type, aggrpos)); - } else { - const IfcParse::declaration* decl = nullptr; - try { - decl = state->file->schema()->declaration_by_name(tagname_copy); - } catch (const std::exception& e) { - Logger::Error(e); - } - if (decl) { - auto inst_or_ref = create_instance(decl); - IfcUtil::IfcBaseClass* inst; - Argument* attr; - instance_to_attribute(inst_or_ref, attr, inst); - state->stack.back().aggregate_elements.push_back(attr); - state->stack.push_back(stack_node::instance(id_in_file, inst)); - } - } - } else if (state_type == stack_node::node_instance) { - const IfcParse::entity* current = state->stack.back().inst()->declaration().as_entity(); - if (current == nullptr) { - Logger::Error("'" + state->stack.back().inst()->declaration().name() + "' is not an entity, unable to set attribute '" + tagname + "'"); - // We need to push something on the stack. Likely there has been some extra indirection that is not understood. - state->stack.push_back(state->stack.back()); - } else { - auto idx = current->attribute_index(tagname); - if (idx == -1) { - auto inverses = current->all_inverse_attributes(); - auto found = std::find_if(inverses.begin(), inverses.end(), [&tagname](const IfcParse::inverse_attribute* attr) { - return attr->name() == tagname; - }); - if (found == inverses.end()) { - Logger::Error("Unknown attribute " + tagname); - state->stack.push_back(state->stack.back()); - } else { - if ((*found)->bound1() == 0 && (*found)->bound2() == 1) { - auto inst_or_ref = create_instance((*found)->entity_reference()); - IfcUtil::IfcBaseClass* inst; - Argument* attr; - instance_to_attribute(inst_or_ref, attr, inst); - if (inst != nullptr) { - int idx = (*found)->entity_reference()->attribute_index( - (*found)->attribute_reference() - ); - IfcWrite::IfcWriteArgument* attr_inv = new IfcWrite::IfcWriteArgument(); - attr_inv->set(state->stack.back().inst()); - inst->data().setArgument(idx, attr_inv); - state->stack.push_back(stack_node::instance(id_in_file, inst)); - } else { - Logger::Error("Unknown attribute " + tagname); - state->stack.push_back(state->stack.back()); - } - } else { - state->stack.push_back(stack_node::inverse(state->stack.back().inst(), *found)); - } - } - } else { - const IfcParse::parameter_type* attribute_type = current->attribute_by_index(idx)->type_of_attribute(); - if (state->dialect == ifcxml_dialect_ifc2x3) { - follow_named(attribute_type); - if (attribute_type->as_aggregation_type()) { - state->stack.push_back(stack_node::aggregate(state->stack.back().inst(), idx)); - } else { - state->stack.push_back(stack_node::instance_attribute(state->stack.back().inst(), idx)); - } - } else { - if (IfcUtil::from_parameter_type(attribute_type) == IfcUtil::Argument_ENTITY_INSTANCE) { - if (auto entity = attribute_type->as_named_type()->declared_type()->as_entity()) { - auto inst_or_reference = create_instance(entity); - Argument* attr; - IfcUtil::IfcBaseClass* newinst; - instance_to_attribute(inst_or_reference, attr, newinst); - state->stack.back().inst()->data().setArgument(idx, attr); - state->stack.push_back(stack_node::instance(id_in_file, newinst)); - } else if (attribute_type->as_named_type()->declared_type()->as_select_type()) { - // Select types cause an additional indirection, so the current stack node is simply repeated - state->stack.push_back(stack_node::select(state->stack.back().inst(), idx)); - } - } else if (attribute_type->as_aggregation_type()) { - state->stack.push_back(stack_node::aggregate(state->stack.back().inst(), idx)); - } - } - } - } - } else if (state->file) { - if (state_type == stack_node::node_header) { - state->stack.push_back(stack_node::header_entry(tagname)); - } else if (tagname == "ex:iso_10303_28_header" || tagname == "header") { - state->stack.push_back(stack_node::header()); - } else if (tagname == "uos") { - // intentially empty, ignored in end_element() as well - } else { - const IfcParse::declaration* decl = nullptr; - try { - decl = state->file->schema()->declaration_by_name(tagname); - } catch (const std::exception& e) { - Logger::Error(e); - } + if (element_type->as_simple_type()) { + state->stack.push_back(stack_node::aggregate_element(element_type, aggrpos)); + } else { + const IfcParse::declaration* decl = nullptr; + try { + decl = state->file->schema()->declaration_by_name(tagname_copy); + } catch (const std::exception& e) { + Logger::Error(e); + } + if (decl) { + auto inst_or_ref = create_instance(decl); + IfcUtil::IfcBaseClass* inst; + Argument* attr; + instance_to_attribute(inst_or_ref, attr, inst); + state->stack.back().aggregate_elements.push_back(attr); + state->stack.push_back(stack_node::instance(id_in_file, inst)); + } + } + } else if (state_type == stack_node::node_instance) { + const IfcParse::entity* current = state->stack.back().inst()->declaration().as_entity(); + if (current == nullptr) { + Logger::Error("'" + state->stack.back().inst()->declaration().name() + "' is not an entity, unable to set attribute '" + tagname + "'"); + // We need to push something on the stack. Likely there has been some extra indirection that is not understood. + state->stack.push_back(state->stack.back()); + } else { + auto idx = current->attribute_index(tagname); + if (idx == -1) { + auto inverses = current->all_inverse_attributes(); + auto found = std::find_if(inverses.begin(), inverses.end(), [&tagname](const IfcParse::inverse_attribute* attr) { + return attr->name() == tagname; + }); + if (found == inverses.end()) { + Logger::Error("Unknown attribute " + tagname); + state->stack.push_back(state->stack.back()); + } else { + if ((*found)->bound1() == 0 && (*found)->bound2() == 1) { + auto inst_or_ref = create_instance((*found)->entity_reference()); + IfcUtil::IfcBaseClass* inst; + Argument* attr; + instance_to_attribute(inst_or_ref, attr, inst); + if (inst != nullptr) { + int idx = (*found)->entity_reference()->attribute_index( + (*found)->attribute_reference()); + IfcWrite::IfcWriteArgument* attr_inv = new IfcWrite::IfcWriteArgument(); + attr_inv->set(state->stack.back().inst()); + inst->data().setArgument(idx, attr_inv); + state->stack.push_back(stack_node::instance(id_in_file, inst)); + } else { + Logger::Error("Unknown attribute " + tagname); + state->stack.push_back(state->stack.back()); + } + } else { + state->stack.push_back(stack_node::inverse(state->stack.back().inst(), *found)); + } + } + } else { + const IfcParse::parameter_type* attribute_type = current->attribute_by_index(idx)->type_of_attribute(); + if (state->dialect == ifcxml_dialect_ifc2x3) { + follow_named(attribute_type); + if (attribute_type->as_aggregation_type()) { + state->stack.push_back(stack_node::aggregate(state->stack.back().inst(), idx)); + } else { + state->stack.push_back(stack_node::instance_attribute(state->stack.back().inst(), idx)); + } + } else { + if (IfcUtil::from_parameter_type(attribute_type) == IfcUtil::Argument_ENTITY_INSTANCE) { + if (auto entity = attribute_type->as_named_type()->declared_type()->as_entity()) { + auto inst_or_reference = create_instance(entity); + Argument* attr; + IfcUtil::IfcBaseClass* newinst; + instance_to_attribute(inst_or_reference, attr, newinst); + state->stack.back().inst()->data().setArgument(idx, attr); + state->stack.push_back(stack_node::instance(id_in_file, newinst)); + } else if (attribute_type->as_named_type()->declared_type()->as_select_type()) { + // Select types cause an additional indirection, so the current stack node is simply repeated + state->stack.push_back(stack_node::select(state->stack.back().inst(), idx)); + } + } else if (attribute_type->as_aggregation_type()) { + state->stack.push_back(stack_node::aggregate(state->stack.back().inst(), idx)); + } + } + } + } + } else if (state->file) { + if (state_type == stack_node::node_header) { + state->stack.push_back(stack_node::header_entry(tagname)); + } else if (tagname == "ex:iso_10303_28_header" || tagname == "header") { + state->stack.push_back(stack_node::header()); + } else if (tagname == "uos") { + // intentially empty, ignored in end_element() as well + } else { + const IfcParse::declaration* decl = nullptr; + try { + decl = state->file->schema()->declaration_by_name(tagname); + } catch (const std::exception& e) { + Logger::Error(e); + } - if (!decl) { - goto end; - } + if (!decl) { + goto end; + } - const IfcParse::entity* entity = decl->as_entity(); - if (!entity && state_type != stack_node::node_instance_attribute) { - Logger::Error("Not an entity definition " + tagname); - goto end; - } + const IfcParse::entity* entity = decl->as_entity(); + if (!entity && state_type != stack_node::node_instance_attribute) { + Logger::Error("Not an entity definition " + tagname); + goto end; + } - auto inst_or_ref = create_instance(decl); - IfcUtil::IfcBaseClass* inst; - Argument* attr; - instance_to_attribute(inst_or_ref, attr, inst); + auto inst_or_ref = create_instance(decl); + IfcUtil::IfcBaseClass* inst; + Argument* attr; + instance_to_attribute(inst_or_ref, attr, inst); - if (state_type == stack_node::node_inverse) { - int idx = state->stack.back().inv_attr()->entity_reference()->attribute_index( - state->stack.back().inv_attr()->attribute_reference() - ); - IfcWrite::IfcWriteArgument* attr_inv = new IfcWrite::IfcWriteArgument(); - attr_inv->set(state->stack.back().inst()); - if (inst) { - inst->data().setArgument(idx, attr_inv); - } else { - Logger::Error("Internal error, inverse attribute not processed"); - } - } else if (state_type == stack_node::node_instance_attribute) { - state->stack.back().inst()->data().attributes()[state->stack.back().idx()] = attr; - } + if (state_type == stack_node::node_inverse) { + int idx = state->stack.back().inv_attr()->entity_reference()->attribute_index( + state->stack.back().inv_attr()->attribute_reference()); + IfcWrite::IfcWriteArgument* attr_inv = new IfcWrite::IfcWriteArgument(); + attr_inv->set(state->stack.back().inst()); + if (inst) { + inst->data().setArgument(idx, attr_inv); + } else { + Logger::Error("Internal error, inverse attribute not processed"); + } + } else if (state_type == stack_node::node_instance_attribute) { + state->stack.back().inst()->data().attributes()[state->stack.back().idx()] = attr; + } - if (entity == nullptr) { - // Type declaration, immediately populate attr 0 - state->stack.push_back(stack_node::instance_attribute(inst, 0)); - } else { - state->stack.push_back(stack_node::instance(id_in_file, inst)); - } - } - } - } + if (entity == nullptr) { + // Type declaration, immediately populate attr 0 + state->stack.push_back(stack_node::instance_attribute(inst, 0)); + } else { + state->stack.push_back(stack_node::instance(id_in_file, inst)); + } + } + } + } end: #ifndef NDEBUG - std::cout << std::endl; + std::cout << std::endl; #endif - return; + return; } #ifdef WITH_IFCXML IFC_PARSE_API IfcParse::IfcFile* IfcParse::parse_ifcxml(const std::string& filename) { - ifcxml_parse_state state; - state.file = nullptr; - state.dialect = ifcxml_dialect_unknown; - - xmlSAXHandler handler; - memset(&handler, 0, sizeof(xmlSAXHandler)); - handler.startElement = start_element; - handler.endElement = end_element; - handler.characters = process_characters; + ifcxml_parse_state state; + state.file = nullptr; + state.dialect = ifcxml_dialect_unknown; - xmlSAXUserParseFile(&handler, &state, filename.c_str()); + xmlSAXHandler handler; + memset(&handler, 0, sizeof(xmlSAXHandler)); + handler.startElement = start_element; + handler.endElement = end_element; + handler.characters = process_characters; - for (const auto& pair : state.forward_references) { - auto it = state.idmap.find(pair.second); - if (it == state.idmap.end()) { - Logger::Error("Instance with id '" + pair.second + "' not encountered"); - } else { - pair.first->set(state.file->instance_by_id(it->second)); - } - } + xmlSAXUserParseFile(&handler, &state, filename.c_str()); - if (state.file) { - state.file->parsing_complete() = true; - state.file->build_inverses(); - } + for (const auto& pair : state.forward_references) { + auto it = state.idmap.find(pair.second); + if (it == state.idmap.end()) { + Logger::Error("Instance with id '" + pair.second + "' not encountered"); + } else { + pair.first->set(state.file->instance_by_id(it->second)); + } + } - return state.file; + if (state.file) { + state.file->parsing_complete() = true; + state.file->build_inverses(); + } + + return state.file; } #endif -#endif // WITH_IFCXML \ No newline at end of file +#endif // WITH_IFCXML diff --git a/src/ifcparse/utils.h b/src/ifcparse/utils.h index dda0ecc768..e1623a8cdb 100644 --- a/src/ifcparse/utils.h +++ b/src/ifcparse/utils.h @@ -17,7 +17,7 @@ * * ********************************************************************************/ -#include "../ifcparse/ifc_parse_api.h" +#include "ifc_parse_api.h" #include @@ -26,34 +26,34 @@ namespace IfcUtil { - /// Replaces spaces and potentially other problem causing characters with underscores. - IFC_PARSE_API void sanitate_material_name(std::string &str); +/// Replaces spaces and potentially other problem causing characters with underscores. +IFC_PARSE_API void sanitate_material_name(std::string& str); - IFC_PARSE_API void escape_xml(std::string &str); - IFC_PARSE_API void unescape_xml(std::string &str); +IFC_PARSE_API void escape_xml(std::string& str); +IFC_PARSE_API void unescape_xml(std::string& str); - namespace path { +namespace path { + +IFC_PARSE_API bool delete_file(const std::string& filename); +IFC_PARSE_API bool rename_file(const std::string& old_filename, const std::string& new_filename); - IFC_PARSE_API bool delete_file(const std::string& filename); - IFC_PARSE_API bool rename_file(const std::string& old_filename, const std::string& new_filename); - #if defined(_MSC_VER) && defined(_UNICODE) - /// Uses windows.h string conversion functions - IFC_PARSE_API std::string to_utf8(const std::wstring& str); +/// Uses windows.h string conversion functions +IFC_PARSE_API std::string to_utf8(const std::wstring& str); - /// Uses windows.h string conversion functions - IFC_PARSE_API std::wstring from_utf8(const std::string& str); +/// Uses windows.h string conversion functions +IFC_PARSE_API std::wstring from_utf8(const std::string& str); #else - /// Identity operation - IFC_PARSE_API inline std::string to_utf8(const std::string& str) { return str; } +/// Identity operation +IFC_PARSE_API inline std::string to_utf8(const std::string& str) { return str; } - /// Identity operation - IFC_PARSE_API inline std::string from_utf8(const std::string& str) { return str; } +/// Identity operation +IFC_PARSE_API inline std::string from_utf8(const std::string& str) { return str; } #endif - } +} // namespace path -} +} // namespace IfcUtil #endif