mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-13 02:47:48 +00:00
WIP
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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_));
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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{};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user