diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 3bdc45bf0f..847f499c13 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -1486,7 +1486,7 @@ namespace latebound_access { enum_type->enumeration_items().end(), t); - return set(inst, attr, IfcWrite::IfcWriteArgument::EnumerationReference(it - enum_type->enumeration_items().begin(), it->c_str())); + return set(inst, attr, EnumerationReference(enum_type, it - enum_type->enumeration_items().begin())); } template @@ -1495,19 +1495,17 @@ namespace latebound_access { auto i = decl->attribute_index(attr); auto attr_type = decl->attribute_by_index(i)->type_of_attribute(); - if (attr_type->as_named_type() && attr_type->as_named_type()->declared_type()->as_enumeration_type() && !std::is_same::value) { + if (attr_type->as_named_type() && attr_type->as_named_type()->declared_type()->as_enumeration_type() && !std::is_same::value) { set_enumeration(inst, attr, attr_type->as_named_type()->declared_type()->as_enumeration_type(), t); } else { - IfcWrite::IfcWriteArgument* a = new IfcWrite::IfcWriteArgument; - a->set(t); - inst->data().attributes()[i] = a; + inst->set_attribute_value(i, t); } } IfcUtil::IfcBaseClass* create(IfcParse::IfcFile& f, const std::string& entity) { auto decl = f.schema()->declaration_by_name(entity); - auto data = new IfcEntityInstanceData(decl); - auto inst = f.schema()->instantiate(data); + auto data = IfcEntityInstanceData(storage_t(decl->as_entity()->attribute_count())); + auto inst = f.schema()->instantiate(entity, std::move(data)); if (decl->is("IfcRoot")) { IfcParse::IfcGlobalId guid; latebound_access::set(inst, "GlobalId", (std::string) guid); @@ -1547,7 +1545,7 @@ void fix_quantities(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool std auto IfcRelDefinesByProperties = f.schema()->declaration_by_name("IfcRelDefinesByProperties"); if (element_quantities) { for (auto& eq : *element_quantities) { - auto rels = eq->data().getInverse(IfcRelDefinesByProperties, -1); + auto rels = eq->file_->getInverse(eq->id(), IfcRelDefinesByProperties, -1); for (auto& rel : *rels) { relationships.push_back(rel); } diff --git a/src/ifcgeom/Converter.cpp b/src/ifcgeom/Converter.cpp index fef9dc3517..d08cec8bb2 100644 --- a/src/ifcgeom/Converter.cpp +++ b/src/ifcgeom/Converter.cpp @@ -35,7 +35,7 @@ IfcGeom::BRepElement* ifcopenshell::geometry::Converter::create_brep_for_represe auto place = place_; - representation_id_builder << representation_node->instance->data().id(); + representation_id_builder << representation_node->instance->as()->id(); IfcGeom::Representation::BRep* shape; IfcGeom::ConversionResults shapes; @@ -137,7 +137,7 @@ IfcGeom::BRepElement* ifcopenshell::geometry::Converter::create_brep_for_represe } if (material_style_applied) { - representation_id_builder << "-material-" << single_material->data().id(); + representation_id_builder << "-material-" << single_material->id(); } if (settings_.get().has() && product->declaration().is("IfcSpace")) { @@ -153,7 +153,7 @@ IfcGeom::BRepElement* ifcopenshell::geometry::Converter::create_brep_for_represe try { IfcUtil::IfcBaseEntity* parent_object = mapping_->get_decomposing_entity(product); if (parent_object) { - parent_id = parent_object->data().id(); + parent_id = parent_object->id(); } } catch (const std::exception& e) { Logger::Error(e); @@ -171,7 +171,7 @@ IfcGeom::BRepElement* ifcopenshell::geometry::Converter::create_brep_for_represe if (!settings_.get().get() && openings && openings->size()) { representation_id_builder << "-openings"; for (auto it = openings->begin(); it != openings->end(); ++it) { - representation_id_builder << "-" << (*it)->data().id(); + representation_id_builder << "-" << (*it)->id(); } IfcGeom::ConversionResults opened_shapes; @@ -236,19 +236,19 @@ IfcGeom::BRepElement* ifcopenshell::geometry::Converter::create_brep_for_represe // IfcShapeRepresentation. const IfcUtil::IfcBaseEntity *representation = representation_node->instance->as(); auto representation_identifier = representation->get("RepresentationIdentifier"); - if (!representation_identifier->isNull()) { - context_string = (std::string) *representation_identifier; + if (!representation_identifier.isNull()) { + context_string = (std::string) representation_identifier; } else { - IfcUtil::IfcBaseClass *context = (IfcUtil::IfcBaseClass *) *representation->get("ContextOfItems"); + IfcUtil::IfcBaseClass *context = (IfcUtil::IfcBaseClass*)representation->get("ContextOfItems"); auto context_type = context->as()->get("ContextType"); - if (!context_type->isNull()) { - context_string = (std::string) *context_type; + if (!context_type.isNull()) { + context_string = (std::string)context_type; } } auto elem = new IfcGeom::BRepElement( - product->data().id(), + product->id(), parent_id, name, product_type, @@ -340,7 +340,7 @@ IfcGeom::BRepElement* ifcopenshell::geometry::Converter::create_brep_for_process try { IfcUtil::IfcBaseEntity* parent_object = mapping_->get_decomposing_entity(product); if (parent_object) { - parent_id = parent_object->data().id(); + parent_id = parent_object->id(); } } catch (const std::exception& e) { Logger::Error(e); @@ -352,7 +352,7 @@ IfcGeom::BRepElement* ifcopenshell::geometry::Converter::create_brep_for_process const std::string context_string = brep->context(); return new IfcGeom::BRepElement( - product->data().id(), + product->id(), parent_id, name, product_type, diff --git a/src/ifcgeom/IfcGeomElement.h b/src/ifcgeom/IfcGeomElement.h index e17d0e39b5..7121425e11 100644 --- a/src/ifcgeom/IfcGeomElement.h +++ b/src/ifcgeom/IfcGeomElement.h @@ -73,12 +73,12 @@ namespace IfcGeom { friend bool operator < (const Element& element1, const Element& element2) { if (element1.type() == "IfcBuildingStorey" && element2.type() == "IfcBuildingStorey") { size_t attr_index = element1.product()->declaration().attribute_index("Elevation"); - Argument* elev_attr1 = element1.product()->data().getArgument(attr_index); - Argument* elev_attr2 = element2.product()->data().getArgument(attr_index); + auto elev_attr1 = element1.product()->data().get_attribute_value(attr_index); + auto elev_attr2 = element2.product()->data().get_attribute_value(attr_index); - if (!elev_attr1->isNull() && !elev_attr2->isNull()) { - double elev1 = *elev_attr1; - double elev2 = *elev_attr2; + if (!elev_attr1.isNull() && !elev_attr2.isNull()) { + double elev1 = elev_attr1; + double elev2 = elev_attr2; return elev1 < elev2; } diff --git a/src/ifcgeom/IfcGeomFilter.h b/src/ifcgeom/IfcGeomFilter.h index c41dbef0d5..eb4eb7cd8a 100644 --- a/src/ifcgeom/IfcGeomFilter.h +++ b/src/ifcgeom/IfcGeomFilter.h @@ -76,7 +76,7 @@ namespace IfcGeom { // schema. // @todo pass settings ifcopenshell::geometry::Settings s; - static auto mapping = ifcopenshell::geometry::impl::mapping_implementations().construct(prod->data().file, s); + static auto mapping = ifcopenshell::geometry::impl::mapping_implementations().construct(prod->file_, s); while ((parent = mapping->get_decomposing_entity(current, traverse_openings)) != nullptr) { if (pred(parent)) { return true; @@ -138,7 +138,7 @@ namespace IfcGeom { std::string value(IfcUtil::IfcBaseEntity* prod) const { try { - return (std::string) *prod->get(attribute_name); + return (std::string) prod->get(attribute_name); } catch (...) { // Either // (a) not an attribute name for this entity instance @@ -184,7 +184,7 @@ namespace IfcGeom { bool match(IfcUtil::IfcBaseEntity* prod) const { // @todo ifcopenshell::geometry::Settings s; - static auto mapping = ifcopenshell::geometry::impl::mapping_implementations().construct(prod->data().file, s); + static auto mapping = ifcopenshell::geometry::impl::mapping_implementations().construct(prod->file_, s); layer_map_t layers = mapping->get_layers(prod); return std::find_if(layers.begin(), layers.end(), wildcards_match(values)) != layers.end(); } @@ -255,7 +255,7 @@ namespace IfcGeom { , instance_ids_(instance_ids) {} bool match(IfcUtil::IfcBaseEntity* prod) const { - return instance_ids_.find(prod->data().id()) != instance_ids_.end(); + return instance_ids_.find(prod->id()) != instance_ids_.end(); } bool operator()(IfcUtil::IfcBaseEntity* prod) const { diff --git a/src/ifcgeom/IfcGeomRepresentation.cpp b/src/ifcgeom/IfcGeomRepresentation.cpp index 89eb2bdd6b..9f8d10bd58 100644 --- a/src/ifcgeom/IfcGeomRepresentation.cpp +++ b/src/ifcgeom/IfcGeomRepresentation.cpp @@ -154,7 +154,7 @@ IfcGeom::Representation::Serialization::Serialization(const BRep& brep) surface_styles_.push_back(clr(1)); surface_styles_.push_back(clr(2)); - sid = it->Style().instance ? it->Style().instance->data().id() : -1; + sid = it->Style().instance ? it->Style().instance->as()->id() : -1; } else { surface_styles_.push_back(-1.); surface_styles_.push_back(-1.); diff --git a/src/ifcgeom/Iterator.h b/src/ifcgeom/Iterator.h index 8b685972b4..f4f4649b7c 100644 --- a/src/ifcgeom/Iterator.h +++ b/src/ifcgeom/Iterator.h @@ -518,7 +518,7 @@ namespace IfcGeom { Logger::SetProduct(product); - IfcGeom::BRepElement* brep = static_cast(decorate_with_cache_(GeometrySerializer::READ_BREP, (std::string)*product->get("GlobalId"), std::to_string(representation->instance->data().id()), [kernel, settings, product, place, representation]() { + IfcGeom::BRepElement* brep = static_cast(decorate_with_cache_(GeometrySerializer::READ_BREP, (std::string)product->get("GlobalId"), std::to_string(representation->instance->as()->id()), [kernel, settings, product, place, representation]() { return kernel->create_brep_for_representation_and_product(representation, product, place); })); @@ -539,7 +539,7 @@ namespace IfcGeom { const IfcUtil::IfcBaseEntity* product2 = p.first; const auto& place2 = p.second; - IfcGeom::BRepElement* brep2 = static_cast(decorate_with_cache_(GeometrySerializer::READ_BREP, (std::string)*product2->get("GlobalId"), std::to_string(representation->instance->data().id()), [kernel, settings, product2, place2, representation, brep]() { + IfcGeom::BRepElement* brep2 = static_cast(decorate_with_cache_(GeometrySerializer::READ_BREP, (std::string)product2->get("GlobalId"), std::to_string(representation->instance->as()->id()), [kernel, settings, product2, place2, representation, brep]() { return kernel->create_brep_for_processed_representation(product2, place2, brep); })); if (brep2) { @@ -746,13 +746,13 @@ namespace IfcGeom { instance_type = ifc_product->declaration().name(); if (ifc_product->declaration().is("IfcRoot")) { - product_guid = (std::string) *ifc_product->get("GlobalId"); + product_guid = (std::string) ifc_product->get("GlobalId"); product_name = ifc_product->get_value("Name", ""); } auto parent_object = converter_->mapping()->get_decomposing_entity(ifc_product); if (parent_object) { - parent_id = parent_object->data().id(); + parent_id = parent_object->id(); } // fails in case of IfcProject diff --git a/src/ifcgeom/abstract_mapping.h b/src/ifcgeom/abstract_mapping.h index bb7904233d..405a6b7c2f 100644 --- a/src/ifcgeom/abstract_mapping.h +++ b/src/ifcgeom/abstract_mapping.h @@ -30,8 +30,10 @@ namespace geometry { Settings settings_; bool use_caching_ = true; + public: abstract_mapping(Settings& s) : settings_(s) {} + virtual ~abstract_mapping() {} virtual ifcopenshell::geometry::taxonomy::ptr map(const IfcUtil::IfcBaseInterface*) = 0; virtual void get_representations(std::vector& tasks, std::vector& filters) = 0; diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index 507fb77c50..1575d7588f 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -767,7 +767,7 @@ bool CgalKernel::convert_impl(const taxonomy::shell::ptr shell, ConversionResult return false; } results.emplace_back(ConversionResult( - shell->instance->data().id(), + shell->instance->as()->id(), shell->matrix, new CgalShape(shape), shell->surface_style @@ -788,7 +788,7 @@ bool CgalKernel::convert_impl(const taxonomy::solid::ptr solid, ConversionResult return false; } results.emplace_back(ConversionResult( - solid->instance->data().id(), + solid->instance->as()->id(), solid->matrix, new CgalShape(shape), solid->surface_style @@ -938,7 +938,7 @@ bool CgalKernel::convert_impl(const taxonomy::extrusion::ptr extrusion, Conversi return false; } results.emplace_back(ConversionResult( - extrusion->instance->data().id(), + extrusion->instance->as()->id(), extrusion->matrix, new CgalShape(shape), extrusion->surface_style @@ -1814,7 +1814,7 @@ bool CgalKernel::convert_impl(const taxonomy::boolean_result::ptr br, Conversion } return ConversionResult( - br->instance->data().id(), + br->instance->as()->id(), br->matrix, new CgalShape(shp), br->surface_style ? br->surface_style : first_item_style @@ -2047,7 +2047,7 @@ bool CgalKernel::convert_impl(const taxonomy::boolean_result::ptr br, Conversion } results.emplace_back(ConversionResult( - br->instance->data().id(), + br->instance->as()->id(), br->matrix, new CgalShape(a_poly), br->surface_style ? br->surface_style : first_item_style diff --git a/src/ifcgeom/kernels/opencascade/boolean_result.cpp b/src/ifcgeom/kernels/opencascade/boolean_result.cpp index d934ddf4fc..6750108a90 100644 --- a/src/ifcgeom/kernels/opencascade/boolean_result.cpp +++ b/src/ifcgeom/kernels/opencascade/boolean_result.cpp @@ -107,7 +107,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result::ptr br, Con if (settings_.get().get()) { results.emplace_back(IfcGeom::ConversionResult( - (int)br->instance->data().id(), + br->instance->as()->id(), br->matrix, new OpenCascadeShape(a), br->surface_style ? br->surface_style : first_item_style @@ -189,7 +189,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result::ptr br, Con } results.emplace_back(IfcGeom::ConversionResult( - (int) br->instance->data().id(), + br->instance->as()->id(), br->matrix, new OpenCascadeShape(a), br->surface_style ? br->surface_style : first_item_style diff --git a/src/ifcgeom/kernels/opencascade/extrusion.cpp b/src/ifcgeom/kernels/opencascade/extrusion.cpp index 0ee6ff8e2a..b1152a4158 100644 --- a/src/ifcgeom/kernels/opencascade/extrusion.cpp +++ b/src/ifcgeom/kernels/opencascade/extrusion.cpp @@ -78,7 +78,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::extrusion::ptr extrusion, I } results.emplace_back(ConversionResult( - extrusion->instance->data().id(), + extrusion->instance->as()->id(), extrusion->matrix, new OpenCascadeShape(shape), extrusion->surface_style diff --git a/src/ifcgeom/kernels/opencascade/face.cpp b/src/ifcgeom/kernels/opencascade/face.cpp index 06ce63af31..86e386b3ed 100644 --- a/src/ifcgeom/kernels/opencascade/face.cpp +++ b/src/ifcgeom/kernels/opencascade/face.cpp @@ -514,7 +514,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::face::ptr face, IfcGeom::Co return false; } results.emplace_back(ConversionResult( - face->instance->data().id(), + face->instance->as()->id(), new OpenCascadeShape(shape), face->surface_style )); diff --git a/src/ifcgeom/kernels/opencascade/loft.cpp b/src/ifcgeom/kernels/opencascade/loft.cpp index 4ed9b59f43..b418675fbd 100644 --- a/src/ifcgeom/kernels/opencascade/loft.cpp +++ b/src/ifcgeom/kernels/opencascade/loft.cpp @@ -113,7 +113,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::loft::ptr loft, IfcGeom::Co return false; } results.emplace_back(ConversionResult( - loft->instance->data().id(), + loft->instance->as()->id(), loft->matrix, new OpenCascadeShape(shape), loft->surface_style diff --git a/src/ifcgeom/kernels/opencascade/loop.cpp b/src/ifcgeom/kernels/opencascade/loop.cpp index 30239349f0..18c658fd15 100644 --- a/src/ifcgeom/kernels/opencascade/loop.cpp +++ b/src/ifcgeom/kernels/opencascade/loop.cpp @@ -363,7 +363,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::loop::ptr loop, IfcGeom::Co } results.emplace_back(ConversionResult( - loop->instance->data().id(), + loop->instance->as()->id(), new OpenCascadeShape(shape), loop->surface_style )); @@ -374,7 +374,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::edge::ptr edge, IfcGeom::Co TopoDS_Wire shape = boost::get(convert_curve(edge)); results.emplace_back(ConversionResult( - edge->instance->data().id(), + edge->instance->as()->id(), new OpenCascadeShape(shape), edge->surface_style )); diff --git a/src/ifcgeom/kernels/opencascade/shell.cpp b/src/ifcgeom/kernels/opencascade/shell.cpp index ef1115a49c..eacc87e12b 100644 --- a/src/ifcgeom/kernels/opencascade/shell.cpp +++ b/src/ifcgeom/kernels/opencascade/shell.cpp @@ -112,7 +112,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::shell::ptr shell, IfcGeom:: return false; } results.emplace_back(ConversionResult( - shell->instance->data().id(), + shell->instance->as()->id(), shell->matrix, new OpenCascadeShape(shape), shell->surface_style diff --git a/src/ifcgeom/kernels/opencascade/solid.cpp b/src/ifcgeom/kernels/opencascade/solid.cpp index cb8112ab25..4f308b0b06 100644 --- a/src/ifcgeom/kernels/opencascade/solid.cpp +++ b/src/ifcgeom/kernels/opencascade/solid.cpp @@ -107,7 +107,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::solid::ptr solid, IfcGeom:: return false; } results.emplace_back(ConversionResult( - solid->instance->data().id(), + solid->instance->as()->id(), solid->matrix, new OpenCascadeShape(shape), solid->surface_style diff --git a/src/ifcgeom/kernels/opencascade/sweep_along_curve.cpp b/src/ifcgeom/kernels/opencascade/sweep_along_curve.cpp index 7505e40663..bb3fa7f190 100644 --- a/src/ifcgeom/kernels/opencascade/sweep_along_curve.cpp +++ b/src/ifcgeom/kernels/opencascade/sweep_along_curve.cpp @@ -148,7 +148,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::sweep_along_curve::ptr scs, return false; } results.emplace_back(ConversionResult( - scs->instance->data().id(), + scs->instance->as()->id(), scs->matrix, new OpenCascadeShape(shape), scs->surface_style diff --git a/src/ifcgeom/mapping/IfcCompositeCurve.cpp b/src/ifcgeom/mapping/IfcCompositeCurve.cpp index c70334b347..aed15a8f83 100644 --- a/src/ifcgeom/mapping/IfcCompositeCurve.cpp +++ b/src/ifcgeom/mapping/IfcCompositeCurve.cpp @@ -85,7 +85,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCompositeCurve* inst) { } if (pwfs.empty()) { - aggregate_of_instance::ptr profile = inst->data().getInverse(&IfcSchema::IfcProfileDef::Class(), -1); + aggregate_of_instance::ptr profile = inst->file_->getInverse(inst->id(), &IfcSchema::IfcProfileDef::Class(), -1); const bool force_close = profile && profile->size() > 0; loop->closed = force_close; loop->instance = inst; diff --git a/src/ifcgeom/mapping/IfcCurveSegment.cpp b/src/ifcgeom/mapping/IfcCurveSegment.cpp index 44b3d330b6..d50ab31281 100644 --- a/src/ifcgeom/mapping/IfcCurveSegment.cpp +++ b/src/ifcgeom/mapping/IfcCurveSegment.cpp @@ -67,7 +67,7 @@ double translate_if_param_value(const IfcSchema::IfcCurve* crv, IfcSchema::IfcCu // We don't care whether length- or positive length measure. return translate_to_length_measure(crv, *param); } else { - return *val->data().getArgument(0); + return val->data().get_attribute_value(0); } } diff --git a/src/ifcgeom/mapping/IfcTrimmedCurve.cpp b/src/ifcgeom/mapping/IfcTrimmedCurve.cpp index 96aa6a83e4..e6e27f3832 100644 --- a/src/ifcgeom/mapping/IfcTrimmedCurve.cpp +++ b/src/ifcgeom/mapping/IfcTrimmedCurve.cpp @@ -117,9 +117,9 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcTrimmedCurve* inst) { // or trimmed segment would be whether there are other curve segments or this // is the only one. boost::optional num_segments; - auto segment = inst->data().getInverse(&IfcSchema::IfcCompositeCurveSegment::Class(), -1); + auto segment = inst->file_->getInverse(inst->id(), & IfcSchema::IfcCompositeCurveSegment::Class(), -1); if (segment->size() == 1) { - auto comp = (*segment->begin())->data().getInverse(&IfcSchema::IfcCompositeCurve::Class(), -1); + auto comp = (*segment->begin())->file_->getInverse((*segment->begin())->id(), &IfcSchema::IfcCompositeCurve::Class(), -1); if (comp->size() == 1) { num_segments = (*comp->begin())->as()->Segments()->size(); } diff --git a/src/ifcgeom/mapping/mapping.cpp b/src/ifcgeom/mapping/mapping.cpp index 67e650b177..3c297f03be 100644 --- a/src/ifcgeom/mapping/mapping.cpp +++ b/src/ifcgeom/mapping/mapping.cpp @@ -59,7 +59,7 @@ IfcSchema::IfcProduct::list::ptr mapping::products_represented_by(const IfcSchem // IfcProductRepresentation also lacks the INVERSE relation to IfcProduct // Let's find the IfcProducts that reference the IfcProductRepresentation anyway - products->push((*it)->data().getInverse((&IfcSchema::IfcProduct::Class()), -1)->as()); + products->push((*it)->file_->getInverse((*it)->id(), &IfcSchema::IfcProduct::Class(), -1)->as()); } if (only_direct) { @@ -81,13 +81,13 @@ IfcSchema::IfcProduct::list::ptr mapping::products_represented_by(const IfcSchem continue; } - IfcSchema::IfcRepresentation::list::ptr reps = item->data().getInverse((&IfcSchema::IfcRepresentation::Class()), -1)->as(); + IfcSchema::IfcRepresentation::list::ptr reps = item->file_->getInverse(item->id(), (&IfcSchema::IfcRepresentation::Class()), -1)->as(); for (IfcSchema::IfcRepresentation::list::it jt = reps->begin(); jt != reps->end(); ++jt) { IfcSchema::IfcRepresentation* rep = *jt; if (rep->Items()->size() != 1) continue; IfcSchema::IfcProductRepresentation::list::ptr prodreps_mapped = rep->OfProductRepresentation(); for (IfcSchema::IfcProductRepresentation::list::it kt = prodreps_mapped->begin(); kt != prodreps_mapped->end(); ++kt) { - IfcSchema::IfcProduct::list::ptr ps = (*kt)->data().getInverse((&IfcSchema::IfcProduct::Class()), -1)->as(); + IfcSchema::IfcProduct::list::ptr ps = (*kt)->file_->getInverse((*kt)->id(), (&IfcSchema::IfcProduct::Class()), -1)->as(); products->push(ps); } } @@ -273,7 +273,7 @@ const IfcUtil::IfcBaseEntity* mapping::get_product_type(const IfcUtil::IfcBaseEn } #endif // Avoid segfault if RelatingType is unset. - if (rel->get("RelatingType")->isNull()){ + if (rel->get("RelatingType").isNull()){ break; return nullptr; } @@ -492,7 +492,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcMaterial* material) { material_style->name = material->Name(); } else { std::ostringstream oss; - oss << material->declaration().name() << "-" << material->data().id(); + oss << material->declaration().name() << "-" << material->id(); material_style->name = oss.str(); } return material_style; @@ -522,7 +522,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcStyledItem* inst) { } else { std::ostringstream oss; if (shading) { - oss << shading->declaration().name() << "-" << shading->data().id(); + oss << shading->declaration().name() << "-" << shading->id(); } else { oss << "-"; } @@ -660,8 +660,8 @@ IfcUtil::IfcBaseEntity* mapping::get_decomposing_entity(const IfcUtil::IfcBaseEn /* Parent decompositions to the RelatingObject */ if (!parent) { - aggregate_of_instance::ptr parents = product->data().getInverse((&IfcSchema::IfcRelAggregates::Class()), -1); - parents->push(product->data().getInverse((&IfcSchema::IfcRelNests::Class()), -1)); + aggregate_of_instance::ptr parents = product->file_->getInverse(product->id(), (&IfcSchema::IfcRelAggregates::Class()), -1); + parents->push(product->file_->getInverse(product->id(), (&IfcSchema::IfcRelNests::Class()), -1)); for (aggregate_of_instance::it it = parents->begin(); it != parents->end(); ++it) { IfcSchema::IfcRelDecomposes* decompose = (*it)->as(); IfcUtil::IfcBaseEntity* ifc_objectdef; @@ -794,11 +794,11 @@ void mapping::initialize_settings() { // See if there is a context_id filter and whether the context is selected if (settings_.get().has()) { auto cids = settings_.get().get(); - if (cids.find(context->data().id()) == cids.end()) { + if (cids.find(context->id()) == cids.end()) { bool selected_sub_context = false; auto subs = context->HasSubContexts(); for (auto& sub : *subs) { - if (cids.find(context->data().id()) != cids.end()) { + if (cids.find(context->id()) != cids.end()) { selected_sub_context = true; break; } diff --git a/src/ifcgeom/taxonomy.cpp b/src/ifcgeom/taxonomy.cpp index 0ed716677d..3eacbe77e3 100644 --- a/src/ifcgeom/taxonomy.cpp +++ b/src/ifcgeom/taxonomy.cpp @@ -641,7 +641,9 @@ void ifcopenshell::geometry::taxonomy::trimmed_curve::print(std::ostream& o, int } if (this->instance) { - o << std::string(indent + 4, ' ') << this->instance->data().toString() << std::endl; + std::ostringstream oss; + this->instance->as()->toString(oss); + o << std::string(indent + 4, ' ') << oss.str() << std::endl; } } diff --git a/src/ifcopenshell-python/ifcopenshell/express/implementation.py b/src/ifcopenshell-python/ifcopenshell/express/implementation.py index 585eebc084..421d96a94f 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/implementation.py +++ b/src/ifcopenshell-python/ifcopenshell/express/implementation.py @@ -370,7 +370,7 @@ class Implementation(codegen.Base): ("IfcEntityInstanceData&& e",), "", ), - ("", "", constructor, "", ("%s v" % type_str,), "set_attribute_value(0, v);") if mapping.simple_type_parent(class_name) is None else \ + ("", "", constructor, "", ("%s v" % type_str,), ("set_attribute_value(0, v%s);" % ("->generalize()" if mapping.is_templated_list(type) else ""))) if mapping.simple_type_parent(class_name) is None else \ ("v", "", constructor, "", ("%s v" % type_str,), ""), ("", "", templates.cast_function, type_str, (), simpletype_impl_cast), ), diff --git a/src/ifcparse/Ifc4.cpp b/src/ifcparse/Ifc4.cpp index 39141b44f0..420f09bdf1 100644 --- a/src/ifcparse/Ifc4.cpp +++ b/src/ifcparse/Ifc4.cpp @@ -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 diff --git a/src/ifcparse/Ifc4x1.cpp b/src/ifcparse/Ifc4x1.cpp index 9f22b9d5ca..d29a74345f 100644 --- a/src/ifcparse/Ifc4x1.cpp +++ b/src/ifcparse/Ifc4x1.cpp @@ -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 diff --git a/src/ifcparse/Ifc4x2.cpp b/src/ifcparse/Ifc4x2.cpp index 0eb63fd82a..f7470a5c39 100644 --- a/src/ifcparse/Ifc4x2.cpp +++ b/src/ifcparse/Ifc4x2.cpp @@ -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 diff --git a/src/ifcparse/Ifc4x3.cpp b/src/ifcparse/Ifc4x3.cpp index fef8a399c6..5b426c34ff 100644 --- a/src/ifcparse/Ifc4x3.cpp +++ b/src/ifcparse/Ifc4x3.cpp @@ -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 diff --git a/src/ifcparse/Ifc4x3_add1.cpp b/src/ifcparse/Ifc4x3_add1.cpp index 3587f23492..658d8a7f2f 100644 --- a/src/ifcparse/Ifc4x3_add1.cpp +++ b/src/ifcparse/Ifc4x3_add1.cpp @@ -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 diff --git a/src/ifcparse/Ifc4x3_add2.cpp b/src/ifcparse/Ifc4x3_add2.cpp index bf1dd03d8e..968f8966da 100644 --- a/src/ifcparse/Ifc4x3_add2.cpp +++ b/src/ifcparse/Ifc4x3_add2.cpp @@ -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 diff --git a/src/ifcparse/Ifc4x3_rc1.cpp b/src/ifcparse/Ifc4x3_rc1.cpp index 952c76ee2f..b0dd4f038e 100644 --- a/src/ifcparse/Ifc4x3_rc1.cpp +++ b/src/ifcparse/Ifc4x3_rc1.cpp @@ -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 diff --git a/src/ifcparse/Ifc4x3_rc2.cpp b/src/ifcparse/Ifc4x3_rc2.cpp index c6ddf80018..f963b6a655 100644 --- a/src/ifcparse/Ifc4x3_rc2.cpp +++ b/src/ifcparse/Ifc4x3_rc2.cpp @@ -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 diff --git a/src/ifcparse/Ifc4x3_rc3.cpp b/src/ifcparse/Ifc4x3_rc3.cpp index 3e004640ea..81d981efd6 100644 --- a/src/ifcparse/Ifc4x3_rc3.cpp +++ b/src/ifcparse/Ifc4x3_rc3.cpp @@ -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 diff --git a/src/ifcparse/Ifc4x3_rc4.cpp b/src/ifcparse/Ifc4x3_rc4.cpp index 8e1455bc30..502a31d9dc 100644 --- a/src/ifcparse/Ifc4x3_rc4.cpp +++ b/src/ifcparse/Ifc4x3_rc4.cpp @@ -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 diff --git a/src/ifcparse/Ifc4x3_tc1.cpp b/src/ifcparse/Ifc4x3_tc1.cpp index 727e51a8cf..c5d293cb23 100644 --- a/src/ifcparse/Ifc4x3_tc1.cpp +++ b/src/ifcparse/Ifc4x3_tc1.cpp @@ -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 diff --git a/src/ifcparse/IfcBaseClass.h b/src/ifcparse/IfcBaseClass.h index a6ee98cd23..a8c1642130 100644 --- a/src/ifcparse/IfcBaseClass.h +++ b/src/ifcparse/IfcBaseClass.h @@ -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; }; diff --git a/src/ifcparse/IfcEntityInstanceData.cpp b/src/ifcparse/IfcEntityInstanceData.cpp new file mode 100644 index 0000000000..8b20702215 --- /dev/null +++ b/src/ifcparse/IfcEntityInstanceData.cpp @@ -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& i) const { return (int)i.size(); } + int operator()(const std::vector& i) const { return (int)i.size(); } + int operator()(const std::vector>& i) const { return (int)i.size(); } + int operator()(const std::vector>& i) const { return (int)i.size(); } + int operator()(const std::vector& i) const { return (int)i.size(); } + int operator()(const std::vector>& i) const { return (int)i.size(); } + int operator()(const 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(index_); +} + +AttributeValue::operator bool() const +{ + return array_->get(index_); +} + +AttributeValue::operator double() const +{ + return array_->get(index_); +} + +AttributeValue::operator boost::logic::tribool() const +{ + return array_->get(index_); +} + +AttributeValue::operator std::string() const +{ + if (array_->has(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(index_).value(); + } + return array_->get(index_); +} + +AttributeValue::operator boost::dynamic_bitset<>() const +{ + return array_->get>(index_); +} + +AttributeValue::operator IfcUtil::IfcBaseClass* () const +{ + return array_->get(index_); +} + +AttributeValue::operator std::vector() const +{ + return array_->get>(index_); +} + +AttributeValue::operator std::vector() const +{ + return array_->get>(index_); +} + +AttributeValue::operator std::vector() const +{ + return array_->get>(index_); +} + +AttributeValue::operator std::vector>() const +{ + return array_->get>>(index_); +} + +AttributeValue::operator boost::shared_ptr() const +{ + return array_->get>(index_); +} + +AttributeValue::operator std::vector>() const +{ + return array_->get>>(index_); +} + +AttributeValue::operator std::vector>() const +{ + return array_->get>>(index_); +} + +AttributeValue::operator boost::shared_ptr() const +{ + return array_->get>(index_); +} + +bool AttributeValue::isNull() const +{ + return array_->has(index_); +} + +unsigned int AttributeValue::size() const +{ + return array_->apply_visitor(SizeVisitor{}, index_); +} + +IfcUtil::ArgumentType AttributeValue::type() const +{ + return static_cast(array_->index(index_)); +} diff --git a/src/ifcparse/IfcEntityInstanceData.h b/src/ifcparse/IfcEntityInstanceData.h index 41d0d24951..10b9da4e8f 100644 --- a/src/ifcparse/IfcEntityInstanceData.h +++ b/src/ifcparse/IfcEntityInstanceData.h @@ -23,9 +23,12 @@ #include "ArgumentType.h" #include "variantarray.h" #include "aggregate_of_instance.h" +#include "IfcSchema.h" #include #include +#include +#include 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 diff --git a/src/ifcparse/IfcFile.cpp b/src/ifcparse/IfcFile.cpp new file mode 100644 index 0000000000..20c45e99c6 --- /dev/null +++ b/src/ifcparse/IfcFile.cpp @@ -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, 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 + struct is_type_in_variant; + + // Specialization for boost::variant + template + struct is_type_in_variant, T> + { + // Recursive template to check if T is one of Types + static constexpr bool value = (std::is_same::value || ...); + }; + + // Helper variable template (C++14 and beyond) + template + constexpr bool is_type_in_variant_v = is_type_in_variant::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& r, const boost::variant& 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(v).type); + } else if (v.which() == 2) { + // @todo check for empty aggregate + get_token_type(r, boost::get(v)->tokens_.front()); + } + } + + bool can_coerce(const std::vector& target, const std::vector& source) { + if (target == std::vector{0, 0} && source == std::vector{1, IfcParse::Token_IDENTIFIER}) { + return true; + } + if (source == std::vector{0, 0} && target == std::vector{1, IfcParse::Token_IDENTIFIER}) { + return true; + } + return source == target; + } + + struct InstanceReference { + int v; + operator int() const { + return v; + } + }; + + template + 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 + 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 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 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, + std::vector, + std::vector, + std::vector>, + std::vector, + + std::vector>, + std::vector>, + std::vector> + > 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, IfcParse::Token>) { + // @todo get aggregate of enumeration + dispatch_token(v, nullptr, [&aggregate_storage](auto v) { + if constexpr (std::is_same_v) { + if (aggregate_storage.which() == 0) { + aggregate_storage = std::vector{ v }; + } else { + boost::get< std::vector>(aggregate_storage).push_back(v); + } + } else if constexpr (is_type_in_variant_v>>) { + if (aggregate_storage.which() == 0) { + aggregate_storage = std::vector>{ v }; + } else { + boost::get< std::vector>>(aggregate_storage).push_back(v); + } + } + }); + } else if constexpr (std::is_same_v, IfcParse::parse_context*>) { + /*construct_(*v, [&aggregate_storage](auto& v) { + if (aggregate_storage.which() == 0) { + aggregate_storage = std::vector>{ v }; + } else { + boost::get>>(aggregate_storage).push_back(v); + } + });*/ + // Too deeply nested list + } else { + if (aggregate_storage.which() == 0) { + aggregate_storage = std::vector{ v }; + } else { + boost::get>(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 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 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, 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, 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, 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, IfcParse::parse_context*>) { + construct_(*v, [this, &storage, name, &references_to_resolve, index](auto& v) { + if constexpr (std::is_same_v, std::vector>) { + references_to_resolve.push_back({ {name, index }, v }); + } else if constexpr (std::is_same_v, std::vector>>) { + 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)); +} diff --git a/src/ifcparse/IfcFile.h b/src/ifcparse/IfcFile.h index ba99d8fd21..16fa47206e 100644 --- a/src/ifcparse/IfcFile.h +++ b/src/ifcparse/IfcFile.h @@ -65,79 +65,41 @@ class IFC_PARSE_API file_open_status { } }; +typedef boost::variant reference_or_simple_type; +typedef std::list, std::vector>>>> unresolved_references; + struct parse_context { - boost::variant< - Blank, - storage_t, // IFCWALL(x) - std::vector, // IFCCARTESIANPOINT((x, y, z)) - std::vector, // IFCCARTESIANPOINT((IFCTEXT(), IFCTEXT())) - std::list // 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{}; - 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>(tokens).size() == 0) { - tokens = std::list{}; - return push(); - } else { - throw std::runtime_error("b"); - } - } else if (tokens.which() == 4) { - boost::get>(tokens).emplace_back(); - return boost::get>(tokens).back(); - } - } + void push(Token t); - void push(Token t) { - if (tokens.which() == 1) { - boost::get>(tokens).push_back(t); - } else if (tokens.which() == 3) { - boost::get>(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>(tokens).push_back(inst); - } else if (tokens.which() == 3) { - boost::get>(tokens).back().push(inst); - } else { - throw std::runtime_error("a"); - } - } - void pop() { - - } - - storage_t&& data() { - return std::move(boost::get(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 entities_by_type_t; typedef boost::unordered_map entity_by_id_t; typedef boost::unordered_map entity_by_iden_t; diff --git a/src/ifcparse/IfcLogger.cpp b/src/ifcparse/IfcLogger.cpp index 30421a8725..2ae1bacb39 100644 --- a/src/ifcparse/IfcLogger.cpp +++ b/src/ifcparse/IfcLogger.cpp @@ -70,7 +70,9 @@ void plain_text_message(T& out, const boost::optionaldata().toString(); + std::ostringstream oss; + instance->as()->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& c property_tree.put(level_string, severity_strings::value[type]); if (current_product) { - property_tree.put(product_string, string_as((**current_product).data().toString())); + std::ostringstream oss; + (*current_product)->toString(oss); + property_tree.put(product_string, string_as(oss.str())); } property_tree.put(message_string, string_as(message)); if (instance) { - property_tree.put(instance_string, string_as(instance->data().toString())); + std::ostringstream oss; + instance->as()->toString(oss); + property_tree.put(instance_string, string_as(oss.str())); } property_tree.put(time_string, string_as(get_time())); diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index a24a905bed..72870432ec 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -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* vector = 0; vector_or_array 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 -std::vector read_aggregate_as_vector(const std::vector& tokens) { - std::vector 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 -std::vector> read_aggregate_of_aggregate_as_vector2(const std::vector& tokens) { - std::vector> return_value; - return_value.reserve(tokens.size()); - for (size_t i = 0; i < tokens.size(); ++i) { - return_value.push_back(read_aggregate_as_vector(boost::get< std::vector>(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 void serialize(const std::vector& 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(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& i) { @@ -1145,39 +1066,6 @@ unsigned IfcUtil::IfcBaseEntity::set_id(const boost::optional& 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 attribute_; IfcEntityInstanceData* data_; int attribute_index_; template 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 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, 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) { + ptr = this->instance_by_id(inst); + } else { + ptr = inst; + } + return ptr; + }, v)); + } else if constexpr (std::is_same_v, std::vector>) { + 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) { + 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::vector>>) { + aggregate_of_aggregate_of_instance::ptr instances(new aggregate_of_aggregate_of_instance); + for (auto& ps : v) { + std::vector inner; + for (auto& p : ps) { + inner.push_back(boost::apply_visitor([this](auto inst) { + IfcUtil::IfcBaseClass* ptr; + if constexpr (std::is_same_v) { + 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()->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 index, const int& value); -template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value(int index, const bool& value); -template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value(int index, const boost::logic::tribool& value); -template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value(int index, const double& value); -template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value(int index, const std::string& value); -template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value>(int index, const boost::dynamic_bitset<>& value); -template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value(int index, const IfcWrite::IfcWriteArgument::EnumerationReference& value); -template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value(int index, IfcUtil::IfcBaseClass* const& value); -template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value>(int index, const std::vector& value); -template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value>(int index, const std::vector& value); -template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value>(int index, const std::vector& value); -template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value>>(int index, const std::vector>& value); -template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value(int index, const aggregate_of_instance::ptr& value); -template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value>>(int index, const std::vector>& value); -template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value>>(int index, const std::vector>& value); -template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_value(int index, const aggregate_of_aggregate_of_instance::ptr& value); -*/ \ No newline at end of file +AttributeValue IfcEntityInstanceData::get_attribute_value(size_t index) const +{ + return { &storage_, (uint8_t) index }; +} + + +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(size_t index, const int& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(size_t index, const bool& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(size_t index, const boost::logic::tribool& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(size_t index, const double& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(size_t index, const std::string& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value>(size_t index, const boost::dynamic_bitset<>& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(size_t index, const EnumerationReference& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(size_t index, IfcUtil::IfcBaseClass* const& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value>(size_t index, const std::vector& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value>(size_t index, const std::vector& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value>(size_t index, const std::vector& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value>>(size_t index, const std::vector>& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(size_t index, const aggregate_of_instance::ptr& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value>>(size_t index, const std::vector>& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value>>(size_t index, const std::vector>& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(size_t index, const aggregate_of_aggregate_of_instance::ptr& value); + +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(const std::string& name, const int& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(const std::string& name, const bool& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(const std::string& name, const boost::logic::tribool& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(const std::string& name, const double& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(const std::string& name, const std::string& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value>(const std::string& name, const boost::dynamic_bitset<>& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(const std::string& name, const EnumerationReference& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(const std::string& name, IfcUtil::IfcBaseClass* const& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value>(const std::string& name, const std::vector& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value>(const std::string& name, const std::vector& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value>(const std::string& name, const std::vector& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value>>(const std::string& name, const std::vector>& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(const std::string& name, const aggregate_of_instance::ptr& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value>>(const std::string& name, const std::vector>& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value>>(const std::string& name, const std::vector>& value); +template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value(const std::string& name, const aggregate_of_aggregate_of_instance::ptr& value); diff --git a/src/ifcparse/IfcParse.h b/src/ifcparse/IfcParse.h index c840d5558d..c24488cb59 100644 --- a/src/ifcparse/IfcParse.h +++ b/src/ifcparse/IfcParse.h @@ -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); diff --git a/src/ifcparse/IfcSpfHeader.cpp b/src/ifcparse/IfcSpfHeader.cpp index 36b45b46b8..7160d942c3 100644 --- a/src/ifcparse/IfcSpfHeader.cpp +++ b/src/ifcparse/IfcSpfHeader.cpp @@ -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() { diff --git a/src/ifcparse/IfcSpfHeader.h b/src/ifcparse/IfcSpfHeader.h index 2275bec525..f07faeacf9 100644 --- a/src/ifcparse/IfcSpfHeader.h +++ b/src/ifcparse/IfcSpfHeader.h @@ -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() { diff --git a/src/ifcparse/IfcUtil.cpp b/src/ifcparse/IfcUtil.cpp index 693c7ee114..90382b7a69 100644 --- a/src/ifcparse/IfcUtil.cpp +++ b/src/ifcparse/IfcUtil.cpp @@ -56,6 +56,7 @@ #include "IfcBaseClass.h" #include "IfcException.h" #include "utils.h" +#include "IfcFile.h" #include #include @@ -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 attrs = declaration().as_entity()->all_inverse_attributes(); std::vector::const_iterator iter = attrs.begin(); diff --git a/src/ifcparse/parse_ifcxml.cpp b/src/ifcparse/parse_ifcxml.cpp index 6a6cbd5e86..dd43269595 100644 --- a/src/ifcparse/parse_ifcxml.cpp +++ b/src/ifcparse/parse_ifcxml.cpp @@ -27,8 +27,35 @@ #include #include #include +#include #include +namespace { + // Base case: when there are no more types left to check. + template + void visit_any_impl(Fn& fn, const boost::any& a) { + } + + // Recursive case: Check the first type in the pack. + template + void visit_any_impl(Fn& fn, const boost::any& a) { + if (a.type() == typeid(T)) { + Fn(boost::any_cast(a)); + } else { + visit_any_impl(a); + } + } + + // Helper to prepend a type to a tuple + template + void visit_any(Fn fn, const boost::any& a); + template + void visit_any(Fn fn, const boost::any & a) { + visit_any_impl(fn, a); + }; + +} + // For debug printing on release builds // #undef NDEBUG @@ -71,7 +98,8 @@ class stack_node { node_header_entry }; - std::vector aggregate_elements; + // to be coerced into the correct type later on + std::vector aggregate_elements; protected: node_type type_; @@ -199,13 +227,12 @@ std::vector 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(value)); + any = boost::lexical_cast(value); } else if (cpp_type == IfcUtil::Argument_DOUBLE) { - v->set(boost::lexical_cast(value)); + any = boost::lexical_cast(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(value)); + any = split(value); } else if (cpp_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) { - v->set(split(value)); + any = split(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(), attribute_index, boost::get(inst_or_ref))); } else { inst = boost::get(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(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(); } diff --git a/src/ifcparse/variantarray.h b/src/ifcparse/variantarray.h index 3f837505fa..20c7d9face 100644 --- a/src/ifcparse/variantarray.h +++ b/src/ifcparse/variantarray.h @@ -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 struct TypeIndex - : std::integral_constant::value ? 0 : 1 + TypeIndex::value> {}; + : std::integral_constant ? std::is_base_of_v, std::remove_pointer_t> : std::is_same_v) ? 0 : + (TypeIndex::value == std::numeric_limits::max() + ? std::numeric_limits::max() + : 1 + TypeIndex::value)> {}; // Recursion termination: When the parameter pack is empty template @@ -117,6 +120,7 @@ namespace impl { struct make_union_from_tuple> { using type = typename std::aligned_union<0, Args...>::type; }; + } template @@ -165,15 +169,17 @@ public: template, VariantArray>>> void set(std::size_t index, T&& value) { + using U = std::decay_t; + static_assert(impl::TypeIndex_v < 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; size_and_indices_[index + 1] = impl::TypeIndex_v; using V = typename std::tuple_element, impl::MapTypes_t>::type; + // std::wcout << "setting " << index << " to " << typeid(V).name() << " (" << impl::TypeIndex_v << ")" << std::endl; if constexpr (impl::is_unique_ptr::value) { new(&storage_[index]) V(new U(value)); } else { @@ -194,7 +200,12 @@ public: if (!has(index)) { throw std::bad_cast(); } - return *reinterpret_cast(&storage_[index]); + using V = typename std::tuple_element, impl::MapTypes_t>::type; + if constexpr (impl::is_unique_ptr::value) { + return **reinterpret_cast(&storage_[index]); + } else { + return *reinterpret_cast(&storage_[index]); + } } template @@ -207,7 +218,12 @@ public: if (size_and_indices_[index + 1] != impl::TypeIndex::value) { throw std::bad_cast(); } - return *reinterpret_cast(&storage_[index]); + using V = typename std::tuple_element, impl::MapTypes_t>::type; + if constexpr (impl::is_unique_ptr::value) { + return **reinterpret_cast(&storage_[index]); + } else { + return *reinterpret_cast(&storage_[index]); + } } template @@ -267,9 +283,18 @@ private: return apply_visitor_impl(std::forward(visitor), idx, std::integral_constant{}); } + template> + struct has_result_type : std::false_type {}; + template + struct has_result_type> : std::true_type {}; + template auto apply_visitor_impl(Visitor&&, std::size_t, std::integral_constant) 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::value) { + return typename Visitor::result_type{}; + } } }; diff --git a/src/serializers/ColladaSerializer.cpp b/src/serializers/ColladaSerializer.cpp index b77a3c369c..364685a426 100644 --- a/src/serializers/ColladaSerializer.cpp +++ b/src/serializers/ColladaSerializer.cpp @@ -417,11 +417,11 @@ std::string ColladaSerializer::differentiateSlabTypes(const IfcUtil::IfcBaseEnti { auto value = slab->get("PredefinedType"); - if (value->isNull()) { + if (value.isNull()) { return "_Unknown"; } - const std::string str_value = *value; + const std::string str_value = value; std::string result; if (str_value == "FLOOR") { @@ -436,10 +436,10 @@ std::string ColladaSerializer::differentiateSlabTypes(const IfcUtil::IfcBaseEnti result = "_NotDefined"; } else { auto otype = slab->get("ObjectType"); - if (otype->isNull()) { + if (otype.isNull()) { result = "_Unknown"; } else { - result = (std::string) *otype; + result = (std::string) otype; } } diff --git a/src/serializers/HdfSerializer.cpp b/src/serializers/HdfSerializer.cpp index f393f8a379..a6388632bb 100644 --- a/src/serializers/HdfSerializer.cpp +++ b/src/serializers/HdfSerializer.cpp @@ -542,7 +542,7 @@ void HdfSerializer::write_style(surface_style_serialization& data, const ifcopen data.name = s.name.c_str(); // @todo data.original_name = s.name.c_str(); - data.id = s.instance->data().id(); + data.id = s.instance->as()->id(); if (s.diffuse) { data.diffuse[0] = s.diffuse.ccomponents()(0); data.diffuse[1] = s.diffuse.ccomponents()(1); diff --git a/src/serializers/SvgSerializer.cpp b/src/serializers/SvgSerializer.cpp index 86e5681ae3..e260c3e623 100644 --- a/src/serializers/SvgSerializer.cpp +++ b/src/serializers/SvgSerializer.cpp @@ -382,7 +382,7 @@ namespace { for (const auto& p : o->parents()) { if (p->type() == "IfcBuildingStorey") { try { - double e = *p->product()->get("Elevation"); + double e = p->product()->get("Elevation"); double storey_elevation = e * o->geometry().settings().get().get(); return std::make_pair(p->product(), storey_elevation); } catch (...) { @@ -495,22 +495,22 @@ namespace { auto rels = product->get_inverse("IsDefinedBy"); for (auto& rel : *rels) { if (rel->declaration().is("IfcRelDefinesByProperties")) { - auto pset = (IfcUtil::IfcBaseEntity*) (IfcUtil::IfcBaseClass*) *((IfcUtil::IfcBaseEntity*) rel)->get("RelatingPropertyDefinition"); + auto pset = ((IfcUtil::IfcBaseClass*) ((IfcUtil::IfcBaseEntity*) rel)->get("RelatingPropertyDefinition"))->as(); std::string pset_name; - if (!pset->get("Name")->isNull()) { - pset_name = (std::string) *pset->get("Name"); + if (!pset->get("Name").isNull()) { + pset_name = (std::string) pset->get("Name"); } - aggregate_of_instance::ptr props = *pset->get("HasProperties"); + aggregate_of_instance::ptr props = pset->get("HasProperties"); for (auto& prop : *props) { if (prop->declaration().is("IfcPropertySingleValue")) { - std::string name = *((IfcUtil::IfcBaseEntity*) prop)->get("Name"); - if (((IfcUtil::IfcBaseEntity*) prop)->get("NominalValue")->isNull()) { + std::string name = ((IfcUtil::IfcBaseEntity*) prop)->get("Name"); + if (((IfcUtil::IfcBaseEntity*) prop)->get("NominalValue").isNull()) { continue; } - IfcUtil::IfcBaseClass* v = *((IfcUtil::IfcBaseEntity*) prop)->get("NominalValue"); - auto value = v->data().getArgument(0); - if (value->type() == IfcUtil::Argument_STRING) { - std::string v_str = *value; + IfcUtil::IfcBaseClass* v = ((IfcUtil::IfcBaseEntity*) prop)->get("NominalValue"); + auto value = v->data().get_attribute_value(0); + if (value.type() == IfcUtil::Argument_STRING) { + std::string v_str = value; *output_it++ = string_property{ pset_name, name, v_str }; } } @@ -525,12 +525,12 @@ namespace { auto refs = item->get_inverse("StyledByItem"); for (auto& ref : *refs) { if (ref->declaration().is("IfcStyledItem")) { - aggregate_of_instance::ptr styles = *((IfcUtil::IfcBaseEntity*)ref)->get("Styles"); + aggregate_of_instance::ptr styles = ((IfcUtil::IfcBaseEntity*)ref)->get("Styles"); for (auto& s_ : *styles) { auto s = (IfcUtil::IfcBaseEntity*) s_; std::vector pss; if (s->declaration().is("IfcPresentationStyleAssignment")) { - aggregate_of_instance::ptr pstyles = *s->get("Styles"); + aggregate_of_instance::ptr pstyles = s->get("Styles"); for (auto& ssss : *pstyles) { pss.push_back((IfcUtil::IfcBaseEntity*) ssss); } @@ -540,8 +540,8 @@ namespace { for (auto& ps : pss) { if (ps->declaration().is("IfcCurveStyle")) { auto arg = ps->get("Name"); - if (!arg->isNull()) { - return (std::string) *arg; + if (!arg.isNull()) { + return (std::string) arg; } } } @@ -555,8 +555,8 @@ namespace { void SvgSerializer::write(const IfcGeom::BRepElement* brep_obj) { boost::optional object_type; - if (!brep_obj->product()->get("ObjectType")->isNull()) { - object_type = static_cast(*brep_obj->product()->get("ObjectType")); + if (!brep_obj->product()->get("ObjectType").isNull()) { + object_type = static_cast(brep_obj->product()->get("ObjectType")); } std::vector>> dash_arrays; @@ -845,11 +845,11 @@ void SvgSerializer::write(const geometry_data& data) { } for (auto& rel : *rels) { if (rel->declaration().name() == "IfcRelDefinesByType") { - IfcUtil::IfcBaseClass* ty = *((IfcUtil::IfcBaseEntity*)rel)->get("RelatingType"); + IfcUtil::IfcBaseClass* ty = ((IfcUtil::IfcBaseEntity*)rel)->get("RelatingType"); const std::string& ty_entity_name = ty->declaration().name(); // Damn you, IFC if (ty_entity_name == "IfcDoorStyle" || ty_entity_name == "IfcDoorType") { - operation_type = (std::string)*((IfcUtil::IfcBaseEntity*)ty)->get("OperationType"); + operation_type = (std::string)((IfcUtil::IfcBaseEntity*)ty)->get("OperationType"); } } } @@ -1273,8 +1273,8 @@ void SvgSerializer::write(const geometry_data& data) { std::string object_type; auto ot_arg = data.product->get("ObjectType"); - if (!ot_arg->isNull()) { - object_type = (std::string) *ot_arg; + if (!ot_arg.isNull()) { + object_type = (std::string) ot_arg; object_type.erase(std::remove_if(object_type.begin(), object_type.end(), [](char c) { return !std::isalnum(c); }), object_type.end()); } @@ -1476,8 +1476,8 @@ void SvgSerializer::write(const geometry_data& data) { const double lu = file->getUnit("LENGTHUNIT").second; auto a = data.product->get("Elevation"); - if (!a->isNull()) { - double elev = *a; + if (!a.isNull()) { + double elev = a; // @nb we don't actually factor in the length unit. // elev *= lu; @@ -1622,8 +1622,8 @@ void SvgSerializer::write(const geometry_data& data) { } if (print_space_names_ && data.product->declaration().is("IfcSpace")) { auto attr = data.product->get("LongName"); - if (!attr->isNull()) { - std::string long_name = *attr; + if (!attr.isNull()) { + std::string long_name = attr; if (!long_name.empty()) { labels.insert(labels.begin(), long_name); } @@ -1851,14 +1851,14 @@ void SvgSerializer::addTextAnnotations(const drawing_key& k) { auto ds = ann->get("Description"); auto pl = ann->get("ObjectPlacement"); - if (!ot->isNull() && !nm->isNull() && !ds->isNull() && !pl->isNull()) { - auto object_type = (std::string) *ot; - auto name = (std::string) *nm; - auto desc = (std::string) *ds; + if (!ot.isNull() && !nm.isNull() && !ds.isNull() && !pl.isNull()) { + auto object_type = (std::string) ot; + auto name = (std::string) nm; + auto desc = (std::string) ds; if (object_type == "Text") { auto mapping = ifcopenshell::geometry::impl::mapping_implementations().construct(file, geometry_settings_); - auto item = mapping->map(*pl); + auto item = mapping->map(pl); auto matrix = ifcopenshell::geometry::taxonomy::cast(item); delete mapping; if (item) { @@ -2085,8 +2085,8 @@ void SvgSerializer::finalize() { for (auto& s : *storeys) { auto storey = (IfcUtil::IfcBaseEntity*) s; auto a = storey->get("Elevation"); - if (!a->isNull()) { - double elev = *a; + if (!a.isNull()) { + double elev = a; elev *= lu; auto svg_name = nameElement(storey); @@ -2117,8 +2117,8 @@ void SvgSerializer::finalize() { B.Add(C, mf.Face()); std::string name; auto a2 = storey->get("Name"); - if (!a2->isNull()) { - name = (std::string) *a2; + if (!a2.isNull()) { + name = (std::string) a2; } write(geometry_data{ C,{boost::none},trsf,storey,storey,elev,name,nameElement(storey) @@ -2280,12 +2280,12 @@ std::string SvgSerializer::idElement(const IfcUtil::IfcBaseEntity* elem) { const std::string type = elem->declaration().is("IfcBuildingStorey") ? "storey" : "product"; const std::string name = (settings().get().get() - ? static_cast(*elem->get("GlobalId")) - : ((settings().get().get() && !elem->get("Name")->isNull())) - ? static_cast(*elem->get("Name")) + ? static_cast(elem->get("GlobalId")) + : ((settings().get().get() && !elem->get("Name").isNull())) + ? static_cast(elem->get("Name")) : (settings().get().get()) - ? ("id-" + boost::lexical_cast(elem->data().id())) - : IfcParse::IfcGlobalId(*elem->get("GlobalId")).formatted()); + ? ("id-" + boost::lexical_cast(elem->id())) + : IfcParse::IfcGlobalId(elem->get("GlobalId")).formatted()); return type + "-" + name; } @@ -2294,8 +2294,8 @@ std::string SvgSerializer::nameElement(const IfcUtil::IfcBaseEntity* elem) { const std::string& entity = elem->declaration().name(); std::string ifc_name; - if (!elem->get("Name")->isNull()) { - ifc_name = (std::string) *elem->get("Name"); + if (!elem->get("Name").isNull()) { + ifc_name = (std::string) elem->get("Name"); IfcUtil::escape_xml(ifc_name); } @@ -2303,7 +2303,7 @@ std::string SvgSerializer::nameElement(const IfcUtil::IfcBaseEntity* elem) { {"id", idElement(elem)}, {"class", entity}, {namespace_prefix_ + "name", ifc_name}, - {namespace_prefix_ + "guid", *elem->get("GlobalId")} + {namespace_prefix_ + "guid", elem->get("GlobalId")} }); } @@ -2322,8 +2322,8 @@ void SvgSerializer::setFile(IfcParse::IfcFile* f) { if (insts) { for (auto jt = insts->begin(); jt != insts->end(); ++jt) { IfcUtil::IfcBaseEntity* product = (IfcUtil::IfcBaseEntity*) *jt; - if (!product->get("ObjectPlacement")->isNull()) { - auto item = mapping->map(*product->get("ObjectPlacement")); + if (!product->get("ObjectPlacement").isNull()) { + auto item = mapping->map(product->get("ObjectPlacement")); auto matrix = ifcopenshell::geometry::taxonomy::cast(item); gp_Trsf trsf; if (matrix) { @@ -2363,10 +2363,10 @@ void SvgSerializer::setSectionHeightsFromStoreys(double offset) { if (storeys && storeys->size() > 0) { for (auto& s : *storeys) { auto attr_value = ((IfcUtil::IfcBaseEntity*)s)->get("Elevation"); - if (!attr_value->isNull()) { + if (!attr_value.isNull()) { double elev; try { - elev = *attr_value; + elev = attr_value; } catch (std::exception& e) { Logger::Error(e); continue; diff --git a/src/serializers/SvgSerializer.h b/src/serializers/SvgSerializer.h index 75373097a1..b7269125f1 100644 --- a/src/serializers/SvgSerializer.h +++ b/src/serializers/SvgSerializer.h @@ -77,12 +77,12 @@ struct storey_sorter { if (a_is_storey && b_is_storey) { boost::optional a_elev, b_elev; try { - a_elev = static_cast(*a->get("Elevation")); - b_elev = static_cast(*b->get("Elevation")); + a_elev = static_cast(a->get("Elevation")); + b_elev = static_cast(b->get("Elevation")); } catch (...) {}; if (a_elev && b_elev) { if (std::equal_to()(*a_elev, *b_elev)) { - return std::less()(a->data().id(), b->data().id()); + return std::less()(a->id(), b->id()); } else { return std::less()(*a_elev, *b_elev); } @@ -90,12 +90,12 @@ struct storey_sorter { boost::optional a_name, b_name; try { - a_name = static_cast(*a->get("Name")); - b_name = static_cast(*b->get("Name")); + a_name = static_cast(a->get("Name")); + b_name = static_cast(b->get("Name")); } catch (...) {}; if (a_name && b_name) { if (std::equal_to()(*a_name, *b_name)) { - return std::less()(a->data().id(), b->data().id()); + return std::less()(a->id(), b->id()); } else { return std::less()(*a_name, *b_name); } diff --git a/src/serializers/schema_dependent/XmlSerializer.cpp b/src/serializers/schema_dependent/XmlSerializer.cpp index a5d68340c8..489ffde09e 100644 --- a/src/serializers/schema_dependent/XmlSerializer.cpp +++ b/src/serializers/schema_dependent/XmlSerializer.cpp @@ -57,7 +57,7 @@ std::map POSTFIX_SCHEMA(argument_name_map); // Format an IFC attribute and maybe returns as string. Only literal scalar // values are converted. Things like entity instances and lists are omitted. -boost::optional format_attribute(ifcopenshell::geometry::abstract_mapping* mapping, const Argument* argument, IfcUtil::ArgumentType argument_type, const std::string& argument_name) { +boost::optional format_attribute(ifcopenshell::geometry::abstract_mapping* mapping, AttributeValue argument, IfcUtil::ArgumentType argument_type, const std::string& argument_name) { boost::optional value; // Hard-code lat-lon as it represents an array @@ -65,7 +65,7 @@ boost::optional format_attribute(ifcopenshell::geometry::abstract_m if (argument_name == "IfcSite.RefLatitude" || argument_name == "IfcSite.RefLongitude") { - std::vector angle = *argument; + std::vector angle = argument; double deg; if (angle.size() >= 3) { deg = angle[0] + angle[1] / 60. + angle[2] / 3600.; @@ -83,30 +83,30 @@ boost::optional format_attribute(ifcopenshell::geometry::abstract_m switch(argument_type) { case IfcUtil::Argument_BOOL: { - const bool b = *argument; + const bool b = argument; value = b ? "true" : "false"; break; } case IfcUtil::Argument_DOUBLE: { - const double d = *argument; + const double d = argument; std::stringstream stream; stream << std::setprecision (std::numeric_limits< double >::max_digits10) << d; value = stream.str(); break; } case IfcUtil::Argument_STRING: case IfcUtil::Argument_ENUMERATION: { - value = static_cast(*argument); + value = static_cast(argument); break; } case IfcUtil::Argument_INT: { - const int v = *argument; + const int v = argument; std::stringstream stream; stream << v; value = stream.str(); break; } case IfcUtil::Argument_ENTITY_INSTANCE: { - IfcUtil::IfcBaseClass* e = *argument; + IfcUtil::IfcBaseClass* e = argument; if (!e->declaration().as_entity()) { IfcUtil::IfcBaseType* f = e->as(); - value = format_attribute(mapping, f->data().getArgument(0), f->data().getArgument(0)->type(), argument_name); + value = format_attribute(mapping, f->data().get_attribute_value(0), f->data().get_attribute_value(0).type(), argument_name); } else if (e->declaration().is(IfcSchema::IfcSIUnit::Class()) || e->declaration().is(IfcSchema::IfcConversionBasedUnit::Class())) { // Some string concatenation to have a unit name as a XML attribute. @@ -155,13 +155,13 @@ ptree* format_entity_instance(ifcopenshell::geometry::abstract_mapping* mapping, const unsigned n = instance->declaration().attribute_count(); for (unsigned i = 0; i < n; ++i) { try { - instance->data().getArgument(i); + instance->data().get_attribute_value(i); } catch (const std::exception&) { Logger::Error("Expected " + boost::lexical_cast(n) + " attributes for:", instance); break; } - const Argument* argument = instance->data().getArgument(i); - if (argument->isNull()) continue; + auto argument = instance->data().get_attribute_value(i); + if (argument.isNull()) continue; std::string argument_name = instance->declaration().attribute_by_index(i)->name(); std::map::const_iterator argument_name_it; @@ -169,7 +169,7 @@ ptree* format_entity_instance(ifcopenshell::geometry::abstract_mapping* mapping, if (argument_name_it != POSTFIX_SCHEMA(argument_name_map).end()) { argument_name = argument_name_it->second; } - const IfcUtil::ArgumentType argument_type = instance->data().getArgument(i)->type(); + const IfcUtil::ArgumentType argument_type = instance->data().get_attribute_value(i).type(); const std::string qualified_name = instance->declaration().name() + "." + argument_name; boost::optional value; @@ -202,7 +202,7 @@ ptree* format_entity_instance(ifcopenshell::geometry::abstract_mapping* mapping, } std::string qualify_unrooted_instance(IfcUtil::IfcBaseInterface* inst) { - return inst->declaration().name() + "_" + boost::lexical_cast(inst->data().id()); + return inst->declaration().name() + "_" + boost::lexical_cast(inst->as()->id()); } // A function to be called recursively. Template specialization is used