diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index 3e3c7377b7..a43d9dc821 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -662,7 +662,10 @@ void ArgumentList::read(IfcSpfLexer* t, std::vector& ids) { } IfcUtil::ArgumentType ArgumentList::type() const { - if (list.empty()) return IfcUtil::Argument_UNKNOWN; + if (list.empty()) { + return IfcUtil::Argument_EMPTY_AGGREGATE; + } + const IfcUtil::ArgumentType elem_type = list[0]->type(); if (elem_type == IfcUtil::Argument_INT) { return IfcUtil::Argument_AGGREGATE_OF_INT; @@ -680,6 +683,8 @@ IfcUtil::ArgumentType ArgumentList::type() const { 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; } diff --git a/src/ifcparse/IfcUtil.cpp b/src/ifcparse/IfcUtil.cpp index a3f2a6a172..9550a9b502 100644 --- a/src/ifcparse/IfcUtil.cpp +++ b/src/ifcparse/IfcUtil.cpp @@ -1,81 +1,81 @@ -/******************************************************************************** - * * - * 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 "IfcUtil.h" -#include "../ifcparse/IfcException.h" - -#include -#include - -#include -#include - - -void IfcEntityList::push(IfcUtil::IfcBaseClass* l) { - if (l) { - ls.push_back(l); - } -} -void IfcEntityList::push(const IfcEntityList::ptr& l) { - if (l) { - for( it i = l->begin(); i != l->end(); ++i ) { - if ( *i ) ls.push_back(*i); - } - } -} -unsigned int IfcEntityList::size() const { return (unsigned int) ls.size(); } -IfcEntityList::it IfcEntityList::begin() { return ls.begin(); } -IfcEntityList::it IfcEntityList::end() { return ls.end(); } -IfcUtil::IfcBaseClass* IfcEntityList::operator[] (int i) { - return ls[i]; -} -bool IfcEntityList::contains(IfcUtil::IfcBaseClass* instance) const { - return std::find(ls.begin(), ls.end(), instance) != ls.end(); -} -void IfcEntityList::remove(IfcUtil::IfcBaseClass* instance) { - std::vector::iterator it; - while ((it = std::find(ls.begin(), ls.end(), instance)) != ls.end()) { - ls.erase(it); - } -} -IfcEntityList::ptr IfcEntityList::filtered(const std::set& entities) { - IfcEntityList::ptr return_value(new IfcEntityList); - for (it it = begin(); it != end(); ++it) { - bool contained = false; - for (std::set::const_iterator jt = entities.begin(); jt != entities.end(); ++jt) { - if ((*it)->is(*jt)) { - contained = true; - break; - } - } - if (!contained) { - return_value->push(*it); - } - } - return return_value; -} - - -unsigned int IfcUtil::IfcBaseType::getArgumentCount() const { return 1; } -Argument* IfcUtil::IfcBaseType::getArgument(unsigned int i) const { return entity->getArgument(i); } -const char* IfcUtil::IfcBaseType::getArgumentName(unsigned int i) const { if (i == 0) { return "wrappedValue"; } else { throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); } } - +/******************************************************************************** + * * + * 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 "IfcUtil.h" +#include "../ifcparse/IfcException.h" + +#include +#include + +#include +#include + + +void IfcEntityList::push(IfcUtil::IfcBaseClass* l) { + if (l) { + ls.push_back(l); + } +} +void IfcEntityList::push(const IfcEntityList::ptr& l) { + if (l) { + for( it i = l->begin(); i != l->end(); ++i ) { + if ( *i ) ls.push_back(*i); + } + } +} +unsigned int IfcEntityList::size() const { return (unsigned int) ls.size(); } +IfcEntityList::it IfcEntityList::begin() { return ls.begin(); } +IfcEntityList::it IfcEntityList::end() { return ls.end(); } +IfcUtil::IfcBaseClass* IfcEntityList::operator[] (int i) { + return ls[i]; +} +bool IfcEntityList::contains(IfcUtil::IfcBaseClass* instance) const { + return std::find(ls.begin(), ls.end(), instance) != ls.end(); +} +void IfcEntityList::remove(IfcUtil::IfcBaseClass* instance) { + std::vector::iterator it; + while ((it = std::find(ls.begin(), ls.end(), instance)) != ls.end()) { + ls.erase(it); + } +} +IfcEntityList::ptr IfcEntityList::filtered(const std::set& entities) { + IfcEntityList::ptr return_value(new IfcEntityList); + for (it it = begin(); it != end(); ++it) { + bool contained = false; + for (std::set::const_iterator jt = entities.begin(); jt != entities.end(); ++jt) { + if ((*it)->is(*jt)) { + contained = true; + break; + } + } + if (!contained) { + return_value->push(*it); + } + } + return return_value; +} + + +unsigned int IfcUtil::IfcBaseType::getArgumentCount() const { return 1; } +Argument* IfcUtil::IfcBaseType::getArgument(unsigned int i) const { return entity->getArgument(i); } +const char* IfcUtil::IfcBaseType::getArgumentName(unsigned int i) const { if (i == 0) { return "wrappedValue"; } else { throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); } } + //Note: some of these methods are overloaded in derived classes Argument::operator int() const { throw IfcParse::IfcException("Argument is not an integer"); } @@ -94,62 +94,64 @@ Argument::operator std::vector< std::vector >() const { throw IfcParse:: Argument::operator IfcEntityListList::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", - "DOUBLE", - "STRING", - "BINARY", - "ENUMERATION", - "ENTITY INSTANCE", - - "AGGREGATE OF INT", - "AGGREGATE OF DOUBLE", - "AGGREGATE OF STRING", - "AGGREGATE OF BINARY", - "AGGREGATE OF ENTITY INSTANCE", - - "AGGREGATE OF AGGREGATE OF INT", - "AGGREGATE OF AGGREGATE OF DOUBLE", - "AGGREGATE OF AGGREGATE OF ENTITY INSTANCE", - - "UNKNOWN" -}; - -const char* IfcUtil::ArgumentTypeToString(ArgumentType 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; -} - -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, "\"", """); - 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, """, "\""); - boost::replace_all(str, "'", "'"); - boost::replace_all(str, "<", "<"); - boost::replace_all(str, ">", ">"); - boost::replace_all(str, "&", "&"); -} +static const char* const argument_type_string[] = { + "NULL", + "DERIVED", + "INT", + "BOOL", + "DOUBLE", + "STRING", + "BINARY", + "ENUMERATION", + "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", + + "UNKNOWN" +}; + +const char* IfcUtil::ArgumentTypeToString(ArgumentType 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; +} + +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, "\"", """); + 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, """, "\""); + boost::replace_all(str, "'", "'"); + boost::replace_all(str, "<", "<"); + boost::replace_all(str, ">", ">"); + boost::replace_all(str, "&", "&"); +} diff --git a/src/ifcparse/IfcUtil.h b/src/ifcparse/IfcUtil.h index 0cf4810d66..13eeb4a134 100644 --- a/src/ifcparse/IfcUtil.h +++ b/src/ifcparse/IfcUtil.h @@ -61,12 +61,14 @@ namespace IfcUtil { Argument_ENUMERATION, Argument_ENTITY_INSTANCE, - Argument_AGGREGATE_OF_INT, + 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, @@ -74,6 +76,7 @@ namespace IfcUtil { Argument_UNKNOWN }; + IFC_PARSE_API const char* ArgumentTypeToString(ArgumentType argument_type); class IFC_PARSE_API IfcBaseClass { diff --git a/src/ifcparse/IfcWritableEntity.h b/src/ifcparse/IfcWritableEntity.h index c84b85110e..2ee652875d 100644 --- a/src/ifcparse/IfcWritableEntity.h +++ b/src/ifcparse/IfcWritableEntity.h @@ -65,7 +65,7 @@ namespace IfcWrite { unsigned int id(); IfcWritableEntity* isWritable(); - void setArgument(int i, Argument* a); + void setArgument(int i, Argument* a, IfcUtil::ArgumentType attr_type = IfcUtil::Argument_UNKNOWN); void setArgument(int i); void setArgumentDerived(int i); diff --git a/src/ifcparse/IfcWrite.cpp b/src/ifcparse/IfcWrite.cpp index 43fd76c8ae..fe5b8064c8 100644 --- a/src/ifcparse/IfcWrite.cpp +++ b/src/ifcparse/IfcWrite.cpp @@ -144,8 +144,10 @@ void IfcWritableEntity::setArgument(int i) { _setArgument(i, boost::none); } -void IfcWritableEntity::setArgument(int i, Argument* a) { - IfcUtil::ArgumentType attr_type = a->type(); +void IfcWritableEntity::setArgument(int i, Argument* a, IfcUtil::ArgumentType attr_type) { + if (attr_type == IfcUtil::Argument_UNKNOWN) { + attr_type = a->type(); + } switch(attr_type) { case IfcUtil::Argument_NULL: this->setArgument(i); @@ -224,14 +226,18 @@ void IfcWritableEntity::setArgument(int i, Argument* a) { } this->setArgument(i, mapped_instances); } break; + case IfcUtil::Argument_EMPTY_AGGREGATE: + case IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE: { + IfcUtil::ArgumentType t2 = IfcSchema::Type::GetAttributeType(type(), (unsigned) i); + this->setArgument(i, a, t2); } + break; default: case IfcUtil::Argument_UNKNOWN: - throw IfcParse::IfcException("Unknown argument encountered"); + throw IfcParse::IfcException(std::string("Unknown attribute encountered: '") + a->toString() + "' at index '" + boost::lexical_cast(i) + "'"); break; } } - void IfcWritableEntity::setArgumentDerived(int i) { _setArgument(i, IfcWriteArgument::Derived()); }