This commit is contained in:
Thomas Krijnen
2024-08-14 12:34:42 +02:00
parent 054ccf9a05
commit debb0f5e59
51 changed files with 947 additions and 488 deletions
+1 -1
View File
@@ -6376,7 +6376,7 @@ Ifc4::IfcPressureMeasure::operator double() const { return data_.get_attribute_v
const IfcParse::type_declaration& Ifc4::IfcPropertySetDefinitionSet::Class() { return *((IfcParse::type_declaration*)IFC4_types[738]); }
const IfcParse::type_declaration& Ifc4::IfcPropertySetDefinitionSet::declaration() const { return *((IfcParse::type_declaration*)IFC4_types[738]); }
Ifc4::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(IfcEntityInstanceData&& e) : IfcUtil::IfcBaseType(std::move(e)) { }
Ifc4::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v); }
Ifc4::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v->generalize()); }
Ifc4::IfcPropertySetDefinitionSet::operator aggregate_of< ::Ifc4::IfcPropertySetDefinition >::ptr() const { aggregate_of_instance::ptr es = data_.get_attribute_value(0); return es->as< ::Ifc4::IfcPropertySetDefinition >(); }
// Function implementations for IfcRadioActivityMeasure
+1 -1
View File
@@ -6457,7 +6457,7 @@ Ifc4x1::IfcPressureMeasure::operator double() const { return data_.get_attribute
const IfcParse::type_declaration& Ifc4x1::IfcPropertySetDefinitionSet::Class() { return *((IfcParse::type_declaration*)IFC4X1_types[759]); }
const IfcParse::type_declaration& Ifc4x1::IfcPropertySetDefinitionSet::declaration() const { return *((IfcParse::type_declaration*)IFC4X1_types[759]); }
Ifc4x1::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(IfcEntityInstanceData&& e) : IfcUtil::IfcBaseType(std::move(e)) { }
Ifc4x1::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x1::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v); }
Ifc4x1::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x1::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v->generalize()); }
Ifc4x1::IfcPropertySetDefinitionSet::operator aggregate_of< ::Ifc4x1::IfcPropertySetDefinition >::ptr() const { aggregate_of_instance::ptr es = data_.get_attribute_value(0); return es->as< ::Ifc4x1::IfcPropertySetDefinition >(); }
// Function implementations for IfcRadioActivityMeasure
+1 -1
View File
@@ -6646,7 +6646,7 @@ Ifc4x2::IfcPressureMeasure::operator double() const { return data_.get_attribute
const IfcParse::type_declaration& Ifc4x2::IfcPropertySetDefinitionSet::Class() { return *((IfcParse::type_declaration*)IFC4X2_types[774]); }
const IfcParse::type_declaration& Ifc4x2::IfcPropertySetDefinitionSet::declaration() const { return *((IfcParse::type_declaration*)IFC4X2_types[774]); }
Ifc4x2::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(IfcEntityInstanceData&& e) : IfcUtil::IfcBaseType(std::move(e)) { }
Ifc4x2::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x2::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v); }
Ifc4x2::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x2::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v->generalize()); }
Ifc4x2::IfcPropertySetDefinitionSet::operator aggregate_of< ::Ifc4x2::IfcPropertySetDefinition >::ptr() const { aggregate_of_instance::ptr es = data_.get_attribute_value(0); return es->as< ::Ifc4x2::IfcPropertySetDefinition >(); }
// Function implementations for IfcRadioActivityMeasure
+1 -1
View File
@@ -7350,7 +7350,7 @@ Ifc4x3::IfcPressureMeasure::operator double() const { return data_.get_attribute
const IfcParse::type_declaration& Ifc4x3::IfcPropertySetDefinitionSet::Class() { return *((IfcParse::type_declaration*)IFC4X3_types[826]); }
const IfcParse::type_declaration& Ifc4x3::IfcPropertySetDefinitionSet::declaration() const { return *((IfcParse::type_declaration*)IFC4X3_types[826]); }
Ifc4x3::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(IfcEntityInstanceData&& e) : IfcUtil::IfcBaseType(std::move(e)) { }
Ifc4x3::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x3::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v); }
Ifc4x3::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x3::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v->generalize()); }
Ifc4x3::IfcPropertySetDefinitionSet::operator aggregate_of< ::Ifc4x3::IfcPropertySetDefinition >::ptr() const { aggregate_of_instance::ptr es = data_.get_attribute_value(0); return es->as< ::Ifc4x3::IfcPropertySetDefinition >(); }
// Function implementations for IfcRadioActivityMeasure
+1 -1
View File
@@ -7350,7 +7350,7 @@ Ifc4x3_add1::IfcPressureMeasure::operator double() const { return data_.get_attr
const IfcParse::type_declaration& Ifc4x3_add1::IfcPropertySetDefinitionSet::Class() { return *((IfcParse::type_declaration*)IFC4X3_ADD1_types[828]); }
const IfcParse::type_declaration& Ifc4x3_add1::IfcPropertySetDefinitionSet::declaration() const { return *((IfcParse::type_declaration*)IFC4X3_ADD1_types[828]); }
Ifc4x3_add1::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(IfcEntityInstanceData&& e) : IfcUtil::IfcBaseType(std::move(e)) { }
Ifc4x3_add1::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x3_add1::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v); }
Ifc4x3_add1::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x3_add1::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v->generalize()); }
Ifc4x3_add1::IfcPropertySetDefinitionSet::operator aggregate_of< ::Ifc4x3_add1::IfcPropertySetDefinition >::ptr() const { aggregate_of_instance::ptr es = data_.get_attribute_value(0); return es->as< ::Ifc4x3_add1::IfcPropertySetDefinition >(); }
// Function implementations for IfcRadioActivityMeasure
+1 -1
View File
@@ -7350,7 +7350,7 @@ Ifc4x3_add2::IfcPressureMeasure::operator double() const { return data_.get_attr
const IfcParse::type_declaration& Ifc4x3_add2::IfcPropertySetDefinitionSet::Class() { return *((IfcParse::type_declaration*)IFC4X3_ADD2_types[828]); }
const IfcParse::type_declaration& Ifc4x3_add2::IfcPropertySetDefinitionSet::declaration() const { return *((IfcParse::type_declaration*)IFC4X3_ADD2_types[828]); }
Ifc4x3_add2::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(IfcEntityInstanceData&& e) : IfcUtil::IfcBaseType(std::move(e)) { }
Ifc4x3_add2::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x3_add2::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v); }
Ifc4x3_add2::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x3_add2::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v->generalize()); }
Ifc4x3_add2::IfcPropertySetDefinitionSet::operator aggregate_of< ::Ifc4x3_add2::IfcPropertySetDefinition >::ptr() const { aggregate_of_instance::ptr es = data_.get_attribute_value(0); return es->as< ::Ifc4x3_add2::IfcPropertySetDefinition >(); }
// Function implementations for IfcRadioActivityMeasure
+1 -1
View File
@@ -7333,7 +7333,7 @@ Ifc4x3_rc1::IfcPressureMeasure::operator double() const { return data_.get_attri
const IfcParse::type_declaration& Ifc4x3_rc1::IfcPropertySetDefinitionSet::Class() { return *((IfcParse::type_declaration*)IFC4X3_RC1_types[842]); }
const IfcParse::type_declaration& Ifc4x3_rc1::IfcPropertySetDefinitionSet::declaration() const { return *((IfcParse::type_declaration*)IFC4X3_RC1_types[842]); }
Ifc4x3_rc1::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(IfcEntityInstanceData&& e) : IfcUtil::IfcBaseType(std::move(e)) { }
Ifc4x3_rc1::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x3_rc1::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v); }
Ifc4x3_rc1::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x3_rc1::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v->generalize()); }
Ifc4x3_rc1::IfcPropertySetDefinitionSet::operator aggregate_of< ::Ifc4x3_rc1::IfcPropertySetDefinition >::ptr() const { aggregate_of_instance::ptr es = data_.get_attribute_value(0); return es->as< ::Ifc4x3_rc1::IfcPropertySetDefinition >(); }
// Function implementations for IfcRadioActivityMeasure
+1 -1
View File
@@ -7416,7 +7416,7 @@ Ifc4x3_rc2::IfcPressureMeasure::operator double() const { return data_.get_attri
const IfcParse::type_declaration& Ifc4x3_rc2::IfcPropertySetDefinitionSet::Class() { return *((IfcParse::type_declaration*)IFC4X3_RC2_types[849]); }
const IfcParse::type_declaration& Ifc4x3_rc2::IfcPropertySetDefinitionSet::declaration() const { return *((IfcParse::type_declaration*)IFC4X3_RC2_types[849]); }
Ifc4x3_rc2::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(IfcEntityInstanceData&& e) : IfcUtil::IfcBaseType(std::move(e)) { }
Ifc4x3_rc2::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x3_rc2::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v); }
Ifc4x3_rc2::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x3_rc2::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v->generalize()); }
Ifc4x3_rc2::IfcPropertySetDefinitionSet::operator aggregate_of< ::Ifc4x3_rc2::IfcPropertySetDefinition >::ptr() const { aggregate_of_instance::ptr es = data_.get_attribute_value(0); return es->as< ::Ifc4x3_rc2::IfcPropertySetDefinition >(); }
// Function implementations for IfcRadioActivityMeasure
+1 -1
View File
@@ -7437,7 +7437,7 @@ Ifc4x3_rc3::IfcPressureMeasure::operator double() const { return data_.get_attri
const IfcParse::type_declaration& Ifc4x3_rc3::IfcPropertySetDefinitionSet::Class() { return *((IfcParse::type_declaration*)IFC4X3_RC3_types[836]); }
const IfcParse::type_declaration& Ifc4x3_rc3::IfcPropertySetDefinitionSet::declaration() const { return *((IfcParse::type_declaration*)IFC4X3_RC3_types[836]); }
Ifc4x3_rc3::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(IfcEntityInstanceData&& e) : IfcUtil::IfcBaseType(std::move(e)) { }
Ifc4x3_rc3::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x3_rc3::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v); }
Ifc4x3_rc3::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x3_rc3::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v->generalize()); }
Ifc4x3_rc3::IfcPropertySetDefinitionSet::operator aggregate_of< ::Ifc4x3_rc3::IfcPropertySetDefinition >::ptr() const { aggregate_of_instance::ptr es = data_.get_attribute_value(0); return es->as< ::Ifc4x3_rc3::IfcPropertySetDefinition >(); }
// Function implementations for IfcRadioActivityMeasure
+1 -1
View File
@@ -7437,7 +7437,7 @@ Ifc4x3_rc4::IfcPressureMeasure::operator double() const { return data_.get_attri
const IfcParse::type_declaration& Ifc4x3_rc4::IfcPropertySetDefinitionSet::Class() { return *((IfcParse::type_declaration*)IFC4X3_RC4_types[834]); }
const IfcParse::type_declaration& Ifc4x3_rc4::IfcPropertySetDefinitionSet::declaration() const { return *((IfcParse::type_declaration*)IFC4X3_RC4_types[834]); }
Ifc4x3_rc4::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(IfcEntityInstanceData&& e) : IfcUtil::IfcBaseType(std::move(e)) { }
Ifc4x3_rc4::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x3_rc4::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v); }
Ifc4x3_rc4::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x3_rc4::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v->generalize()); }
Ifc4x3_rc4::IfcPropertySetDefinitionSet::operator aggregate_of< ::Ifc4x3_rc4::IfcPropertySetDefinition >::ptr() const { aggregate_of_instance::ptr es = data_.get_attribute_value(0); return es->as< ::Ifc4x3_rc4::IfcPropertySetDefinition >(); }
// Function implementations for IfcRadioActivityMeasure
+1 -1
View File
@@ -7350,7 +7350,7 @@ Ifc4x3_tc1::IfcPressureMeasure::operator double() const { return data_.get_attri
const IfcParse::type_declaration& Ifc4x3_tc1::IfcPropertySetDefinitionSet::Class() { return *((IfcParse::type_declaration*)IFC4X3_TC1_types[826]); }
const IfcParse::type_declaration& Ifc4x3_tc1::IfcPropertySetDefinitionSet::declaration() const { return *((IfcParse::type_declaration*)IFC4X3_TC1_types[826]); }
Ifc4x3_tc1::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(IfcEntityInstanceData&& e) : IfcUtil::IfcBaseType(std::move(e)) { }
Ifc4x3_tc1::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x3_tc1::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v); }
Ifc4x3_tc1::IfcPropertySetDefinitionSet::IfcPropertySetDefinitionSet(aggregate_of< ::Ifc4x3_tc1::IfcPropertySetDefinition >::ptr v) : IfcUtil::IfcBaseType() { set_attribute_value(0, v->generalize()); }
Ifc4x3_tc1::IfcPropertySetDefinitionSet::operator aggregate_of< ::Ifc4x3_tc1::IfcPropertySetDefinition >::ptr() const { aggregate_of_instance::ptr es = data_.get_attribute_value(0); return es->as< ::Ifc4x3_tc1::IfcPropertySetDefinition >(); }
// Function implementations for IfcRadioActivityMeasure
+7 -4
View File
@@ -88,7 +88,6 @@ class IFC_PARSE_API IfcBaseInterface {
class IFC_PARSE_API IfcBaseClass : public virtual IfcBaseInterface {
protected:
uint32_t identity_;
uint32_t id_;
static std::atomic_uint32_t counter_;
IfcEntityInstanceData data_;
@@ -98,10 +97,15 @@ class IFC_PARSE_API IfcBaseClass : public virtual IfcBaseInterface {
}
public:
uint32_t id_;
IfcParse::IfcFile* file_;
IfcBaseClass(IfcEntityInstanceData&& data) : identity_(counter_++),
data_(std::move(data)) {}
IfcBaseClass(IfcEntityInstanceData&& data)
: identity_(counter_++)
, data_(std::move(data))
, id_(0)
, file_(nullptr)
{}
const IfcEntityInstanceData& data() const { return data_; }
IfcEntityInstanceData& data() { return data_; }
@@ -120,7 +124,6 @@ class IFC_PARSE_API IfcBaseClass : public virtual IfcBaseInterface {
uint32_t id() const { return id_; }
std::string toString(bool upper = false) const;
void toString(std::ostream&, bool upper = false) const;
};
+124
View File
@@ -0,0 +1,124 @@
#include "IfcEntityInstanceData.h"
#include "IfcBaseClass.h"
// @todo is size() still needed?
class SizeVisitor {
public:
typedef int result_type;
int operator()(const Blank& /*i*/) const { return -1; }
int operator()(const 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 empty_aggregate_t&) const { return 0; }
int operator()(const empty_aggregate_of_aggregate_t&) const { return 0; }
int operator()(const std::vector<int>& i) const { return (int)i.size(); }
int operator()(const std::vector<double>& i) const { return (int)i.size(); }
int operator()(const std::vector<std::vector<int>>& i) const { return (int)i.size(); }
int operator()(const std::vector<std::vector<double>>& i) const { return (int)i.size(); }
int operator()(const std::vector<std::string>& i) const { return (int)i.size(); }
int operator()(const std::vector<boost::dynamic_bitset<>>& i) const { return (int)i.size(); }
int operator()(const 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(); }
};
AttributeValue::operator int() const
{
return array_->get<int>(index_);
}
AttributeValue::operator bool() const
{
return array_->get<bool>(index_);
}
AttributeValue::operator double() const
{
return array_->get<double>(index_);
}
AttributeValue::operator boost::logic::tribool() const
{
return array_->get<boost::logic::tribool>(index_);
}
AttributeValue::operator std::string() const
{
if (array_->has<EnumerationReference>(index_)) {
// @todo this is silly, but the way things currently work,
// @todo also we don't really need to store a reference to the enumeration type, when this same type is already stored on the definition of the entity and no other value can be provided.
return array_->get<EnumerationReference>(index_).value();
}
return array_->get<std::string>(index_);
}
AttributeValue::operator boost::dynamic_bitset<>() const
{
return array_->get<boost::dynamic_bitset<>>(index_);
}
AttributeValue::operator IfcUtil::IfcBaseClass* () const
{
return array_->get<IfcUtil::IfcBaseClass*>(index_);
}
AttributeValue::operator std::vector<int>() const
{
return array_->get<std::vector<int>>(index_);
}
AttributeValue::operator std::vector<double>() const
{
return array_->get<std::vector<double>>(index_);
}
AttributeValue::operator std::vector<std::string>() const
{
return array_->get<std::vector<std::string>>(index_);
}
AttributeValue::operator std::vector<boost::dynamic_bitset<>>() const
{
return array_->get<std::vector<boost::dynamic_bitset<>>>(index_);
}
AttributeValue::operator boost::shared_ptr<aggregate_of_instance>() const
{
return array_->get<boost::shared_ptr<aggregate_of_instance>>(index_);
}
AttributeValue::operator std::vector<std::vector<int>>() const
{
return array_->get<std::vector<std::vector<int>>>(index_);
}
AttributeValue::operator std::vector<std::vector<double>>() const
{
return array_->get<std::vector<std::vector<double>>>(index_);
}
AttributeValue::operator boost::shared_ptr<aggregate_of_aggregate_of_instance>() const
{
return array_->get<boost::shared_ptr<aggregate_of_aggregate_of_instance>>(index_);
}
bool AttributeValue::isNull() const
{
return array_->has<Blank>(index_);
}
unsigned int AttributeValue::size() const
{
return array_->apply_visitor(SizeVisitor{}, index_);
}
IfcUtil::ArgumentType AttributeValue::type() const
{
return static_cast<IfcUtil::ArgumentType>(array_->index(index_));
}
+19 -9
View File
@@ -23,9 +23,12 @@
#include "ArgumentType.h"
#include "variantarray.h"
#include "aggregate_of_instance.h"
#include "IfcSchema.h"
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/logic/tribool.hpp>
#include <boost/dynamic_bitset.hpp>
class EnumerationReference {
private:
@@ -112,19 +115,22 @@ typedef VariantArray <
aggregate_of_aggregate_of_instance::ptr
> storage_t;
struct MutableAttributeValue {
int name_;
uint8_t index_;
};
// short lived
class AttributeValue {
private:
storage_t* array_;
struct AttributeValue {
const storage_t* array_;
uint8_t index_;
public:
AttributeValue()
: array_(nullptr)
, index_(0)
{}
AttributeValue(storage_t* arr, uint8_t index)
AttributeValue(const storage_t* arr, uint8_t index)
: array_(arr)
, index_(index)
{}
@@ -151,7 +157,6 @@ public:
unsigned int size() const;
IfcUtil::ArgumentType type() const;
// AttributeValue* operator[](unsigned int index) const = 0;
};
class IFC_PARSE_API IfcEntityInstanceData {
@@ -164,6 +169,13 @@ class IFC_PARSE_API IfcEntityInstanceData {
IfcEntityInstanceData(const IfcEntityInstanceData& data);
IfcEntityInstanceData& operator=(IfcEntityInstanceData&& other) {
if (this != &other) {
storage_ = std::move(other.storage_);
}
return *this;
}
AttributeValue get_attribute_value(size_t index) const;
/*
@@ -177,9 +189,7 @@ class IFC_PARSE_API IfcEntityInstanceData {
return storage_.size();
}
// @todo can no longer work because we don't have access to type anymore to lookup derived
std::string toString(bool upper = false) const;
void toString(std::ostream&, bool upper = false) const;
void toString(std::ostream&, bool upper = false, const IfcParse::entity* ent = nullptr) const;
};
#endif
+322
View File
@@ -0,0 +1,322 @@
#include "IfcFile.h"
IfcParse::parse_context::~parse_context() {
for (auto& t : tokens_) {
boost::apply_visitor([](auto& v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, parse_context*>) {
delete v;
}
}, t);
}
}
IfcParse::parse_context& IfcParse::parse_context::push() {
auto* pc = new IfcParse::parse_context;
tokens_.push_back(pc);
return *pc;
}
void IfcParse::parse_context::push(Token t) {
tokens_.push_back(t);
}
void IfcParse::parse_context::push(IfcUtil::IfcBaseClass* inst) {
tokens_.push_back(inst);
}
namespace {
// Define a template to check if a type is in a boost::variant
template<typename Variant, typename T>
struct is_type_in_variant;
// Specialization for boost::variant
template<typename T, typename... Types>
struct is_type_in_variant<boost::variant<Types...>, T>
{
// Recursive template to check if T is one of Types
static constexpr bool value = (std::is_same<T, Types>::value || ...);
};
// Helper variable template (C++14 and beyond)
template<typename Variant, typename T>
constexpr bool is_type_in_variant_v = is_type_in_variant<Variant, T>::value;
IfcUtil::ArgumentType get_element_type(IfcUtil::ArgumentType aggregate) {
switch (aggregate) {
case IfcUtil::Argument_AGGREGATE_OF_INT:
return IfcUtil::Argument_INT;
case IfcUtil::Argument_AGGREGATE_OF_DOUBLE:
return IfcUtil::Argument_DOUBLE;
case IfcUtil::Argument_AGGREGATE_OF_STRING:
return IfcUtil::Argument_STRING;
case IfcUtil::Argument_AGGREGATE_OF_BINARY:
return IfcUtil::Argument_BINARY;
case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE:
return IfcUtil::Argument_ENTITY_INSTANCE;
case IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE:
return IfcUtil::Argument_EMPTY_AGGREGATE;
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT:
return IfcUtil::Argument_AGGREGATE_OF_INT;
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE:
return IfcUtil::Argument_AGGREGATE_OF_DOUBLE;
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE:
return IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE;
default:
return IfcUtil::Argument_UNKNOWN;
}
}
bool can_coerce(IfcUtil::ArgumentType target, IfcUtil::ArgumentType source) {
if (source == IfcUtil::Argument_EMPTY_AGGREGATE) {
return target == IfcUtil::Argument_AGGREGATE_OF_INT ||
target == IfcUtil::Argument_AGGREGATE_OF_DOUBLE ||
target == IfcUtil::Argument_AGGREGATE_OF_STRING ||
target == IfcUtil::Argument_AGGREGATE_OF_BINARY ||
target == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE ||
target == IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE ||
target == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT ||
target == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE ||
target == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE;
} else if (source == IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE) {
return target == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT ||
target == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE ||
target == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE;
} else if (source == IfcUtil::Argument_BOOL && target == IfcUtil::Argument_LOGICAL) {
return true;
} else {
// @todo make it configurable to coerce int to double, which is not standard compliant?
auto elt = get_element_type(target);
auto els = get_element_type(source);
if (elt != IfcUtil::Argument_UNKNOWN && els != IfcUtil::Argument_UNKNOWN) {
return can_coerce(elt, els);
}
return false;
}
}
// we need to have a compatibility between (#123, IfcLengthMeasure(123.))
// which are different token kinds
void get_token_type(std::vector<uint8_t>& r, const boost::variant<IfcUtil::IfcBaseClass*,IfcParse::Token, IfcParse::parse_context*>& v) {
r.push_back((uint8_t)v.which());
if (v.which() == 0) {
// pass
} else if (v.which() == 1) {
r.push_back((uint8_t)boost::get<IfcParse::Token>(v).type);
} else if (v.which() == 2) {
// @todo check for empty aggregate
get_token_type(r, boost::get<IfcParse::parse_context*>(v)->tokens_.front());
}
}
bool can_coerce(const std::vector<uint8_t>& target, const std::vector<uint8_t>& source) {
if (target == std::vector<uint8_t>{0, 0} && source == std::vector<uint8_t>{1, IfcParse::Token_IDENTIFIER}) {
return true;
}
if (source == std::vector<uint8_t>{0, 0} && target == std::vector<uint8_t>{1, IfcParse::Token_IDENTIFIER}) {
return true;
}
return source == target;
}
struct InstanceReference {
int v;
operator int() const {
return v;
}
};
template <typename Fn>
void dispatch_token(IfcParse::Token t, IfcParse::declaration* decl, Fn fn) {
if (t.type == IfcParse::Token_BINARY) {
fn(IfcParse::TokenFunc::asBinary(t));
} else if (t.type == IfcParse::Token_BOOL) {
fn(IfcParse::TokenFunc::asBool(t));
} else if (t.type == IfcParse::Token_ENUMERATION) {
if (decl->as_enumeration_type()) {
fn(EnumerationReference(decl->as_enumeration_type(), decl->as_enumeration_type()->lookup_enum_offset(IfcParse::TokenFunc::asStringRef(t))));
}
} else if (t.type == IfcParse::Token_FLOAT) {
fn(IfcParse::TokenFunc::asFloat(t));
} else if (t.type == IfcParse::Token_IDENTIFIER) {
fn(InstanceReference{ IfcParse::TokenFunc::asIdentifier(t) });
} else if (t.type == IfcParse::Token_INT) {
fn(IfcParse::TokenFunc::asInt(t));
} else if (t.type == IfcParse::Token_STRING) {
fn(IfcParse::TokenFunc::asStringRef(t));
}
}
template <typename Fn>
void construct_(IfcParse::parse_context& p, Fn fn) {
if (p.tokens_.empty()) {
// @todo based on type create appropate empty aggregate
return;
}
decltype(p.tokens_) p_tokens_filtered;
std::vector<uint8_t> first_type;
get_token_type(first_type, p.tokens_.front());
std::copy_if(
p.tokens_.begin(),
p.tokens_.end(),
std::back_inserter(p_tokens_filtered),
[first_type](auto& x) {
std::vector<uint8_t> nth_type;
get_token_type(nth_type, x);
return can_coerce(first_type, nth_type);
}
);
if (p.tokens_.size() != p_tokens_filtered.size()) {
// warning
}
typedef boost::variant<
Blank,
std::vector<int>,
std::vector<double>,
std::vector<std::string>,
std::vector<boost::dynamic_bitset<>>,
std::vector<IfcParse::reference_or_simple_type>,
std::vector<std::vector<int>>,
std::vector<std::vector<double>>,
std::vector<std::vector<IfcParse::reference_or_simple_type>>
> possible_aggregation_types_t;
possible_aggregation_types_t aggregate_storage;
for (auto& t : p_tokens_filtered) {
boost::apply_visitor([&aggregate_storage](auto& v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::Token>) {
// @todo get aggregate of enumeration
dispatch_token(v, nullptr, [&aggregate_storage](auto v) {
if constexpr (std::is_same_v<decltype(v), InstanceReference>) {
if (aggregate_storage.which() == 0) {
aggregate_storage = std::vector<IfcParse::reference_or_simple_type>{ v };
} else {
boost::get< std::vector<IfcParse::reference_or_simple_type>>(aggregate_storage).push_back(v);
}
} else if constexpr (is_type_in_variant_v<possible_aggregation_types_t, std::vector<std::decay_t<decltype(v)>>>) {
if (aggregate_storage.which() == 0) {
aggregate_storage = std::vector<std::decay_t<decltype(v)>>{ v };
} else {
boost::get< std::vector<std::decay_t<decltype(v)>>>(aggregate_storage).push_back(v);
}
}
});
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::parse_context*>) {
/*construct_(*v, [&aggregate_storage](auto& v) {
if (aggregate_storage.which() == 0) {
aggregate_storage = std::vector<std::decay_t<decltype(v)>>{ v };
} else {
boost::get<std::vector<std::decay_t<decltype(v)>>>(aggregate_storage).push_back(v);
}
});*/
// Too deeply nested list
} else {
if (aggregate_storage.which() == 0) {
aggregate_storage = std::vector<IfcParse::reference_or_simple_type>{ v };
} else {
boost::get<std::vector<IfcParse::reference_or_simple_type>>(aggregate_storage).push_back(v);
}
}
}, t);
}
boost::apply_visitor(fn, aggregate_storage);
}
}
IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl) {
std::vector<const IfcParse::parameter_type*> parameter_types;
if (decl && decl->as_type_declaration()) {
parameter_types = { decl->as_type_declaration()->declared_type() };
} else if (decl && decl->as_entity()) {
auto entity_attrs = decl->as_entity()->all_attributes();
std::transform(
entity_attrs.begin(),
entity_attrs.end(),
std::back_inserter(parameter_types),
[](auto* attr) {
return attr->type_of_attribute();
}
);
}
std::vector<IfcUtil::ArgumentType> attr_types;
std::transform(
parameter_types.begin(),
parameter_types.end(),
std::back_inserter(attr_types),
IfcUtil::from_parameter_type
);
if (decl && (tokens_.size() != attr_types.size())) {
// warning
}
if (tokens_.size() == 0) {
return IfcEntityInstanceData(storage_t(0));
}
storage_t storage(decl
? (std::min)(attr_types.size(), tokens_.size())
: tokens_.size()
);
auto it = tokens_.begin();
auto jt = attr_types.begin();
auto kt = parameter_types.begin();
for (; it != tokens_.end() && (!decl || jt != attr_types.end()); ++it) {
auto& token = *it;
// @todo coerce to expected type, e.g empty -> std::vector<int>, bool -> logical
// auto& attr_type = *jt;
const IfcParse::parameter_type* param_type = nullptr;
if (decl) {
param_type = *kt;
}
auto index = (uint8_t) std::distance(tokens_.begin(), it);
boost::apply_visitor([this, &storage, name, &references_to_resolve, index, it, param_type](auto& v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::Token>) {
dispatch_token(v, param_type && param_type->as_named_type() ? param_type->as_named_type()->declared_type() : nullptr, [this, &storage, name, &references_to_resolve, index](auto v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, InstanceReference>) {
references_to_resolve.push_back(std::make_pair(
// @todo previously this was storage but apparently the
// pointer is not constant with the moving and temporary nature
// maybe it ought to be and in that case a pointer is more direct
MutableAttributeValue{ name, index },
unresolved_references::value_type::second_type{v}
));
} else {
storage.set(index, v);
}
});
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::parse_context*>) {
construct_(*v, [this, &storage, name, &references_to_resolve, index](auto& v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<reference_or_simple_type>>) {
references_to_resolve.push_back({ {name, index }, v });
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<std::vector<reference_or_simple_type>>>) {
references_to_resolve.push_back({ {name, index }, v });
} else {
storage.set(index, v);
}
});
} else {
storage.set(index, v);
}
}, token);
if (decl) {
++jt, ++kt;
}
}
return IfcEntityInstanceData(std::move(storage));
}
+20 -58
View File
@@ -65,79 +65,41 @@ class IFC_PARSE_API file_open_status {
}
};
typedef boost::variant<int, IfcUtil::IfcBaseClass*> reference_or_simple_type;
typedef std::list<std::pair<MutableAttributeValue, boost::variant<reference_or_simple_type, std::vector<reference_or_simple_type>, std::vector<std::vector<reference_or_simple_type>>>>> unresolved_references;
struct parse_context {
boost::variant<
Blank,
storage_t, // IFCWALL(x)
std::vector<Token>, // IFCCARTESIANPOINT((x, y, z))
std::vector<IfcUtil::IfcBaseClass*>, // IFCCARTESIANPOINT((IFCTEXT(), IFCTEXT()))
std::list<parse_context> // IFCCARTESIANPOINTLIST3D(((x, y, z), (q, r, s)))
> tokens;
std::list<
boost::variant<
IfcUtil::IfcBaseClass*,
Token,
parse_context*
>> tokens_;
parse_context() {};
~parse_context();
parse_context(const parse_context&) = delete;
parse_context& operator=(const parse_context&) = delete;
parse_context()
: tokens(Blank{})
{}
parse_context(parse_context&&) = default;
parse_context& operator=(parse_context&&) = default;
parse_context(storage_t&& instance_attribute_storage)
: tokens(std::move(instance_attribute_storage))
{}
parse_context& push();
parse_context& push() {
if (tokens.which() == 0) {
// tokens = std::vector<Token>{};
throw std::runtime_error("d");
} else if (tokens.which() == 1) {
throw std::runtime_error("e");
} else if (tokens.which() == 2) {
throw std::runtime_error("e");
} else if (tokens.which() == 3) {
if (boost::get<std::vector<Token>>(tokens).size() == 0) {
tokens = std::list<parse_context>{};
return push();
} else {
throw std::runtime_error("b");
}
} else if (tokens.which() == 4) {
boost::get<std::list<parse_context>>(tokens).emplace_back();
return boost::get<std::list<parse_context>>(tokens).back();
}
}
void push(Token t);
void push(Token t) {
if (tokens.which() == 1) {
boost::get<std::vector<Token>>(tokens).push_back(t);
} else if (tokens.which() == 3) {
boost::get<std::list<parse_context>>(tokens).back().push(t);
} else {
throw std::runtime_error("a");
}
}
void push(IfcUtil::IfcBaseClass* inst);
void push(IfcUtil::IfcBaseClass* inst) {
if (tokens.which() == 2) {
boost::get<std::vector<IfcUtil::IfcBaseClass*>>(tokens).push_back(inst);
} else if (tokens.which() == 3) {
boost::get<std::list<parse_context>>(tokens).back().push(inst);
} else {
throw std::runtime_error("a");
}
}
void pop() {
}
storage_t&& data() {
return std::move(boost::get<storage_t>(tokens));
}
IfcEntityInstanceData construct(int name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl);
};
/// 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:
unresolved_references references_to_resolve;
typedef std::map<const IfcParse::declaration*, aggregate_of_instance::ptr> entities_by_type_t;
typedef boost::unordered_map<unsigned int, IfcUtil::IfcBaseClass*> entity_by_id_t;
typedef boost::unordered_map<uint32_t, IfcUtil::IfcBaseClass*> entity_by_iden_t;
+9 -3
View File
@@ -70,7 +70,9 @@ void plain_text_message(T& out, const boost::optional<const IfcUtil::IfcBaseClas
}
out << message.c_str() << std::endl;
if (instance) {
std::string instance_string = instance->data().toString();
std::ostringstream oss;
instance->as<IfcUtil::IfcBaseClass>()->toString(oss);
auto instance_string = oss.str();
if (instance_string.size() > 259) {
instance_string = instance_string.substr(0, 256) + "...";
}
@@ -98,11 +100,15 @@ void json_message(T& out, const boost::optional<const IfcUtil::IfcBaseClass*>& c
property_tree.put(level_string, severity_strings<typename T::char_type>::value[type]);
if (current_product) {
property_tree.put(product_string, string_as<typename T::char_type>((**current_product).data().toString()));
std::ostringstream oss;
(*current_product)->toString(oss);
property_tree.put(product_string, string_as<typename T::char_type>(oss.str()));
}
property_tree.put(message_string, string_as<typename T::char_type>(message));
if (instance) {
property_tree.put(instance_string, string_as<typename T::char_type>(instance->data().toString()));
std::ostringstream oss;
instance->as<IfcUtil::IfcBaseClass>()->toString(oss);
property_tree.put(instance_string, string_as<typename T::char_type>(oss.str()));
}
property_tree.put(time_string, string_as<typename T::char_type>(get_time()));
+137 -188
View File
@@ -366,10 +366,14 @@ Token IfcSpfLexer::Next() {
decoder_->skip();
}
}
Token t;
if (len != 0) {
return GeneralTokenPtr(this, pos, stream->Tell());
t = GeneralTokenPtr(this, pos, stream->Tell());
} else {
t = NoneTokenPtr();
}
return NoneTokenPtr();
// std::wcout << "token: " << pos << " " << TokenFunc::asStringRef(t).c_str() << std::endl;
return t;
}
bool IfcSpfStream::is_eof_at(unsigned int local_ptr) {
@@ -685,6 +689,10 @@ std::string TokenFunc::toString(const Token& token) {
void IfcParse::IfcFile::load(unsigned entity_instance_name, const IfcParse::entity* entity, parse_context& context, int attribute_index) {
Token next = tokens->Next();
if (TokenFunc::isOperator(next, '(')) {
next = tokens->Next();
}
/*
std::vector<Argument*>* vector = 0;
vector_or_array<Argument*> filler(attributes, num_attributes);
@@ -711,7 +719,7 @@ void IfcParse::IfcFile::load(unsigned entity_instance_name, const IfcParse::enti
while ((next.startPos != 0U) || (next.lexer != nullptr)) {
if (TokenFunc::isOperator(next, ',')) {
if (attribute_index == 0) {
if (attribute_index == -1) {
attribute_index_within_data += 1;
}
} else if (TokenFunc::isOperator(next, ')')) {
@@ -722,17 +730,17 @@ void IfcParse::IfcFile::load(unsigned entity_instance_name, const IfcParse::enti
} else {
return_value++;
if (TokenFunc::isIdentifier(next)) {
// register_inverse(entity_instance_name, entity, next, attribute_index == -1 ? attribute_index_within_data : attribute_index);
register_inverse(entity_instance_name, entity, next, attribute_index == -1 ? attribute_index_within_data : attribute_index);
}
if (TokenFunc::isKeyword(next)) {
try {
parse_context ps(storage_t(1));
parse_context ps;
load(0, nullptr, ps, -1);
IfcParse::schema_definition* schema;
auto* simple_type_instance = schema->instantiate(TokenFunc::asStringRef(next), IfcEntityInstanceData(ps.data()));
auto* simple_type_instance = schema_->instantiate(TokenFunc::asStringRef(next), ps.construct(-1, references_to_resolve, schema_->declaration_by_name(TokenFunc::asStringRef(next))));
//@todo decide addEntity(((IfcUtil::IfcBaseClass*)*entity));
context.push(simple_type_instance);
simple_type_instance->file_ = this;
} catch (IfcException& e) {
Logger::Message(Logger::LOG_ERROR, e.what());
// #4070 We didn't actually capture an aggregate entry, undo length increment.
@@ -744,103 +752,24 @@ void IfcParse::IfcFile::load(unsigned entity_instance_name, const IfcParse::enti
}
next = tokens->Next();
}
/*
if (vector != nullptr) {
// Obviously don't try and create a 0-length array.
if ((num_attributes != 0U) || !vector->empty()) {
// @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();
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;
}
}
return return_value;
*/
}
// templated helper function for reading arguments into a list
template <typename T>
std::vector<T> read_aggregate_as_vector(const std::vector<Token>& tokens) {
std::vector<T> return_value;
return_value.reserve(tokens.size());
for (size_t i = 0; i < tokens.size(); ++i) {
return_value.push_back(tokens[i]);
}
return return_value;
}
template <typename T>
std::vector<std::vector<T>> read_aggregate_of_aggregate_as_vector2(const std::vector<parse_context>& tokens) {
std::vector<std::vector<T>> return_value;
return_value.reserve(tokens.size());
for (size_t i = 0; i < tokens.size(); ++i) {
return_value.push_back(read_aggregate_as_vector<T>(boost::get< std::vector<Token>>(tokens[i].tokens)));
}
return return_value;
}
/*
IfcUtil::ArgumentType TokenArgument::type() const {
if (TokenFunc::isInt(token)) {
return IfcUtil::Argument_INT;
}
if (TokenFunc::isBool(token)) {
return IfcUtil::Argument_BOOL;
}
if (TokenFunc::isLogical(token)) {
return IfcUtil::Argument_LOGICAL;
}
if (TokenFunc::isFloat(token)) {
return IfcUtil::Argument_DOUBLE;
}
if (TokenFunc::isString(token)) {
return IfcUtil::Argument_STRING;
}
if (TokenFunc::isEnumeration(token)) {
return IfcUtil::Argument_ENUMERATION;
}
if (TokenFunc::isIdentifier(token)) {
return IfcUtil::Argument_ENTITY_INSTANCE;
}
if (TokenFunc::isBinary(token)) {
return IfcUtil::Argument_BINARY;
}
if (TokenFunc::isOperator(token, '$')) {
return IfcUtil::Argument_NULL;
}
if (TokenFunc::isOperator(token, '*')) {
return IfcUtil::Argument_DERIVED;
}
return IfcUtil::Argument_UNKNOWN;
}
*/
//
// Reads an Entity from the list of Tokens at the specified offset in the file
//
IfcEntityInstanceData&& IfcParse::read(unsigned int i, IfcFile* f) {
IfcEntityInstanceData IfcParse::read(unsigned int i, IfcFile* f) {
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));
parse_context pc(storage_t((uint8_t) ty->as_entity()->all_attributes().size()));
parse_context pc;
f->load(i, ty->as_entity(), pc, -1);
return IfcEntityInstanceData(pc.data());
return IfcEntityInstanceData(pc.construct(i, f->references_to_resolve, ty));
/*std::ostringstream oss;
d.toString(oss);
auto osss = oss.str();
std::wcout << osss.c_str() << std::endl;*/
}
void IfcParse::IfcFile::try_read_semicolon() {
@@ -900,7 +829,7 @@ namespace {
StringBuilderVisitor(const StringBuilderVisitor&); //N/A
StringBuilderVisitor& operator=(const StringBuilderVisitor&); //N/A
std::ostringstream& data_;
std::ostream& data_;
template <typename T>
void serialize(const std::vector<T>& i) {
data_ << "(";
@@ -961,7 +890,7 @@ namespace {
bool upper_;
public:
StringBuilderVisitor(std::ostringstream& stream, bool upper = false)
StringBuilderVisitor(std::ostream& stream, bool upper = false)
: data_(stream),
upper_(upper) {}
void operator()(const Blank& /*i*/) { data_ << "$"; }
@@ -1024,7 +953,6 @@ namespace {
}
void operator()(const empty_aggregate_t&) const { data_ << "()"; }
void operator()(const empty_aggregate_of_aggregate_t&) const { data_ << "()"; }
operator std::string() { return data_.str(); }
};
template <>
@@ -1094,8 +1022,7 @@ namespace {
// Returns a string representation of the entity
// Note that this initializes the entity if it is not initialized
//
std::string IfcEntityInstanceData::toString(bool upper) const {
std::ostringstream ss;
void IfcEntityInstanceData::toString(std::ostream& ss, bool upper, const entity* decl) const {
ss.imbue(std::locale::classic());
/*
@@ -1120,23 +1047,17 @@ std::string IfcEntityInstanceData::toString(bool upper) const {
if (i != 0) {
ss << ",";
}
/*
if (storage_.has<Blank>(i)) {
// @todo
if (type_->as_entity() != nullptr && type_->as_entity()->derived()[i]) {
if (decl != nullptr && decl->derived()[i]) {
ss << "*";
} else {
ss << "$";
// }
}
} else {
storage_.apply_visitor(vis, i);
}
*/
storage_.apply_visitor(vis, i);
}
ss << ")";
return ss.str();
}
unsigned IfcUtil::IfcBaseEntity::set_id(const boost::optional<unsigned>& i) {
@@ -1145,39 +1066,6 @@ unsigned IfcUtil::IfcBaseEntity::set_id(const boost::optional<unsigned>& i) {
}
return id_ = file_->FreshId();
}
/*
void IfcEntityInstanceData::load() const {
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();
}
// 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_ != nullptr ? type_->as_entity() : nullptr, type_ != nullptr ? 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 != nullptr) {
attributes_ = tmp_data;
}
}
*/
namespace {
// @todo remove redundancy with python wrapper code (which is not identical due to
@@ -1202,24 +1090,6 @@ IfcUtil::ArgumentType get_argument_type(const IfcParse::declaration* decl, size_
}
} // namespace
/*
IfcEntityInstanceData::IfcEntityInstanceData(const IfcEntityInstanceData& data) {
file = 0;
type_ = data.type_;
id_ = 0;
const size_t count = data.getArgumentCount();
// In order not to have the instance read from file
attributes_ = new Argument*[count];
for (unsigned int i = 0; i < count; ++i) {
attributes_[i] = 0;
this->setArgument(i, data.get_attribute_value(i), get_argument_type(data.type(), i), true);
}
}
*/
class unregister_inverse_visitor {
private:
IfcFile& file_;
@@ -1265,16 +1135,12 @@ class add_to_instance_list_visitor {
class apply_individual_instance_visitor {
private:
AttributeValue attribute_;
boost::optional<AttributeValue> attribute_;
IfcEntityInstanceData* data_;
int attribute_index_;
template <typename T>
void apply_attribute_(T& t, const AttributeValue& attr, int index) const {
if (!attr) {
return;
}
if (attr.type() == IfcUtil::Argument_ENTITY_INSTANCE) {
IfcUtil::IfcBaseClass* inst = attr;
t(inst, index);
@@ -1306,7 +1172,7 @@ class apply_individual_instance_visitor {
template <typename T>
void apply(T& t) const {
if (attribute_) {
apply_attribute_(t, attribute_, attribute_index_);
apply_attribute_(t, *attribute_, attribute_index_);
} else {
for (size_t i = 0; i < data_->size(); ++i) {
auto attr = data_->get_attribute_value(i);
@@ -1554,7 +1420,7 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
stream = 0;
schema_ = 0;
setDefaultHeaderValues();
// setDefaultHeaderValues();
stream = s;
if (!stream->valid) {
@@ -1625,11 +1491,11 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
goto advance;
}
// @todo implement attribute_size() accessor
parse_context ps(storage_t(entity_type->as_entity()->all_attributes().size()));
parse_context ps;
load(current_id, entity_type->as_entity(), ps, -1);
IfcParse::schema_definition* schema;
instance = schema->instantiate(entity_type->name(), IfcEntityInstanceData(ps.data()));
instance = schema_->instantiate(entity_type->name(), ps.construct(current_id, references_to_resolve, entity_type));
instance->file_ = this;
instance->id_ = current_id;
/// @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
@@ -1722,6 +1588,58 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
Logger::Status("\rDone scanning file ");
for (auto& p : references_to_resolve) {
boost::apply_visitor([this, &p](auto& v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, reference_or_simple_type>) {
byid_[p.first.name_]->data().storage_.set(p.first.index_, boost::apply_visitor([this](auto inst) {
IfcUtil::IfcBaseClass* ptr;
if constexpr (std::is_same_v<decltype(inst), int>) {
ptr = this->instance_by_id(inst);
} else {
ptr = inst;
}
return ptr;
}, v));
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<reference_or_simple_type>>) {
aggregate_of_instance::ptr instances(new aggregate_of_instance);
for (auto& p : v) {
instances->push(boost::apply_visitor([this](auto inst) {
IfcUtil::IfcBaseClass* ptr;
if constexpr (std::is_same_v<decltype(inst), int>) {
ptr = this->instance_by_id(inst);
} else {
ptr = inst;
}
return ptr;
}, p));
}
byid_[p.first.name_]->data().storage_.set(p.first.index_, instances);
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<std::vector<reference_or_simple_type>>>) {
aggregate_of_aggregate_of_instance::ptr instances(new aggregate_of_aggregate_of_instance);
for (auto& ps : v) {
std::vector<IfcUtil::IfcBaseClass*> inner;
for (auto& p : ps) {
inner.push_back(boost::apply_visitor([this](auto inst) {
IfcUtil::IfcBaseClass* ptr;
if constexpr (std::is_same_v<decltype(inst), int>) {
ptr = this->instance_by_id(inst);
} else {
ptr = inst;
}
return ptr;
}, p));
}
instances->push(inner);
}
byid_[p.first.name_]->data().storage_.set(p.first.index_, instances);
} else {
static_assert(false, "Inconsistent type");
}
}, p.second);
}
references_to_resolve.clear();
return;
}
@@ -2414,7 +2332,8 @@ std::ostream& operator<<(std::ostream& out, const IfcParse::IfcFile& file) {
for (vector_t::const_iterator it = sorted.begin(); it != sorted.end(); ++it) {
const IfcUtil::IfcBaseClass* e = it->second;
if (e->declaration().as_entity() != nullptr) {
out << e->data().toString(true) << ";" << std::endl;
e->toString(out, true);
out << ";" << std::endl;
}
}
@@ -2646,6 +2565,15 @@ void IfcUtil::IfcBaseClass::unset_attribute_value(size_t index) {
data_.storage_.set(index, Blank{});
}
void IfcUtil::IfcBaseClass::toString(std::ostream& out, bool upper) const
{
auto ent = declaration().as_entity();
if (ent) {
out << "#" << as<IfcUtil::IfcBaseEntity>()->id();
}
data().toString(out, upper, ent);
}
IfcEntityInstanceData::IfcEntityInstanceData(const IfcEntityInstanceData& data)
: storage_(data.storage_.size() )
{
@@ -2656,21 +2584,42 @@ IfcEntityInstanceData::IfcEntityInstanceData(const IfcEntityInstanceData& data)
}
}
/*
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value<int>(int index, const int& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value<bool>(int index, const bool& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value<boost::logic::tribool>(int index, const boost::logic::tribool& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value<double>(int index, const double& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value<std::string>(int index, const std::string& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value<boost::dynamic_bitset<>>(int index, const boost::dynamic_bitset<>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value<IfcWrite::IfcWriteArgument::EnumerationReference>(int index, const IfcWrite::IfcWriteArgument::EnumerationReference& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value<IfcUtil::IfcBaseClass*>(int index, IfcUtil::IfcBaseClass* const& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value<std::vector<int>>(int index, const std::vector<int>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value<std::vector<double>>(int index, const std::vector<double>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value<std::vector<std::string>>(int index, const std::vector<std::string>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value<std::vector<boost::dynamic_bitset<>>>(int index, const std::vector<boost::dynamic_bitset<>>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value<aggregate_of_instance::ptr>(int index, const aggregate_of_instance::ptr& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value<std::vector<std::vector<int>>>(int index, const std::vector<std::vector<int>>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value<std::vector<std::vector<double>>>(int index, const std::vector<std::vector<double>>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value<aggregate_of_aggregate_of_instance::ptr>(int index, const aggregate_of_aggregate_of_instance::ptr& value);
*/
AttributeValue IfcEntityInstanceData::get_attribute_value(size_t index) const
{
return { &storage_, (uint8_t) index };
}
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<int>(size_t index, const int& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<bool>(size_t index, const bool& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<boost::logic::tribool>(size_t index, const boost::logic::tribool& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<double>(size_t index, const double& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<std::string>(size_t index, const std::string& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<boost::dynamic_bitset<>>(size_t index, const boost::dynamic_bitset<>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<EnumerationReference>(size_t index, const EnumerationReference& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<IfcUtil::IfcBaseClass*>(size_t index, IfcUtil::IfcBaseClass* const& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<std::vector<int>>(size_t index, const std::vector<int>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<std::vector<double>>(size_t index, const std::vector<double>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<std::vector<std::string>>(size_t index, const std::vector<std::string>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<std::vector<boost::dynamic_bitset<>>>(size_t index, const std::vector<boost::dynamic_bitset<>>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<aggregate_of_instance::ptr>(size_t index, const aggregate_of_instance::ptr& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<std::vector<std::vector<int>>>(size_t index, const std::vector<std::vector<int>>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<std::vector<std::vector<double>>>(size_t index, const std::vector<std::vector<double>>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<aggregate_of_aggregate_of_instance::ptr>(size_t index, const aggregate_of_aggregate_of_instance::ptr& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<int>(const std::string& name, const int& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<bool>(const std::string& name, const bool& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<boost::logic::tribool>(const std::string& name, const boost::logic::tribool& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<double>(const std::string& name, const double& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<std::string>(const std::string& name, const std::string& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<boost::dynamic_bitset<>>(const std::string& name, const boost::dynamic_bitset<>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<EnumerationReference>(const std::string& name, const EnumerationReference& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<IfcUtil::IfcBaseClass*>(const std::string& name, IfcUtil::IfcBaseClass* const& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<std::vector<int>>(const std::string& name, const std::vector<int>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<std::vector<double>>(const std::string& name, const std::vector<double>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<std::vector<std::string>>(const std::string& name, const std::vector<std::string>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<std::vector<boost::dynamic_bitset<>>>(const std::string& name, const std::vector<boost::dynamic_bitset<>>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<aggregate_of_instance::ptr>(const std::string& name, const aggregate_of_instance::ptr& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<std::vector<std::vector<int>>>(const std::string& name, const std::vector<std::vector<int>>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<std::vector<std::vector<double>>>(const std::string& name, const std::vector<std::vector<double>>& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<aggregate_of_aggregate_of_instance::ptr>(const std::string& name, const aggregate_of_aggregate_of_instance::ptr& value);
+1 -1
View File
@@ -164,7 +164,7 @@ class IFC_PARSE_API IfcSpfLexer {
void TokenString(unsigned int offset, std::string& result);
};
IFC_PARSE_API IfcEntityInstanceData&& read(unsigned int index, IfcFile* file);
IFC_PARSE_API IfcEntityInstanceData read(unsigned int index, IfcFile* file);
IFC_PARSE_API aggregate_of_instance::ptr traverse(IfcUtil::IfcBaseClass* instance, int max_level = -1);
+22 -11
View File
@@ -36,18 +36,26 @@ 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 != nullptr) {
offset_in_file_ = file->stream->Tell();
load();
namespace {
IfcEntityInstanceData read_from_file(IfcFile* f, size_t s) {
parse_context pc;
f->load(-1, nullptr, pc, -1);
return pc.construct(-1, f->references_to_resolve, nullptr);
/*std::ostringstream oss;
ent.toString(oss);
auto osss = oss.str();
std::wcout << osss.c_str() << std::endl;*/
// return ent;
}
}
HeaderEntity::HeaderEntity(const char* const datatype, size_t size, IfcFile* file)
: data_(file ? read_from_file(file, size) : IfcEntityInstanceData(storage_t(size)))
, datatype_(datatype)
, file_(file)
{}
HeaderEntity::~HeaderEntity() {
clearArguments();
}
void IfcSpfHeader::readSemicolon() {
@@ -89,18 +97,21 @@ void IfcSpfHeader::read() {
readTerminal(FILE_DESCRIPTION, NONE);
delete file_description_;
// readParen();
file_description_ = new FileDescription(file_);
// readSemicolon();
readSemicolon();
readTerminal(FILE_NAME, NONE);
delete file_name_;
// readParen();
file_name_ = new FileName(file_);
// readSemicolon();
readSemicolon();
readTerminal(FILE_SCHEMA, NONE);
delete file_schema_;
// readParen();
file_schema_ = new FileSchema(file_);
// readSemicolon();
readSemicolon();
}
bool IfcSpfHeader::tryRead() {
+14 -9
View File
@@ -21,6 +21,7 @@
#define IFCSPFHEADER_H
#include "ifc_parse_api.h"
#include "IfcEntityInstanceData.h"
namespace IfcParse {
class IfcFile;
@@ -28,8 +29,8 @@ namespace IfcParse {
class IFC_PARSE_API HeaderEntity {
private:
const char* const datatype_;
size_t size_;
IfcFile* file_;
HeaderEntity(const HeaderEntity&); //N/A
HeaderEntity& operator=(const HeaderEntity&); //N/A
protected:
@@ -48,12 +49,13 @@ class IFC_PARSE_API HeaderEntity {
public:
virtual size_t getArgumentCount() const {
return size_;
return data_.size();
}
std::string toString(bool upper = false) const {
std::stringstream stream;
stream << datatype_ << data_.toString(upper);
stream << datatype_;
data_.toString(stream, upper);
return stream.str();
}
};
@@ -115,14 +117,17 @@ class IFC_PARSE_API IfcSpfHeader {
void readTerminal(const std::string& term, Trail trail);
public:
explicit IfcSpfHeader(IfcParse::IfcFile* file = 0)
explicit IfcSpfHeader(IfcParse::IfcFile* file = nullptr)
: 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_);
file_schema_(0)
{
if (file == nullptr) {
file_description_ = new FileDescription(file_);
file_name_ = new FileName(file_);
file_schema_ = new FileSchema(file_);
}
}
~IfcSpfHeader() {
+14
View File
@@ -56,6 +56,7 @@
#include "IfcBaseClass.h"
#include "IfcException.h"
#include "utils.h"
#include "IfcFile.h"
#include <algorithm>
#include <boost/algorithm/string/replace.hpp>
@@ -207,6 +208,19 @@ Argument* IfcUtil::IfcBaseEntity::get(const std::string& name) const {
}
*/
AttributeValue IfcUtil::IfcBaseEntity::get(const std::string& name) const
{
auto attrs = declaration().as_entity()->all_attributes();
auto iter = attrs.begin();
size_t idx = 0;
for (; iter != attrs.end(); ++iter, ++idx) {
if ((*iter)->name() == name) {
return data().get_attribute_value(idx);
}
}
throw IfcParse::IfcException(name + " not found on " + declaration().name());
}
aggregate_of_instance::ptr IfcUtil::IfcBaseEntity::get_inverse(const std::string& name) const {
const std::vector<const IfcParse::inverse_attribute*> attrs = declaration().as_entity()->all_inverse_attributes();
std::vector<const IfcParse::inverse_attribute*>::const_iterator iter = attrs.begin();
+81 -55
View File
@@ -27,8 +27,35 @@
#include <boost/algorithm/string.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/any.hpp>
#include <libxml/parser.h>
namespace {
// Base case: when there are no more types left to check.
template <typename Fn>
void visit_any_impl(Fn& fn, const boost::any& a) {
}
// Recursive case: Check the first type in the pack.
template <typename Fn, typename T, typename... Types>
void visit_any_impl(Fn& fn, const boost::any& a) {
if (a.type() == typeid(T)) {
Fn(boost::any_cast<T>(a));
} else {
visit_any_impl<Types...>(a);
}
}
// Helper to prepend a type to a tuple
template <typename Fn, typename U>
void visit_any(Fn fn, const boost::any& a);
template <typename Fn, typename... Types>
void visit_any(Fn fn, const boost::any & a) {
visit_any_impl<Fn, Types...>(fn, a);
};
}
// For debug printing on release builds
// #undef NDEBUG
@@ -71,7 +98,8 @@ class stack_node {
node_header_entry
};
std::vector<Argument*> aggregate_elements;
// to be coerced into the correct type later on
std::vector<boost::any> aggregate_elements;
protected:
node_type type_;
@@ -199,13 +227,12 @@ std::vector<T> split(const std::string& value) {
return r;
}
Argument* parse_attribute_value(const IfcParse::parameter_type* ty, const std::string& value) {
auto* v = new IfcWrite::IfcWriteArgument();
boost::any parse_attribute_value(const IfcParse::parameter_type* ty, const std::string& value) {
boost::any any;
auto cpp_type = IfcUtil::from_parameter_type(ty);
if (cpp_type == IfcUtil::Argument_STRING) {
v->set(value);
any = value;
} else if (cpp_type == IfcUtil::Argument_ENUMERATION) {
const auto* enum_type = ty->as_named_type()->declared_type()->as_enumeration_type();
@@ -214,28 +241,24 @@ Argument* parse_attribute_value(const IfcParse::parameter_type* ty, const std::s
enum_type->enumeration_items().end(),
boost::to_upper_copy(value));
if (iter != enum_type->enumeration_items().end()) {
v->set(IfcWrite::IfcWriteArgument::EnumerationReference(iter - enum_type->enumeration_items().begin(), iter->c_str()));
}
any = EnumerationReference(enum_type, std::distance(enum_type->enumeration_items().begin(), iter));
} else if (cpp_type == IfcUtil::Argument_INT) {
v->set(boost::lexical_cast<int>(value));
any = boost::lexical_cast<int>(value);
} else if (cpp_type == IfcUtil::Argument_DOUBLE) {
v->set(boost::lexical_cast<double>(value));
any = boost::lexical_cast<double>(value);
} else if (cpp_type == IfcUtil::Argument_BOOL) {
v->set(boost::to_lower_copy(value) == "true");
any = boost::to_lower_copy(value) == "true";
} else if (cpp_type == IfcUtil::Argument_AGGREGATE_OF_INT) {
v->set(split<int>(value));
any = split<int>(value);
} else if (cpp_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) {
v->set(split<double>(value));
any = split<double>(value);
}
if (v->isNull()) {
if (any.empty()) {
Logger::Error("Attribute '" + value + "' not successfully parsed");
delete v;
v = nullptr;
}
return v;
return any;
}
static void end_element(void* user, const xmlChar* tag) {
@@ -248,17 +271,20 @@ static void end_element(void* user, const xmlChar* tag) {
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* list = new IfcParse::ArgumentList(elems.size());
size_t i = 0;
for (auto& elem : elems) {
list->arguments()[i++] = elem;
}
back.inst()->data().attributes()[back.idx()] = list;
*/
// @todo
// back.inst()->data().storage_.set(back.idx(), elems);
}
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()] = state->file->addEntity(state->stack.back().inst())->data().id();
state->idmap[state->stack.back().id()] = state->file->addEntity(state->stack.back().inst())->id();
}
}
@@ -290,15 +316,17 @@ static void process_characters(void* user, const xmlChar* character, int len) {
if (!state->stack.empty() && state->stack.back().inst() != nullptr && (state->stack.back().inst()->declaration().as_type_declaration() != nullptr)) {
const auto* pt = state->stack.back().inst()->declaration().as_type_declaration()->declared_type();
Argument* val = nullptr;
boost::any val;
try {
val = parse_attribute_value(pt, txt);
} catch (const std::exception& e) {
Logger::Error(e, state->stack.back().inst());
}
if (val != nullptr) {
if (!val.empty()) {
// type declaration always at idx 0
state->stack.back().inst()->data().setArgument(0, val);
visit_any([&state](auto& v) {
state->stack.back().inst()->data().storage_.set(0, v);
}, val);
}
} else if (state_type == stack_node::node_header_entry) {
const std::string tagname = boost::replace_all_copy(state->stack.back().tagname(), "ex:", "");
@@ -326,15 +354,17 @@ static void process_characters(void* user, const xmlChar* character, int len) {
const 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 != nullptr) {
state->stack.back().inst()->data().setArgument(state->stack.back().idx(), val);
auto val = parse_attribute_value(pt, txt);
if (!val.empty()) {
visit_any([&state](auto& v) {
state->stack.back().inst()->data().setArgument(state->stack.back().idx(), v);
}, val);
}
}
} else if (state_type == stack_node::node_aggregate_element) {
const auto* pt = state->stack.back().aggregate_elem_type();
auto* val = parse_attribute_value(pt, txt);
if (val != nullptr) {
auto val = parse_attribute_value(pt, txt);
if (!val.empty()) {
(*(state->stack.rbegin() + 1)).aggregate_elements.push_back(val);
}
}
@@ -388,13 +418,11 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
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;
}
@@ -426,7 +454,6 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
state->forward_references.push_back(std::make_tuple(inst->as<IfcUtil::IfcBaseEntity>(), attribute_index, boost::get<std::string>(inst_or_ref)));
} else {
inst = boost::get<IfcUtil::IfcBaseClass*>(inst_or_ref);
// wattr->set(inst);
inst->set_attribute_value(attribute_index, inst);
}
};
@@ -452,7 +479,7 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
}
}
auto* untyped = new IfcEntityInstanceData(decl);
auto untyped = IfcEntityInstanceData(storage_t(decl->as_entity() ? decl->as_entity()->attribute_count() : 1));
const IfcParse::entity* entity = decl->as_entity();
if (entity != nullptr) {
@@ -464,9 +491,11 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
auto idx = entity->attribute_index(pair.first);
if (idx != -1) {
const auto* attr = entity->attribute_by_index(idx);
auto* val = parse_attribute_value(attr->type_of_attribute(), pair.second);
if (val != nullptr) {
untyped->setArgument(idx, val);
auto val = parse_attribute_value(attr->type_of_attribute(), pair.second);
if (!val.empty()) {
visit_any([&untyped, idx](auto& v) {
untyped->data().storage_->set_attribute_value(idx, v);
}, val);
}
} else {
Logger::Error("Unknown attribute '" + pair.first + "' on entity '" + entity->name() + "' with value '" + pair.second + "'");
@@ -474,7 +503,7 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
}
}
IfcUtil::IfcBaseClass* newinst = state->file->schema()->instantiate(untyped);
IfcUtil::IfcBaseClass* newinst = state->file->schema()->instantiate(decl->name(), std::move(untyped));
if (state->dialect == ifcxml_dialect_ifc4) {
// In IFC2X3 not added directly because attrs such as GlobalId are in
@@ -532,9 +561,10 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
if (decl != nullptr) {
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);
// Argument* attr;
// @todo
// instance_to_attribute(inst_or_ref, attr, inst);
state->stack.back().aggregate_elements.push_back(boost::any{});
state->stack.push_back(stack_node::instance(id, inst));
}
}
@@ -558,14 +588,11 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
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);
instance_to_attribute(inst_or_ref, 0, 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);
inst->data().storage_.set(idx, state->stack.back().inst());
state->stack.push_back(stack_node::instance(id, inst));
} else {
Logger::Error("Unknown attribute " + tagname);
@@ -588,11 +615,11 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
if (IfcUtil::from_parameter_type(attribute_type) == IfcUtil::Argument_ENTITY_INSTANCE) {
if (const 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, newinst));
IfcUtil::IfcBaseClass* inst;
instance_to_attribute(inst_or_reference, idx, inst);
// @todo
state->stack.back().inst();
state->stack.push_back(stack_node::instance(id, boost::get<IfcUtil::IfcBaseClass*>(inst_or_reference)));
} else if (attribute_type->as_named_type()->declared_type()->as_select_type() != nullptr) {
// 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));
@@ -630,21 +657,18 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
auto inst_or_ref = create_instance(decl);
IfcUtil::IfcBaseClass* inst;
Argument* attr;
instance_to_attribute(inst_or_ref, attr, inst);
instance_to_attribute(inst_or_ref, state->stack.back().idx(), 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 != nullptr) {
inst->data().setArgument(idx, attr_inv);
inst->data().storage_.set(idx, state->stack.back().inst());
} 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;
state->stack.back().inst()->data().storage_.set(state->stack.back().idx(), inst);
}
if (entity == nullptr) {
@@ -679,16 +703,18 @@ IFC_PARSE_API IfcParse::IfcFile* IfcParse::parse_ifcxml(const std::string& filen
xmlSAXUserParseFile(&handler, &state, filename.c_str());
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));
}
*/
}
if (state.file != nullptr) {
state.file->parsing_complete() = true;
// state.file->parsing_complete() = true;
state.file->build_inverses();
}
+29 -4
View File
@@ -59,7 +59,10 @@ namespace impl {
// Base case: When the first type in the pack is the type we're looking for, or is a base class of it
template <typename T, typename U, typename... Ts>
struct TypeIndex<T, U, Ts...>
: std::integral_constant<std::size_t, std::is_base_of<U, T>::value ? 0 : 1 + TypeIndex<T, Ts...>::value> {};
: std::integral_constant<std::size_t, (std::is_pointer_v<T> ? std::is_base_of_v<std::remove_pointer_t<U>, std::remove_pointer_t<T>> : std::is_same_v<T, U>) ? 0 :
(TypeIndex<T, Ts...>::value == std::numeric_limits<std::size_t>::max()
? std::numeric_limits<std::size_t>::max()
: 1 + TypeIndex<T, Ts...>::value)> {};
// Recursion termination: When the parameter pack is empty
template <typename T>
@@ -117,6 +120,7 @@ namespace impl {
struct make_union_from_tuple<std::tuple<Args...>> {
using type = typename std::aligned_union<0, Args...>::type;
};
}
template<typename... Types>
@@ -165,15 +169,17 @@ public:
template<typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, VariantArray>>>
void set(std::size_t index, T&& value) {
using U = std::decay_t<T>;
static_assert(impl::TypeIndex_v<U, Types...> < sizeof...(Types), "Type not supported by variant");
if (index >= size_and_indices_[0]) {
throw std::out_of_range("Index out of range");
}
destroy_at_index(index);
using U = std::decay_t<T>;
size_and_indices_[index + 1] = impl::TypeIndex_v<U, Types...>;
using V = typename std::tuple_element<impl::TypeIndex_v<U, Types...>, impl::MapTypes_t<Types... >>::type;
// std::wcout << "setting " << index << " to " << typeid(V).name() << " (" << impl::TypeIndex_v<U, Types...> << ")" << std::endl;
if constexpr (impl::is_unique_ptr<V>::value) {
new(&storage_[index]) V(new U(value));
} else {
@@ -194,7 +200,12 @@ public:
if (!has<T>(index)) {
throw std::bad_cast();
}
return *reinterpret_cast<T*>(&storage_[index]);
using V = typename std::tuple_element<impl::TypeIndex_v<T, Types...>, impl::MapTypes_t<Types... >>::type;
if constexpr (impl::is_unique_ptr<V>::value) {
return **reinterpret_cast<V*>(&storage_[index]);
} else {
return *reinterpret_cast<V*>(&storage_[index]);
}
}
template<typename T>
@@ -207,7 +218,12 @@ public:
if (size_and_indices_[index + 1] != impl::TypeIndex<T, Types...>::value) {
throw std::bad_cast();
}
return *reinterpret_cast<const T*>(&storage_[index]);
using V = typename std::tuple_element<impl::TypeIndex_v<T, Types...>, impl::MapTypes_t<Types... >>::type;
if constexpr (impl::is_unique_ptr<V>::value) {
return **reinterpret_cast<const V*>(&storage_[index]);
} else {
return *reinterpret_cast<const V*>(&storage_[index]);
}
}
template<typename Visitor>
@@ -267,9 +283,18 @@ private:
return apply_visitor_impl(std::forward<Visitor>(visitor), idx, std::integral_constant<std::size_t, Index - 1>{});
}
template<typename, typename = std::void_t<>>
struct has_result_type : std::false_type {};
template<typename T>
struct has_result_type<T, std::void_t<typename T::result_type>> : std::true_type {};
template<typename Visitor>
auto apply_visitor_impl(Visitor&&, std::size_t, std::integral_constant<std::size_t, 0>) const {
throw std::runtime_error("Invalid variant index");
// This raises a warning but is neccessary (?) for the auto return type inference?
if constexpr (has_result_type<Visitor>::value) {
return typename Visitor::result_type{};
}
}
};