Compare commits

...

33 Commits

Author SHA1 Message Date
Thomas Krijnen f40d147830 Cheat 2024-08-23 20:15:21 +02:00
Thomas Krijnen f0ecf2d3d5 black 2024-08-23 20:03:02 +02:00
Thomas Krijnen 246989170c Fix test files actually 2024-08-23 20:02:14 +02:00
Thomas Krijnen c143546903 Copy shared_ptr objects in copy constructor and don't use moved out data 2024-08-23 19:57:05 +02:00
Thomas Krijnen 6052f48b88 Merge remote-tracking branch 'origin/v0.8.0' into tfk-unify-variant-storage 2024-08-23 16:10:14 +02:00
Thomas Krijnen 0445110778 For the love of god, add support for selected enumerations 2024-08-23 16:05:59 +02:00
Thomas Krijnen c032178753 Log and validate invalid attribute counts - 0 for header entities 2024-08-23 15:01:47 +02:00
Thomas Krijnen 09d9c6bd4b Log and validate invalid attribute counts 2024-08-23 14:29:49 +02:00
Thomas Krijnen 27cd362568 Don't fail on retrieving id of simpletypes 2024-08-23 13:58:48 +02:00
Thomas Krijnen 2da34deaf1 Temp disable ifc-xml 2024-08-23 13:58:28 +02:00
Thomas Krijnen 4f0297d8b2 Re-enable explicit tagging and validation of derived in subtype 2024-08-23 13:58:12 +02:00
Thomas Krijnen 74a2d50d97 Unused include 2024-08-23 11:25:44 +02:00
Thomas Krijnen 9c38a7c58b Don't fail on invalid enumeration literal 2024-08-23 11:25:14 +02:00
Thomas Krijnen 8b8663eb8e Bool to logical upgrade 2024-08-23 09:58:21 +02:00
Thomas Krijnen 43becceb94 Handle references to missing instances gracefully 2024-08-23 09:07:29 +02:00
Thomas Krijnen 4ba253a19b Add missing explicit instantiation 2024-08-23 09:06:23 +02:00
Thomas Krijnen f9a02829b6 Fixes for arrays of simple type 2024-08-22 13:35:12 +02:00
Thomas Krijnen 7d2066e7c2 Don't eat opening parens on nested list 2024-08-22 12:07:00 +02:00
Thomas Krijnen 1534e7962e Revert wrongfully applied parts 2024-08-21 20:24:17 +02:00
Thomas Krijnen 952ba717e6 Submodule 2024-08-21 20:14:33 +02:00
Thomas Krijnen 600e9e0a4b Submodule 2024-08-21 19:22:43 +02:00
Thomas Krijnen 0694d34707 Submodule 2024-08-21 19:17:57 +02:00
Thomas Krijnen e5bb1b98ed gltf and cityjson/validation fixes 2024-08-21 18:31:03 +02:00
Thomas Krijnen 3d8874559d Changes after merge and fixes for examples 2024-08-21 15:38:03 +02:00
Thomas Krijnen ad62a5fdef Fixes after merge 2024-08-21 11:26:49 +02:00
Thomas Krijnen e0f5adfb7e Merge branch 'v0.8.0' into tfk-unify-variant-storage 2024-08-21 11:24:56 +02:00
Thomas Krijnen fac13f1e1f clang-tidy 2024-08-21 11:22:18 +02:00
Thomas Krijnen 2e27ff64b4 Fixes for compilation on clang 2024-08-21 08:48:39 +02:00
Thomas Krijnen 261fb895eb WIP 2024-08-20 20:21:35 +02:00
Thomas Krijnen 9c323f91dd WIP 2024-08-16 09:25:16 +02:00
Thomas Krijnen debb0f5e59 WIP 2024-08-14 12:34:42 +02:00
Thomas Krijnen 054ccf9a05 WIP 2024-08-01 04:12:10 +02:00
Thomas Krijnen 53e0f40cb9 WIP 2024-08-01 03:54:59 +02:00
107 changed files with 118028 additions and 142394 deletions
+13 -11
View File
@@ -22,6 +22,7 @@
#include "../ifcparse/IfcFile.h"
#include "../ifcparse/IfcLogger.h"
#include "../ifcparse/Ifc2x3.h"
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
@@ -79,31 +80,31 @@ struct is_ifc4_or_higher<T, std::void_t<decltype(T::IfcMaterialDefinition)>> : s
typedef std::map<std::string, std::map<std::string, std::string>> element_properties;
std::string format_string(const Argument* argument) {
std::string format_string(const AttributeValue& argument) {
// Argument is a runtime tagged variant for the various data types in a IFC model,
// in this particular case we only care about flattening it to a string.
// @todo mostly duplicated from XmlSerializer.cpp
if (argument->isNull()) {
if (argument.isNull()) {
return "-";
}
auto argument_type = argument->type();
auto argument_type = argument.type();
switch (argument_type) {
case IfcUtil::Argument_BOOL: {
const bool b = *argument;
const bool b = argument;
return b ? "true" : "false";
}
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;
return stream.str();
break; }
case IfcUtil::Argument_STRING:
case IfcUtil::Argument_ENUMERATION: {
return static_cast<std::string>(*argument);
return static_cast<std::string>(argument);
break; }
case IfcUtil::Argument_INT: {
const int v = *argument;
const int v = argument;
std::stringstream stream;
stream << v;
return stream.str();
@@ -136,7 +137,7 @@ void process_pset(element_properties& props, const T* inst) {
if (!singleval->NominalValue()) {
propvalue = "-";
} else {
props[*pset->Name()][propname] = format_string(singleval->NominalValue()->template as<IfcUtil::IfcBaseClass>()->data().getArgument(0));
props[*pset->Name()][propname] = format_string(singleval->NominalValue()->template as<IfcUtil::IfcBaseClass>()->data().get_attribute_value(0));
}
}
}
@@ -148,8 +149,8 @@ void process_pset(element_properties& props, const T* inst) {
auto qs = qset->Quantities();
for (auto it = qs->begin(); it != qs->end(); ++it) {
auto& q = *it;
if (q->template as<typename Schema::IfcPhysicalSimpleQuantity>() && q->data().getArgument(3)->type() == IfcUtil::Argument_DOUBLE) {
double v = *q->data().getArgument(3);
if (q->template as<typename Schema::IfcPhysicalSimpleQuantity>() && q->data().get_attribute_value(3).type() == IfcUtil::Argument_DOUBLE) {
double v = q->data().get_attribute_value(3);
props[*qset->Name()][q->Name()] = std::to_string(v);
}
}
@@ -264,7 +265,8 @@ int main(int argc, char** argv) {
for (auto it = elements->begin(); it != elements->end(); ++it) {
const auto* element = *it;
std::cout << element->data().toString() << std::endl;
element->toString(std::cout);
std::cout << std::endl;
const IfcSchema::IfcWindow* window;
if ((window = element->as<IfcSchema::IfcWindow>()) != 0) {
+6 -8
View File
@@ -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 <typename T>
@@ -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<T, IfcWrite::IfcWriteArgument::EnumerationReference>::value) {
if (attr_type->as_named_type() && attr_type->as_named_type()->declared_type()->as_enumeration_type() && !std::is_same<T, EnumerationReference>::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(decl, 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);
}
+1 -1
View File
@@ -471,7 +471,7 @@ struct intersection_validator {
}
std::stringstream ss;
ss << geom_object->product()->data().toString();
geom_object->product()->toString(ss);
auto sss = ss.str();
std::wcout << sss.c_str() << std::endl;
+12 -12
View File
@@ -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<IfcUtil::IfcBaseEntity>()->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<ifcopenshell::geometry::settings::ForceSpaceTransparency>().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<ifcopenshell::geometry::settings::DisableOpeningSubtractions>().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<IfcUtil::IfcBaseEntity>();
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<IfcUtil::IfcBaseEntity>()->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,
+5 -5
View File
@@ -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;
}
+4 -4
View File
@@ -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 {
+1 -1
View File
@@ -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<IfcUtil::IfcBaseEntity>()->id() : -1;
} else {
surface_styles_.push_back(-1.);
surface_styles_.push_back(-1.);
+4 -4
View File
@@ -518,7 +518,7 @@ namespace IfcGeom {
Logger::SetProduct(product);
IfcGeom::BRepElement* brep = static_cast<IfcGeom::BRepElement*>(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<IfcGeom::BRepElement*>(decorate_with_cache_(GeometrySerializer::READ_BREP, (std::string)product->get("GlobalId"), std::to_string(representation->instance->as<IfcUtil::IfcBaseEntity>()->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<IfcGeom::BRepElement*>(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<IfcGeom::BRepElement*>(decorate_with_cache_(GeometrySerializer::READ_BREP, (std::string)product2->get("GlobalId"), std::to_string(representation->instance->as<IfcUtil::IfcBaseEntity>()->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<std::string>("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
+2
View File
@@ -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<geometry_conversion_task>& tasks, std::vector<filter_t>& filters) = 0;
+5 -5
View File
@@ -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<IfcUtil::IfcBaseEntity>()->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<IfcUtil::IfcBaseEntity>()->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<IfcUtil::IfcBaseEntity>()->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<IfcUtil::IfcBaseEntity>()->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<IfcUtil::IfcBaseEntity>()->id(),
br->matrix,
new CgalShape(a_poly),
br->surface_style ? br->surface_style : first_item_style
@@ -408,7 +408,7 @@ bool IfcGeom::OpenCascadeKernel::convert_impl(const taxonomy::revolve::ptr r, If
TopoDS_Shape shape = BRepPrimAPI_MakeRevol(face, ax);
results.emplace_back(ConversionResult(
r->instance->data().id(),
r->instance->as<IfcUtil::IfcBaseEntity>()->id(),
r->matrix,
new OpenCascadeShape(shape),
r->surface_style
@@ -107,7 +107,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result::ptr br, Con
if (settings_.get<settings::DisableBooleanResult>().get()) {
results.emplace_back(IfcGeom::ConversionResult(
(int)br->instance->data().id(),
br->instance->as<IfcUtil::IfcBaseEntity>()->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<IfcUtil::IfcBaseEntity>()->id(),
br->matrix,
new OpenCascadeShape(a),
br->surface_style ? br->surface_style : first_item_style
@@ -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<IfcUtil::IfcBaseEntity>()->id(),
extrusion->matrix,
new OpenCascadeShape(shape),
extrusion->surface_style
+1 -1
View File
@@ -528,7 +528,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<IfcUtil::IfcBaseEntity>()->id(),
new OpenCascadeShape(shape),
face->surface_style
));
+1 -1
View File
@@ -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<IfcUtil::IfcBaseEntity>()->id(),
loft->matrix,
new OpenCascadeShape(shape),
loft->surface_style
+2 -2
View File
@@ -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<IfcUtil::IfcBaseEntity>()->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<TopoDS_Wire>(convert_curve(edge));
results.emplace_back(ConversionResult(
edge->instance->data().id(),
edge->instance->as<IfcUtil::IfcBaseEntity>()->id(),
new OpenCascadeShape(shape),
edge->surface_style
));
+1 -1
View File
@@ -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<IfcUtil::IfcBaseEntity>()->id(),
shell->matrix,
new OpenCascadeShape(shape),
shell->surface_style
+1 -1
View File
@@ -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<IfcUtil::IfcBaseEntity>()->id(),
solid->matrix,
new OpenCascadeShape(shape),
solid->surface_style
@@ -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<IfcUtil::IfcBaseEntity>()->id(),
scs->matrix,
new OpenCascadeShape(shape),
scs->surface_style
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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);
}
}
+2 -2
View File
@@ -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<size_t> 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<IfcSchema::IfcCompositeCurve>()->Segments()->size();
}
+12 -12
View File
@@ -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<IfcSchema::IfcProduct>());
products->push((*it)->file_->getInverse((*it)->id(), &IfcSchema::IfcProduct::Class(), -1)->as<IfcSchema::IfcProduct>());
}
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>();
IfcSchema::IfcRepresentation::list::ptr reps = item->file_->getInverse(item->id(), (&IfcSchema::IfcRepresentation::Class()), -1)->as<IfcSchema::IfcRepresentation>();
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>();
IfcSchema::IfcProduct::list::ptr ps = (*kt)->file_->getInverse((*kt)->id(), (&IfcSchema::IfcProduct::Class()), -1)->as<IfcSchema::IfcProduct>();
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;
}
@@ -303,7 +303,7 @@ const IfcUtil::IfcBaseEntity* mapping::get_single_material_association(const Ifc
if (associated_material->as<IfcSchema::IfcMaterialLayerSetUsage>() || associated_material->as<IfcSchema::IfcMaterialLayerSet>()) {
IfcSchema::IfcMaterialLayerSet* layerset;
if (auto *m = associated_material->as<IfcSchema::IfcMaterialLayerSetUsage>()) {
if (m->get("ForLayerSet")->isNull()) {
if (m->get("ForLayerSet").isNull()) {
Logger::Warning("Missing ForLayerSet for:", m);
return nullptr;
}
@@ -322,7 +322,7 @@ const IfcUtil::IfcBaseEntity* mapping::get_single_material_association(const Ifc
if (associated_material->as<IfcSchema::IfcMaterialProfileSetUsage>() || associated_material->as<IfcSchema::IfcMaterialProfileSet>()) {
IfcSchema::IfcMaterialProfileSet* profileset;
if (auto* m = associated_material->as<IfcSchema::IfcMaterialProfileSetUsage>()) {
if (m->get("ForProfileSet")->isNull()) {
if (m->get("ForProfileSet").isNull()) {
Logger::Warning("Missing ForProfileSet for:", m);
return nullptr;
}
@@ -523,7 +523,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;
@@ -553,7 +553,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 << "-";
}
@@ -693,8 +693,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<IfcSchema::IfcRelDecomposes>();
IfcUtil::IfcBaseEntity* ifc_objectdef;
@@ -827,11 +827,11 @@ void mapping::initialize_settings() {
// See if there is a context_id filter and whether the context is selected
if (settings_.get<settings::ContextIds>().has()) {
auto cids = settings_.get<settings::ContextIds>().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;
}
+3 -1
View File
@@ -588,7 +588,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<IfcUtil::IfcBaseClass>()->toString(oss);
o << std::string(indent + 4, ' ') << oss.str() << std::endl;
}
}
@@ -153,7 +153,7 @@ def parse(fn: str) -> mapping.Mapping:
special = ((not_paren_star_quote_special | CaselessLiteral("(") | CaselessLiteral(")") | CaselessLiteral("*") | CaselessLiteral("\"\""))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="special"))("special")
binary_literal = ((CaselessLiteral("%") + bit + ZeroOrMore(bit))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="binary_literal"))("binary_literal")
integer_literal = (digits)("integer_literal")
simple_id = ~CaselessKeyword("bag") + ~CaselessKeyword("lobound") + ~CaselessKeyword("aggregate") + ~CaselessKeyword("reference") + ~CaselessKeyword("abstract") + ~CaselessKeyword("value_unique") + ~CaselessKeyword("if") + ~CaselessKeyword("loindex") + ~CaselessKeyword("format") + ~CaselessKeyword("true") + ~CaselessKeyword("insert") + ~CaselessKeyword("exp") + ~CaselessKeyword("end_type") + ~CaselessKeyword("end") + ~CaselessKeyword("optional") + ~CaselessKeyword("in") + ~CaselessKeyword("like") + ~CaselessKeyword("type") + ~CaselessKeyword("end_rule") + ~CaselessKeyword("repeat") + ~CaselessKeyword("nvl") + ~CaselessKeyword("otherwise") + ~CaselessKeyword("procedure") + ~CaselessKeyword("number") + ~CaselessKeyword("boolean") + ~CaselessKeyword("exists") + ~CaselessKeyword("andor") + ~CaselessKeyword("alias") + ~CaselessKeyword("entity") + ~CaselessKeyword("constant") + ~CaselessKeyword("tan") + ~CaselessKeyword("or") + ~CaselessKeyword("oneof") + ~CaselessKeyword("from") + ~CaselessKeyword("escape") + ~CaselessKeyword("typeof") + ~CaselessKeyword("extensible") + ~CaselessKeyword("div") + ~CaselessKeyword("then") + ~CaselessKeyword("by") + ~CaselessKeyword("unknown") + ~CaselessKeyword("var") + ~CaselessKeyword("pi") + ~CaselessKeyword("inverse") + ~CaselessKeyword("skip") + ~CaselessKeyword("array") + ~CaselessKeyword("end_subtype_constraint") + ~CaselessKeyword("use") + ~CaselessKeyword("self") + ~CaselessKeyword("end_alias") + ~CaselessKeyword("select") + ~CaselessKeyword("for") + ~CaselessKeyword("sizeof") + ~CaselessKeyword("fixed") + ~CaselessKeyword("local") + ~CaselessKeyword("remove") + ~CaselessKeyword("enumeration") + ~CaselessKeyword("end_local") + ~CaselessKeyword("not") + ~CaselessKeyword("function") + ~CaselessKeyword("cos") + ~CaselessKeyword("logical") + ~CaselessKeyword("query") + ~CaselessKeyword("atan") + ~CaselessKeyword("return") + ~CaselessKeyword("schema") + ~CaselessKeyword("hiindex") + ~CaselessKeyword("rolesof") + ~CaselessKeyword("log10") + ~CaselessKeyword("end_function") + ~CaselessKeyword("abs") + ~CaselessKeyword("length") + ~CaselessKeyword("renamed") + ~CaselessKeyword("acos") + ~CaselessKeyword("end_case") + ~CaselessKeyword("case") + ~CaselessKeyword("mod") + ~CaselessKeyword("end_if") + ~CaselessKeyword("list") + ~CaselessKeyword("end_repeat") + ~CaselessKeyword("generic") + ~CaselessKeyword("of") + ~CaselessKeyword("supertype") + ~CaselessKeyword("false") + ~CaselessKeyword("end_entity") + ~CaselessKeyword("odd") + ~CaselessKeyword("integer") + ~CaselessKeyword("hibound") + ~CaselessKeyword("rule") + ~CaselessKeyword("as") + ~CaselessKeyword("derive") + ~CaselessKeyword("log") + ~CaselessKeyword("set") + ~CaselessKeyword("subtype_constraint") + ~CaselessKeyword("unique") + ~CaselessKeyword("value") + ~CaselessKeyword("subtype") + ~CaselessKeyword("until") + ~CaselessKeyword("with") + ~CaselessKeyword("sqrt") + ~CaselessKeyword("where") + ~CaselessKeyword("value_in") + ~CaselessKeyword("to") + ~CaselessKeyword("xor") + ~CaselessKeyword("sin") + ~CaselessKeyword("while") + ~CaselessKeyword("string") + ~CaselessKeyword("usedin") + ~CaselessKeyword("total_over") + ~CaselessKeyword("binary") + ~CaselessKeyword("and") + ~CaselessKeyword("end_schema") + ~CaselessKeyword("generic_entity") + ~CaselessKeyword("end_constant") + ~CaselessKeyword("const_e") + ~CaselessKeyword("based_on") + ~CaselessKeyword("else") + ~CaselessKeyword("asin") + ~CaselessKeyword("blength") + ~CaselessKeyword("real") + ~CaselessKeyword("end_procedure") + ~CaselessKeyword("log2") + ~CaselessKeyword("begin") + originalTextFor(Combine((letter + ZeroOrMore((letter | digit | CaselessLiteral("_"))))))("simple_id")
simple_id = ~CaselessKeyword("generic") + ~CaselessKeyword("value") + ~CaselessKeyword("case") + ~CaselessKeyword("for") + ~CaselessKeyword("sin") + ~CaselessKeyword("value_unique") + ~CaselessKeyword("extensible") + ~CaselessKeyword("tan") + ~CaselessKeyword("local") + ~CaselessKeyword("string") + ~CaselessKeyword("procedure") + ~CaselessKeyword("derive") + ~CaselessKeyword("end_if") + ~CaselessKeyword("supertype") + ~CaselessKeyword("entity") + ~CaselessKeyword("oneof") + ~CaselessKeyword("constant") + ~CaselessKeyword("end_case") + ~CaselessKeyword("end_alias") + ~CaselessKeyword("unknown") + ~CaselessKeyword("total_over") + ~CaselessKeyword("div") + ~CaselessKeyword("type") + ~CaselessKeyword("true") + ~CaselessKeyword("end_repeat") + ~CaselessKeyword("unique") + ~CaselessKeyword("end_rule") + ~CaselessKeyword("number") + ~CaselessKeyword("end_function") + ~CaselessKeyword("where") + ~CaselessKeyword("self") + ~CaselessKeyword("usedin") + ~CaselessKeyword("end_type") + ~CaselessKeyword("logical") + ~CaselessKeyword("generic_entity") + ~CaselessKeyword("end_schema") + ~CaselessKeyword("xor") + ~CaselessKeyword("until") + ~CaselessKeyword("to") + ~CaselessKeyword("in") + ~CaselessKeyword("inverse") + ~CaselessKeyword("enumeration") + ~CaselessKeyword("var") + ~CaselessKeyword("value_in") + ~CaselessKeyword("const_e") + ~CaselessKeyword("use") + ~CaselessKeyword("exists") + ~CaselessKeyword("exp") + ~CaselessKeyword("while") + ~CaselessKeyword("if") + ~CaselessKeyword("fixed") + ~CaselessKeyword("subtype") + ~CaselessKeyword("format") + ~CaselessKeyword("as") + ~CaselessKeyword("and") + ~CaselessKeyword("rule") + ~CaselessKeyword("function") + ~CaselessKeyword("lobound") + ~CaselessKeyword("length") + ~CaselessKeyword("hiindex") + ~CaselessKeyword("log2") + ~CaselessKeyword("reference") + ~CaselessKeyword("skip") + ~CaselessKeyword("with") + ~CaselessKeyword("integer") + ~CaselessKeyword("sqrt") + ~CaselessKeyword("insert") + ~CaselessKeyword("nvl") + ~CaselessKeyword("log") + ~CaselessKeyword("boolean") + ~CaselessKeyword("from") + ~CaselessKeyword("rolesof") + ~CaselessKeyword("hibound") + ~CaselessKeyword("abs") + ~CaselessKeyword("like") + ~CaselessKeyword("pi") + ~CaselessKeyword("alias") + ~CaselessKeyword("not") + ~CaselessKeyword("repeat") + ~CaselessKeyword("based_on") + ~CaselessKeyword("subtype_constraint") + ~CaselessKeyword("asin") + ~CaselessKeyword("optional") + ~CaselessKeyword("list") + ~CaselessKeyword("abstract") + ~CaselessKeyword("mod") + ~CaselessKeyword("false") + ~CaselessKeyword("log10") + ~CaselessKeyword("loindex") + ~CaselessKeyword("aggregate") + ~CaselessKeyword("end_constant") + ~CaselessKeyword("end") + ~CaselessKeyword("sizeof") + ~CaselessKeyword("remove") + ~CaselessKeyword("acos") + ~CaselessKeyword("set") + ~CaselessKeyword("renamed") + ~CaselessKeyword("end_local") + ~CaselessKeyword("of") + ~CaselessKeyword("escape") + ~CaselessKeyword("begin") + ~CaselessKeyword("select") + ~CaselessKeyword("end_procedure") + ~CaselessKeyword("else") + ~CaselessKeyword("end_subtype_constraint") + ~CaselessKeyword("cos") + ~CaselessKeyword("real") + ~CaselessKeyword("query") + ~CaselessKeyword("odd") + ~CaselessKeyword("andor") + ~CaselessKeyword("return") + ~CaselessKeyword("then") + ~CaselessKeyword("end_entity") + ~CaselessKeyword("array") + ~CaselessKeyword("blength") + ~CaselessKeyword("or") + ~CaselessKeyword("typeof") + ~CaselessKeyword("binary") + ~CaselessKeyword("atan") + ~CaselessKeyword("by") + ~CaselessKeyword("otherwise") + ~CaselessKeyword("bag") + ~CaselessKeyword("schema") + originalTextFor(Combine((letter + ZeroOrMore((letter | digit | CaselessLiteral("_"))))))("simple_id")
simple_string_literal = ((CaselessLiteral("'") + ZeroOrMore(((CaselessLiteral("'") + CaselessLiteral("'")) | not_quote)) + CaselessLiteral("'")))("simple_string_literal")
abstract_entity_declaration = (ABSTRACT)("abstract_entity_declaration")
abstract_supertype = ((ABSTRACT + SUPERTYPE + CaselessLiteral(";"))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="abstract_supertype"))("abstract_supertype")
@@ -251,224 +251,224 @@ def parse(fn: str) -> mapping.Mapping:
constructed_types = ((enumeration_type | select_type)).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="constructed_types"))("constructed_types")
reference_clause = ((REFERENCE + FROM + schema_ref + Optional((CaselessLiteral("(") + resource_or_rename + ZeroOrMore((CaselessLiteral(",") + resource_or_rename)) + CaselessLiteral(")"))) + CaselessLiteral(";"))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="reference_clause"))("reference_clause")
interface_specification = ((reference_clause | use_clause)).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="interface_specification"))("interface_specification")
stmt = Forward()("stmt")
general_aggregation_types = Forward()("general_aggregation_types")
procedure_call_stmt = Forward()("procedure_call_stmt")
inverse_attr = Forward()("inverse_attr")
derived_attr = Forward()("derived_attr")
width_spec = Forward()("width_spec")
actual_parameter_list = Forward()("actual_parameter_list")
type_decl = Forward()("type_decl")
selector = Forward()("selector")
abstract_supertype_declaration = Forward()("abstract_supertype_declaration")
explicit_attr = Forward()("explicit_attr")
aggregation_types = Forward()("aggregation_types")
domain_rule = Forward()("domain_rule")
entity_constructor = Forward()("entity_constructor")
function_call = Forward()("function_call")
numeric_expression = Forward()("numeric_expression")
general_set_type = Forward()("general_set_type")
qualifier = Forward()("qualifier")
formal_parameter = Forward()("formal_parameter")
index_1 = Forward()("index_1")
underlying_type = Forward()("underlying_type")
local_variable = Forward()("local_variable")
aggregate_source = Forward()("aggregate_source")
while_control = Forward()("while_control")
interval_low = Forward()("interval_low")
parameter = Forward()("parameter")
precision_spec = Forward()("precision_spec")
one_of = Forward()("one_of")
subtype_constraint_body = Forward()("subtype_constraint_body")
general_array_type = Forward()("general_array_type")
list_type = Forward()("list_type")
subtype_constraint_decl = Forward()("subtype_constraint_decl")
schema_decl = Forward()("schema_decl")
algorithm_head = Forward()("algorithm_head")
query_expression = Forward()("query_expression")
primary = Forward()("primary")
repeat_control = Forward()("repeat_control")
factor = Forward()("factor")
procedure_head = Forward()("procedure_head")
aggregate_type = Forward()("aggregate_type")
supertype_factor = Forward()("supertype_factor")
interval_item = Forward()("interval_item")
subtype_constraint = Forward()("subtype_constraint")
repeat_stmt = Forward()("repeat_stmt")
entity_body = Forward()("entity_body")
interval_high = Forward()("interval_high")
logical_expression = Forward()("logical_expression")
simple_expression = Forward()("simple_expression")
subsuper = Forward()("subsuper")
increment = Forward()("increment")
remark = Forward()("remark")
simple_factor = Forward()("simple_factor")
case_stmt = Forward()("case_stmt")
derive_clause = Forward()("derive_clause")
supertype_constraint = Forward()("supertype_constraint")
assignment_stmt = Forward()("assignment_stmt")
entity_head = Forward()("entity_head")
set_type = Forward()("set_type")
instantiable_type = Forward()("instantiable_type")
increment_control = Forward()("increment_control")
local_variable = Forward()("local_variable")
until_control = Forward()("until_control")
while_control = Forward()("while_control")
parameter = Forward()("parameter")
width = Forward()("width")
string_type = Forward()("string_type")
array_type = Forward()("array_type")
if_stmt = Forward()("if_stmt")
index = Forward()("index")
repetition = Forward()("repetition")
index_qualifier = Forward()("index_qualifier")
bound_1 = Forward()("bound_1")
procedure_decl = Forward()("procedure_decl")
entity_constructor = Forward()("entity_constructor")
inverse_clause = Forward()("inverse_clause")
function_head = Forward()("function_head")
formal_parameter = Forward()("formal_parameter")
interval_high = Forward()("interval_high")
entity_decl = Forward()("entity_decl")
abstract_supertype_declaration = Forward()("abstract_supertype_declaration")
index_1 = Forward()("index_1")
general_aggregation_types = Forward()("general_aggregation_types")
real_type = Forward()("real_type")
type_decl = Forward()("type_decl")
stmt = Forward()("stmt")
declaration = Forward()("declaration")
binary_type = Forward()("binary_type")
interval = Forward()("interval")
explicit_attr = Forward()("explicit_attr")
compound_stmt = Forward()("compound_stmt")
aggregation_types = Forward()("aggregation_types")
simple_factor = Forward()("simple_factor")
where_clause = Forward()("where_clause")
entity_head = Forward()("entity_head")
underlying_type = Forward()("underlying_type")
subtype_constraint_decl = Forward()("subtype_constraint_decl")
logical_expression = Forward()("logical_expression")
case_label = Forward()("case_label")
expression = Forward()("expression")
general_list_type = Forward()("general_list_type")
actual_parameter_list = Forward()("actual_parameter_list")
width_spec = Forward()("width_spec")
selector = Forward()("selector")
syntax = Forward()("syntax")
aggregate_source = Forward()("aggregate_source")
return_stmt = Forward()("return_stmt")
embedded_remark = Forward()("embedded_remark")
parameter_type = Forward()("parameter_type")
term = Forward()("term")
index = Forward()("index")
expression = Forward()("expression")
derived_attr = Forward()("derived_attr")
repeat_control = Forward()("repeat_control")
assignment_stmt = Forward()("assignment_stmt")
bag_type = Forward()("bag_type")
schema_body = Forward()("schema_body")
until_control = Forward()("until_control")
simple_types = Forward()("simple_types")
subsuper = Forward()("subsuper")
entity_decl = Forward()("entity_decl")
concrete_types = Forward()("concrete_types")
element = Forward()("element")
general_bag_type = Forward()("general_bag_type")
interval_item = Forward()("interval_item")
inverse_attr = Forward()("inverse_attr")
constant_body = Forward()("constant_body")
increment = Forward()("increment")
case_label = Forward()("case_label")
case_action = Forward()("case_action")
width = Forward()("width")
procedure_decl = Forward()("procedure_decl")
increment_control = Forward()("increment_control")
index_qualifier = Forward()("index_qualifier")
constant_decl = Forward()("constant_decl")
supertype_rule = Forward()("supertype_rule")
syntax = Forward()("syntax")
function_head = Forward()("function_head")
repetition = Forward()("repetition")
if_stmt = Forward()("if_stmt")
supertype_expression = Forward()("supertype_expression")
inverse_clause = Forward()("inverse_clause")
aggregate_initializer = Forward()("aggregate_initializer")
return_stmt = Forward()("return_stmt")
generalized_types = Forward()("generalized_types")
bound_2 = Forward()("bound_2")
real_type = Forward()("real_type")
index_2 = Forward()("index_2")
array_type = Forward()("array_type")
local_decl = Forward()("local_decl")
supertype_term = Forward()("supertype_term")
where_clause = Forward()("where_clause")
embedded_remark = Forward()("embedded_remark")
compound_stmt = Forward()("compound_stmt")
bound_1 = Forward()("bound_1")
alias_stmt = Forward()("alias_stmt")
subtype_constraint = Forward()("subtype_constraint")
string_type = Forward()("string_type")
function_decl = Forward()("function_decl")
general_list_type = Forward()("general_list_type")
supertype_factor = Forward()("supertype_factor")
rule_decl = Forward()("rule_decl")
precision_spec = Forward()("precision_spec")
general_bag_type = Forward()("general_bag_type")
qualifiable_factor = Forward()("qualifiable_factor")
bound_2 = Forward()("bound_2")
instantiable_type = Forward()("instantiable_type")
general_set_type = Forward()("general_set_type")
supertype_rule = Forward()("supertype_rule")
factor = Forward()("factor")
list_type = Forward()("list_type")
one_of = Forward()("one_of")
aggregate_type = Forward()("aggregate_type")
entity_body = Forward()("entity_body")
generalized_types = Forward()("generalized_types")
case_stmt = Forward()("case_stmt")
binary_type = Forward()("binary_type")
local_decl = Forward()("local_decl")
alias_stmt = Forward()("alias_stmt")
simple_expression = Forward()("simple_expression")
general_array_type = Forward()("general_array_type")
interval = Forward()("interval")
procedure_head = Forward()("procedure_head")
function_decl = Forward()("function_decl")
supertype_expression = Forward()("supertype_expression")
set_type = Forward()("set_type")
primary = Forward()("primary")
procedure_call_stmt = Forward()("procedure_call_stmt")
simple_types = Forward()("simple_types")
query_expression = Forward()("query_expression")
index_2 = Forward()("index_2")
constant_decl = Forward()("constant_decl")
case_action = Forward()("case_action")
schema_body = Forward()("schema_body")
element = Forward()("element")
numeric_expression = Forward()("numeric_expression")
aggregate_initializer = Forward()("aggregate_initializer")
schema_decl = Forward()("schema_decl")
supertype_term = Forward()("supertype_term")
algorithm_head = Forward()("algorithm_head")
supertype_constraint = Forward()("supertype_constraint")
interval_low = Forward()("interval_low")
domain_rule = Forward()("domain_rule")
rule_decl = Forward()("rule_decl")
concrete_types = Forward()("concrete_types")
qualifier = Forward()("qualifier")
subtype_constraint_body = Forward()("subtype_constraint_body")
function_call = Forward()("function_call")
bound_spec = Forward()("bound_spec")
stmt << (((alias_stmt | assignment_stmt | case_stmt | compound_stmt | escape_stmt | if_stmt | null_stmt | procedure_call_stmt | repeat_stmt | return_stmt | skip_stmt))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="stmt"))
general_aggregation_types << (((general_array_type | general_bag_type | general_list_type | general_set_type))).setParseAction(AggregationType)
procedure_call_stmt << ((((built_in_procedure | procedure_ref) + actual_parameter_list + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="procedure_call_stmt"))
inverse_attr << (((attribute_decl + CaselessLiteral(":") + Optional(((SET | BAG) + Optional(bound_spec) + OF)) + entity_ref + FOR + Optional((entity_ref + CaselessLiteral("."))) + attribute_ref + CaselessLiteral(";")))).setParseAction(InverseAttribute)
derived_attr << (((attribute_decl + CaselessLiteral(":") + parameter_type + CaselessLiteral(":=") + expression + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="derived_attr"))
width_spec << (((CaselessLiteral("(") + width + CaselessLiteral(")") + Optional(FIXED)))).setParseAction(WidthSpec)
actual_parameter_list << (((CaselessLiteral("(") + Optional(parameter) + ZeroOrMore((CaselessLiteral(",") + parameter)) + CaselessLiteral(")")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="actual_parameter_list"))
type_decl << (((TYPE + type_id + CaselessLiteral("=") + underlying_type + CaselessLiteral(";") + Optional(where_clause) + END_TYPE + CaselessLiteral(";")))).setParseAction(TypeDeclaration)
selector << (expression)
abstract_supertype_declaration << (((ABSTRACT + SUPERTYPE + Optional(subtype_constraint)))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="abstract_supertype_declaration"))
explicit_attr << (((attribute_decl + ZeroOrMore((CaselessLiteral(",") + attribute_decl)) + CaselessLiteral(":") + Optional(OPTIONAL) + parameter_type + CaselessLiteral(";")))).setParseAction(ExplicitAttribute)
aggregation_types << (((array_type | bag_type | list_type | set_type))).setParseAction(AggregationType)
domain_rule << (((Optional((rule_label_id + CaselessLiteral(":"))) + expression))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="domain_rule"))
entity_constructor << (((entity_ref + CaselessLiteral("(") + Optional((expression + ZeroOrMore((CaselessLiteral(",") + expression)))) + CaselessLiteral(")")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="entity_constructor"))
function_call << ((((built_in_function | function_ref) + actual_parameter_list))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="function_call"))
numeric_expression << (simple_expression)
general_set_type << (((SET + Optional(bound_spec) + OF + parameter_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="general_set_type"))
qualifier << (((attribute_qualifier | group_qualifier | index_qualifier))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="qualifier"))
formal_parameter << (((parameter_id + ZeroOrMore((CaselessLiteral(",") + parameter_id)) + CaselessLiteral(":") + parameter_type))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="formal_parameter"))
index_1 << (index)
underlying_type << (((constructed_types | concrete_types))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="underlying_type"))
local_variable << (((variable_id + ZeroOrMore((CaselessLiteral(",") + variable_id)) + CaselessLiteral(":") + parameter_type + Optional((CaselessLiteral(":=") + expression)) + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="local_variable"))
aggregate_source << (simple_expression)
while_control << (((WHILE + logical_expression))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="while_control"))
interval_low << (simple_expression)
parameter << (expression)
precision_spec << (numeric_expression)
one_of << (((ONEOF + CaselessLiteral("(") + supertype_expression + ZeroOrMore((CaselessLiteral(",") + supertype_expression)) + CaselessLiteral(")")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="one_of"))
subtype_constraint_body << (((Optional(abstract_supertype) + Optional(total_over) + Optional((supertype_expression + CaselessLiteral(";")))))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="subtype_constraint_body"))
general_array_type << (((ARRAY + Optional(bound_spec) + OF + Optional(OPTIONAL) + Optional(UNIQUE) + parameter_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="general_array_type"))
list_type << (((LIST + Optional(bound_spec) + OF + Optional(UNIQUE) + instantiable_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="list_type"))
subtype_constraint_decl << (((subtype_constraint_head + subtype_constraint_body + END_SUBTYPE_CONSTRAINT + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="subtype_constraint_decl"))
schema_decl << (((SCHEMA + schema_id + Optional(schema_version_id) + CaselessLiteral(";") + schema_body + END_SCHEMA + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="schema_decl"))
algorithm_head << (((ZeroOrMore(declaration) + Optional(constant_decl) + Optional(local_decl)))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="algorithm_head"))
query_expression << (((QUERY + CaselessLiteral("(") + variable_id + CaselessLiteral("<*") + aggregate_source + CaselessLiteral("|") + logical_expression + CaselessLiteral(")")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="query_expression"))
primary << (((literal | (qualifiable_factor + ZeroOrMore(qualifier))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="primary"))
repeat_control << (((Optional(increment_control) + Optional(while_control) + Optional(until_control)))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="repeat_control"))
factor << (((simple_factor + Optional((CaselessLiteral("**") + simple_factor))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="factor"))
procedure_head << (((PROCEDURE + procedure_id + Optional((CaselessLiteral("(") + Optional(VAR) + formal_parameter + ZeroOrMore((CaselessLiteral(";") + Optional(VAR) + formal_parameter)) + CaselessLiteral(")"))) + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="procedure_head"))
aggregate_type << (((AGGREGATE + Optional((CaselessLiteral(":") + type_label)) + OF + parameter_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="aggregate_type"))
derive_clause = Forward()("derive_clause")
supertype_factor << (((supertype_term + ZeroOrMore((AND + supertype_term))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="supertype_factor"))
interval_item << (simple_expression)
subtype_constraint << (((OF + CaselessLiteral("(") + supertype_expression + CaselessLiteral(")")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="subtype_constraint"))
repeat_stmt << (((REPEAT + repeat_control + CaselessLiteral(";") + stmt + ZeroOrMore(stmt) + END_REPEAT + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="repeat_stmt"))
entity_body << (((ZeroOrMore(explicit_attr) + Optional(derive_clause) + Optional(inverse_clause) + Optional(unique_clause) + Optional(where_clause)))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="entity_body"))
interval_high << (simple_expression)
logical_expression << (expression)
simple_expression << (((term + ZeroOrMore((add_like_op + term))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="simple_expression"))
subsuper << (((Optional(supertype_constraint) + Optional(subtype_declaration)))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="subsuper"))
increment << (numeric_expression)
remark << (((embedded_remark | tail_remark))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="remark"))
simple_factor << (((aggregate_initializer | interval | query_expression | (Optional(unary_op) + ((CaselessLiteral("(") + expression + CaselessLiteral(")")) | primary)) | entity_constructor | enumeration_reference))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="simple_factor"))
case_stmt << (((CASE + selector + OF + ZeroOrMore(case_action) + Optional((OTHERWISE + CaselessLiteral(":") + stmt)) + END_CASE + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="case_stmt"))
derive_clause << (((DERIVE + derived_attr + ZeroOrMore(derived_attr)))).setParseAction(AttributeList)
supertype_constraint << (((abstract_supertype_declaration | abstract_entity_declaration | supertype_rule))).setParseAction(SuperTypeExpression)
assignment_stmt << (((general_ref + ZeroOrMore(qualifier) + CaselessLiteral(":=") + expression + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="assignment_stmt"))
entity_head << (((ENTITY + entity_id + subsuper + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="entity_head"))
set_type << (((SET + Optional(bound_spec) + OF + instantiable_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="set_type"))
instantiable_type << (((concrete_types | entity_ref))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="instantiable_type"))
increment_control << (((variable_id + CaselessLiteral(":=") + bound_1 + TO + bound_2 + Optional((BY + increment))))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="increment_control"))
local_variable << (((variable_id + ZeroOrMore((CaselessLiteral(",") + variable_id)) + CaselessLiteral(":") + parameter_type + Optional((CaselessLiteral(":=") + expression)) + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="local_variable"))
until_control << (((UNTIL + logical_expression))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="until_control"))
while_control << (((WHILE + logical_expression))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="while_control"))
parameter << (expression)
width << (numeric_expression)
string_type << (((STRING + Optional(width_spec)))).setParseAction(StringType)
array_type << (((ARRAY + bound_spec + OF + Optional(OPTIONAL) + Optional(UNIQUE) + instantiable_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="array_type"))
if_stmt << (((IF + logical_expression + THEN + stmt + ZeroOrMore(stmt) + Optional((ELSE + stmt + ZeroOrMore(stmt))) + END_IF + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="if_stmt"))
index << (numeric_expression)
repetition << (numeric_expression)
index_qualifier << (((CaselessLiteral("[") + index_1 + Optional((CaselessLiteral(":") + index_2)) + CaselessLiteral("]")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="index_qualifier"))
bound_1 << (numeric_expression)
procedure_decl << (((procedure_head + algorithm_head + ZeroOrMore(stmt) + END_PROCEDURE + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="procedure_decl"))
entity_constructor << (((entity_ref + CaselessLiteral("(") + Optional((expression + ZeroOrMore((CaselessLiteral(",") + expression)))) + CaselessLiteral(")")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="entity_constructor"))
inverse_clause << (((INVERSE + inverse_attr + ZeroOrMore(inverse_attr)))).setParseAction(AttributeList)
function_head << (((FUNCTION + function_id + Optional((CaselessLiteral("(") + formal_parameter + ZeroOrMore((CaselessLiteral(";") + formal_parameter)) + CaselessLiteral(")"))) + CaselessLiteral(":") + parameter_type + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="function_head"))
formal_parameter << (((parameter_id + ZeroOrMore((CaselessLiteral(",") + parameter_id)) + CaselessLiteral(":") + parameter_type))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="formal_parameter"))
interval_high << (simple_expression)
entity_decl << (((entity_head + entity_body + END_ENTITY + CaselessLiteral(";")))).setParseAction(EntityDeclaration)
abstract_supertype_declaration << (((ABSTRACT + SUPERTYPE + Optional(subtype_constraint)))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="abstract_supertype_declaration"))
index_1 << (index)
general_aggregation_types << (((general_array_type | general_bag_type | general_list_type | general_set_type))).setParseAction(AggregationType)
real_type << (((REAL + Optional((CaselessLiteral("(") + precision_spec + CaselessLiteral(")")))))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="real_type"))
type_decl << (((TYPE + type_id + CaselessLiteral("=") + underlying_type + CaselessLiteral(";") + Optional(where_clause) + END_TYPE + CaselessLiteral(";")))).setParseAction(TypeDeclaration)
stmt << (((alias_stmt | assignment_stmt | case_stmt | compound_stmt | escape_stmt | if_stmt | null_stmt | procedure_call_stmt | repeat_stmt | return_stmt | skip_stmt))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="stmt"))
declaration << (((entity_decl | function_decl | procedure_decl | subtype_constraint_decl | type_decl))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="declaration"))
binary_type << (((BINARY + Optional(width_spec)))).setParseAction(BinaryType)
interval << (((CaselessLiteral("{") + interval_low + interval_op + interval_item + interval_op + interval_high + CaselessLiteral("}")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="interval"))
explicit_attr << (((attribute_decl + ZeroOrMore((CaselessLiteral(",") + attribute_decl)) + CaselessLiteral(":") + Optional(OPTIONAL) + parameter_type + CaselessLiteral(";")))).setParseAction(ExplicitAttribute)
compound_stmt << (((BEGIN + stmt + ZeroOrMore(stmt) + END + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="compound_stmt"))
aggregation_types << (((array_type | bag_type | list_type | set_type))).setParseAction(AggregationType)
simple_factor << (((aggregate_initializer | interval | query_expression | (Optional(unary_op) + ((CaselessLiteral("(") + expression + CaselessLiteral(")")) | primary)) | entity_constructor | enumeration_reference))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="simple_factor"))
where_clause << (((WHERE + domain_rule + CaselessLiteral(";") + ZeroOrMore((domain_rule + CaselessLiteral(";")))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="where_clause"))
entity_head << (((ENTITY + entity_id + subsuper + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="entity_head"))
underlying_type << (((constructed_types | concrete_types))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="underlying_type"))
subtype_constraint_decl << (((subtype_constraint_head + subtype_constraint_body + END_SUBTYPE_CONSTRAINT + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="subtype_constraint_decl"))
logical_expression << (expression)
case_label << (expression)
expression << (((simple_expression + Optional((rel_op_extended + simple_expression))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="expression"))
general_list_type << (((LIST + Optional(bound_spec) + OF + Optional(UNIQUE) + parameter_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="general_list_type"))
actual_parameter_list << (((CaselessLiteral("(") + Optional(parameter) + ZeroOrMore((CaselessLiteral(",") + parameter)) + CaselessLiteral(")")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="actual_parameter_list"))
width_spec << (((CaselessLiteral("(") + width + CaselessLiteral(")") + Optional(FIXED)))).setParseAction(WidthSpec)
selector << (expression)
syntax << (((schema_decl + ZeroOrMore(schema_decl)))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="syntax"))
aggregate_source << (simple_expression)
return_stmt << (((RETURN + Optional((CaselessLiteral("(") + expression + CaselessLiteral(")"))) + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="return_stmt"))
embedded_remark << (((CaselessLiteral("(*") + Optional(remark_tag) + ZeroOrMore(((not_paren_star + ZeroOrMore(not_paren_star)) | lparen_then_not_lparen_star | (CaselessLiteral("*") + ZeroOrMore(CaselessLiteral("*"))) | not_rparen_star_then_rparen | embedded_remark)) + CaselessLiteral("*)")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="embedded_remark"))
parameter_type << (((generalized_types | simple_types | named_types))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="parameter_type"))
term << (((factor + ZeroOrMore((multiplication_like_op + factor))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="term"))
index << (numeric_expression)
expression << (((simple_expression + Optional((rel_op_extended + simple_expression))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="expression"))
derived_attr << (((attribute_decl + CaselessLiteral(":") + parameter_type + CaselessLiteral(":=") + expression + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="derived_attr"))
repeat_control << (((Optional(increment_control) + Optional(while_control) + Optional(until_control)))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="repeat_control"))
assignment_stmt << (((general_ref + ZeroOrMore(qualifier) + CaselessLiteral(":=") + expression + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="assignment_stmt"))
bag_type << (((BAG + Optional(bound_spec) + OF + instantiable_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="bag_type"))
schema_body << (((ZeroOrMore(interface_specification) + Optional(constant_decl) + ZeroOrMore((declaration | rule_decl))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="schema_body"))
until_control << (((UNTIL + logical_expression))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="until_control"))
simple_types << (((binary_type | boolean_type | integer_type | logical_type | number_type | real_type | string_type))).setParseAction(SimpleType)
subsuper << (((Optional(supertype_constraint) + Optional(subtype_declaration)))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="subsuper"))
entity_decl << (((entity_head + entity_body + END_ENTITY + CaselessLiteral(";")))).setParseAction(EntityDeclaration)
concrete_types << (((aggregation_types | simple_types | type_ref))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="concrete_types"))
element << (((expression + Optional((CaselessLiteral(":") + repetition))))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="element"))
general_bag_type << (((BAG + Optional(bound_spec) + OF + parameter_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="general_bag_type"))
interval_item << (simple_expression)
inverse_attr << (((attribute_decl + CaselessLiteral(":") + Optional(((SET | BAG) + Optional(bound_spec) + OF)) + entity_ref + FOR + Optional((entity_ref + CaselessLiteral("."))) + attribute_ref + CaselessLiteral(";")))).setParseAction(InverseAttribute)
constant_body << (((constant_id + CaselessLiteral(":") + instantiable_type + CaselessLiteral(":=") + expression + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="constant_body"))
increment << (numeric_expression)
case_label << (expression)
case_action << (((case_label + ZeroOrMore((CaselessLiteral(",") + case_label)) + CaselessLiteral(":") + stmt))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="case_action"))
width << (numeric_expression)
procedure_decl << (((procedure_head + algorithm_head + ZeroOrMore(stmt) + END_PROCEDURE + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="procedure_decl"))
increment_control << (((variable_id + CaselessLiteral(":=") + bound_1 + TO + bound_2 + Optional((BY + increment))))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="increment_control"))
index_qualifier << (((CaselessLiteral("[") + index_1 + Optional((CaselessLiteral(":") + index_2)) + CaselessLiteral("]")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="index_qualifier"))
constant_decl << (((CONSTANT + constant_body + ZeroOrMore(constant_body) + END_CONSTANT + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="constant_decl"))
supertype_rule << (((SUPERTYPE + subtype_constraint))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="supertype_rule"))
syntax << (((schema_decl + ZeroOrMore(schema_decl)))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="syntax"))
function_head << (((FUNCTION + function_id + Optional((CaselessLiteral("(") + formal_parameter + ZeroOrMore((CaselessLiteral(";") + formal_parameter)) + CaselessLiteral(")"))) + CaselessLiteral(":") + parameter_type + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="function_head"))
repetition << (numeric_expression)
if_stmt << (((IF + logical_expression + THEN + stmt + ZeroOrMore(stmt) + Optional((ELSE + stmt + ZeroOrMore(stmt))) + END_IF + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="if_stmt"))
supertype_expression << (((supertype_factor + ZeroOrMore((ANDOR + supertype_factor))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="supertype_expression"))
inverse_clause << (((INVERSE + inverse_attr + ZeroOrMore(inverse_attr)))).setParseAction(AttributeList)
aggregate_initializer << (((CaselessLiteral("[") + Optional((element + ZeroOrMore((CaselessLiteral(",") + element)))) + CaselessLiteral("]")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="aggregate_initializer"))
return_stmt << (((RETURN + Optional((CaselessLiteral("(") + expression + CaselessLiteral(")"))) + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="return_stmt"))
generalized_types << (((aggregate_type | general_aggregation_types | generic_entity_type | generic_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="generalized_types"))
bound_2 << (numeric_expression)
real_type << (((REAL + Optional((CaselessLiteral("(") + precision_spec + CaselessLiteral(")")))))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="real_type"))
index_2 << (index)
array_type << (((ARRAY + bound_spec + OF + Optional(OPTIONAL) + Optional(UNIQUE) + instantiable_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="array_type"))
local_decl << (((LOCAL + local_variable + ZeroOrMore(local_variable) + END_LOCAL + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="local_decl"))
supertype_term << (((one_of | (CaselessLiteral("(") + supertype_expression + CaselessLiteral(")")) | entity_ref))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="supertype_term"))
where_clause << (((WHERE + domain_rule + CaselessLiteral(";") + ZeroOrMore((domain_rule + CaselessLiteral(";")))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="where_clause"))
embedded_remark << (((CaselessLiteral("(*") + Optional(remark_tag) + ZeroOrMore(((not_paren_star + ZeroOrMore(not_paren_star)) | lparen_then_not_lparen_star | (CaselessLiteral("*") + ZeroOrMore(CaselessLiteral("*"))) | not_rparen_star_then_rparen | embedded_remark)) + CaselessLiteral("*)")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="embedded_remark"))
compound_stmt << (((BEGIN + stmt + ZeroOrMore(stmt) + END + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="compound_stmt"))
bound_1 << (numeric_expression)
alias_stmt << (((ALIAS + variable_id + FOR + general_ref + ZeroOrMore(qualifier) + CaselessLiteral(";") + stmt + ZeroOrMore(stmt) + END_ALIAS + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="alias_stmt"))
subtype_constraint << (((OF + CaselessLiteral("(") + supertype_expression + CaselessLiteral(")")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="subtype_constraint"))
string_type << (((STRING + Optional(width_spec)))).setParseAction(StringType)
function_decl << (((function_head + algorithm_head + stmt + ZeroOrMore(stmt) + END_FUNCTION + CaselessLiteral(";")))).setParseAction(FunctionDeclaration)
general_list_type << (((LIST + Optional(bound_spec) + OF + Optional(UNIQUE) + parameter_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="general_list_type"))
supertype_factor << (((supertype_term + ZeroOrMore((AND + supertype_term))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="supertype_factor"))
rule_decl << (((rule_head + algorithm_head + ZeroOrMore(stmt) + where_clause + END_RULE + CaselessLiteral(";")))).setParseAction(RuleDeclaration)
precision_spec << (numeric_expression)
general_bag_type << (((BAG + Optional(bound_spec) + OF + parameter_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="general_bag_type"))
qualifiable_factor << (((function_call | attribute_ref | constant_factor | general_ref | population))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="qualifiable_factor"))
bound_2 << (numeric_expression)
instantiable_type << (((concrete_types | entity_ref))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="instantiable_type"))
general_set_type << (((SET + Optional(bound_spec) + OF + parameter_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="general_set_type"))
supertype_rule << (((SUPERTYPE + subtype_constraint))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="supertype_rule"))
factor << (((simple_factor + Optional((CaselessLiteral("**") + simple_factor))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="factor"))
list_type << (((LIST + Optional(bound_spec) + OF + Optional(UNIQUE) + instantiable_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="list_type"))
one_of << (((ONEOF + CaselessLiteral("(") + supertype_expression + ZeroOrMore((CaselessLiteral(",") + supertype_expression)) + CaselessLiteral(")")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="one_of"))
aggregate_type << (((AGGREGATE + Optional((CaselessLiteral(":") + type_label)) + OF + parameter_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="aggregate_type"))
entity_body << (((ZeroOrMore(explicit_attr) + Optional(derive_clause) + Optional(inverse_clause) + Optional(unique_clause) + Optional(where_clause)))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="entity_body"))
generalized_types << (((aggregate_type | general_aggregation_types | generic_entity_type | generic_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="generalized_types"))
case_stmt << (((CASE + selector + OF + ZeroOrMore(case_action) + Optional((OTHERWISE + CaselessLiteral(":") + stmt)) + END_CASE + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="case_stmt"))
binary_type << (((BINARY + Optional(width_spec)))).setParseAction(BinaryType)
local_decl << (((LOCAL + local_variable + ZeroOrMore(local_variable) + END_LOCAL + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="local_decl"))
alias_stmt << (((ALIAS + variable_id + FOR + general_ref + ZeroOrMore(qualifier) + CaselessLiteral(";") + stmt + ZeroOrMore(stmt) + END_ALIAS + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="alias_stmt"))
simple_expression << (((term + ZeroOrMore((add_like_op + term))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="simple_expression"))
general_array_type << (((ARRAY + Optional(bound_spec) + OF + Optional(OPTIONAL) + Optional(UNIQUE) + parameter_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="general_array_type"))
interval << (((CaselessLiteral("{") + interval_low + interval_op + interval_item + interval_op + interval_high + CaselessLiteral("}")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="interval"))
procedure_head << (((PROCEDURE + procedure_id + Optional((CaselessLiteral("(") + Optional(VAR) + formal_parameter + ZeroOrMore((CaselessLiteral(";") + Optional(VAR) + formal_parameter)) + CaselessLiteral(")"))) + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="procedure_head"))
function_decl << (((function_head + algorithm_head + stmt + ZeroOrMore(stmt) + END_FUNCTION + CaselessLiteral(";")))).setParseAction(FunctionDeclaration)
supertype_expression << (((supertype_factor + ZeroOrMore((ANDOR + supertype_factor))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="supertype_expression"))
set_type << (((SET + Optional(bound_spec) + OF + instantiable_type))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="set_type"))
primary << (((literal | (qualifiable_factor + ZeroOrMore(qualifier))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="primary"))
procedure_call_stmt << ((((built_in_procedure | procedure_ref) + actual_parameter_list + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="procedure_call_stmt"))
simple_types << (((binary_type | boolean_type | integer_type | logical_type | number_type | real_type | string_type))).setParseAction(SimpleType)
query_expression << (((QUERY + CaselessLiteral("(") + variable_id + CaselessLiteral("<*") + aggregate_source + CaselessLiteral("|") + logical_expression + CaselessLiteral(")")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="query_expression"))
index_2 << (index)
constant_decl << (((CONSTANT + constant_body + ZeroOrMore(constant_body) + END_CONSTANT + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="constant_decl"))
case_action << (((case_label + ZeroOrMore((CaselessLiteral(",") + case_label)) + CaselessLiteral(":") + stmt))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="case_action"))
schema_body << (((ZeroOrMore(interface_specification) + Optional(constant_decl) + ZeroOrMore((declaration | rule_decl))))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="schema_body"))
element << (((expression + Optional((CaselessLiteral(":") + repetition))))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="element"))
numeric_expression << (simple_expression)
aggregate_initializer << (((CaselessLiteral("[") + Optional((element + ZeroOrMore((CaselessLiteral(",") + element)))) + CaselessLiteral("]")))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="aggregate_initializer"))
schema_decl << (((SCHEMA + schema_id + Optional(schema_version_id) + CaselessLiteral(";") + schema_body + END_SCHEMA + CaselessLiteral(";")))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="schema_decl"))
supertype_term << (((one_of | (CaselessLiteral("(") + supertype_expression + CaselessLiteral(")")) | entity_ref))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="supertype_term"))
algorithm_head << (((ZeroOrMore(declaration) + Optional(constant_decl) + Optional(local_decl)))).setParseAction(lambda s, loc, t: ListNode(s, loc, t, rule="algorithm_head"))
supertype_constraint << (((abstract_supertype_declaration | abstract_entity_declaration | supertype_rule))).setParseAction(SuperTypeExpression)
interval_low << (simple_expression)
domain_rule << (((Optional((rule_label_id + CaselessLiteral(":"))) + expression))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="domain_rule"))
rule_decl << (((rule_head + algorithm_head + ZeroOrMore(stmt) + where_clause + END_RULE + CaselessLiteral(";")))).setParseAction(RuleDeclaration)
concrete_types << (((aggregation_types | simple_types | type_ref))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="concrete_types"))
qualifier << (((attribute_qualifier | group_qualifier | index_qualifier))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="qualifier"))
subtype_constraint_body << (((Optional(abstract_supertype) + Optional(total_over) + Optional((supertype_expression + CaselessLiteral(";")))))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="subtype_constraint_body"))
function_call << ((((built_in_function | function_ref) + actual_parameter_list))).setParseAction(lambda s, loc, t: Node(s, loc, t, rule="function_call"))
bound_spec << (((CaselessLiteral("[") + bound_1 + CaselessLiteral(":") + bound_2 + CaselessLiteral("]")))).setParseAction(BoundSpecification)
derive_clause << (((DERIVE + derived_attr + ZeroOrMore(derived_attr)))).setParseAction(AttributeList)
syntax.ignore("--" + restOfLine)
syntax.ignore(Regex(r"\((?:\*(?:[^*]*\*+)+?\))"))
@@ -155,6 +155,7 @@ class Header(codegen.Base):
tt = mapping.schema.entities[tt.supertypes[0]]
supertypes = list(type.supertypes) if len(type.supertypes) else ["IfcUtil::IfcBaseEntity"]
direct_superclass = supertypes[0]
supertypes.extend(get_select_super_types(name, bases=all_supertypes))
supertypes = list(map(case_normalize, supertypes))
superclass = create_supertype_statement(supertypes)
@@ -115,8 +115,8 @@ class Implementation(codegen.Base):
null_check = ""
if arg["is_optional"]:
attr_check = (
"if(!data_->getArgument(%d) || data_->getArgument(%d)->isNull()) { return %%s; }"
% (arg["index"] - 1, arg["index"] - 1)
"if(data_.get_attribute_value(%d).isNull()) { return %%s; }"
% (arg["index"] - 1,)
)
if "boost::optional" in arg["full_type"]:
null_check = attr_check % "boost::none"
@@ -236,11 +236,17 @@ class Implementation(codegen.Base):
]
superclass = (
"%s((IfcEntityInstanceData*)0)" % type.supertypes[0]
"%s(std::move(e))" % type.supertypes[0]
if len(type.supertypes) == 1
else "IfcUtil::IfcBaseEntity()"
else "IfcUtil::IfcBaseEntity(std::move(e))"
)
superclass_num_attrs = (
"%s(IfcEntityInstanceData(storage_t(%%d)))" % type.supertypes[0]
if len(type.supertypes) == 1
else "IfcUtil::IfcBaseEntity(IfcEntityInstanceData(storage_t(%d)))"
) % len(constructor_arguments)
write(
templates.entity_implementation,
name=name,
@@ -250,6 +256,7 @@ class Implementation(codegen.Base):
attributes=nl(catnl(attributes)),
inverse=nl(catnl(inverse)),
superclass=superclass,
superclass_num_attrs=superclass_num_attrs,
schema_name=schema_name,
schema_name_upper=schema_name_upper,
index_in_schema=self.names.index(str(name)),
@@ -302,7 +309,7 @@ class Implementation(codegen.Base):
for class_name, type in mapping.schema.simpletypes.items():
type_str = mapping.make_type_string(mapping.flatten_type_string(type))
attr_type = mapping.make_argument_type(type)
superclass = mapping.simple_type_parent(class_name)
superclass = mapping.simple_type_parent(class_name) or "IfcUtil::IfcBaseType"
simpletype_impl_is = (
templates.simpletype_impl_is_with_supertype
@@ -310,7 +317,7 @@ class Implementation(codegen.Base):
else templates.simpletype_impl_is_without_supertype
)
constructor = templates.constructor_single_initlist if superclass else templates.constructor
constructor = templates.constructor_single_initlist# if superclass else templates.constructor
simpletype_impl_cast = (
templates.simpletype_impl_cast_templated
@@ -337,9 +344,10 @@ class Implementation(codegen.Base):
map(
compose,
map(
lambda x: (class_name, attr_type, superclass, "(IfcEntityInstanceData*)0") + x,
lambda x: (class_name, attr_type, superclass) + x,
(
(
"",
"Class",
templates.function,
"const IfcParse::type_declaration&",
@@ -347,6 +355,7 @@ class Implementation(codegen.Base):
templates.simpletype_impl_class,
),
(
"",
"declaration",
templates.const_function,
"const IfcParse::type_declaration&",
@@ -354,14 +363,16 @@ class Implementation(codegen.Base):
templates.simpletype_impl_declaration,
),
(
"std::move(e)",
"",
constructor,
"",
("IfcEntityInstanceData* e",),
templates.simpletype_impl_explicit_constructor,
("IfcEntityInstanceData&& e",),
"",
),
("", constructor, "", ("%s v" % type_str,), simpletype_impl_constructor),
("", templates.cast_function, type_str, (), simpletype_impl_cast),
("", "", 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),
),
),
)
@@ -330,13 +330,13 @@ class EarlyBoundCodeWriter:
name = idx_name[1]
return name in can_be_instantiated_set
instance_mapping = """switch(data->type()->index_in_schema()) {
instance_mapping = """switch(decl->index_in_schema()) {
%s
default: throw IfcParse::IfcException(data->type()->name() + " cannot be instantiated");
default: throw IfcParse::IfcException(decl->name() + " cannot be instantiated");
}
""" % "\n ".join(
map(
lambda tup: ("case %%d: return new ::%s::%%s(data);" % schema_name_title) % tup,
lambda tup: ("case %%d: return new ::%s::%%s(std::move(data));" % schema_name_title) % tup,
filter(can_be_instantiated, enumerate(self.names)),
)
)
@@ -344,7 +344,7 @@ class EarlyBoundCodeWriter:
self.statements[self.statements.index("{factory_placeholder}")] = (
"""
class %(schema_name)s_instance_factory : public IfcParse::instance_factory {
virtual IfcUtil::IfcBaseClass* operator()(IfcEntityInstanceData* data) const {
virtual IfcUtil::IfcBaseClass* operator()(const IfcParse::declaration* decl, IfcEntityInstanceData&& data) const {
%(instance_mapping)s
}
};
@@ -71,14 +71,13 @@ implementation = """
#include "../ifcparse/%(schema_name)s.h"
#include "../ifcparse/IfcSchema.h"
#include "../ifcparse/IfcException.h"
#include "../ifcparse/IfcWrite.h"
#include "../ifcparse/IfcFile.h"
#include <map>
const char* const %(schema_name)s::Identifier = "%(schema_name_upper)s";
using namespace IfcParse;
using namespace IfcWrite;
// External definitions
%(external_definitions)s
@@ -113,7 +112,7 @@ class IFC_PARSE_API %(name)s : %(superclass)s {
public:
virtual const IfcParse::type_declaration& declaration() const;
static const IfcParse::type_declaration& Class();
explicit %(name)s (IfcEntityInstanceData* e);
explicit %(name)s (IfcEntityInstanceData&& e);
%(name)s (%(type)s v);
operator %(type)s() const;
};
@@ -121,19 +120,19 @@ public:
simpletype_impl_comment = "// Function implementations for %(name)s"
simpletype_impl_argument_type = 'if (i == 0) { return %(attr_type)s; } else { throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); }'
simpletype_impl_argument = "return data_->getArgument(i);"
simpletype_impl_argument = "return data_.get_attribute_value(i);"
simpletype_impl_is_with_supertype = "return v == %(class_name)s_type || %(superclass)s::is(v);"
simpletype_impl_is_without_supertype = "return v == %(class_name)s_type;"
simpletype_impl_type = "return *((IfcParse::type_declaration*)%(schema_name_upper)s_types[%(index_in_schema)d]);"
simpletype_impl_class = "return *((IfcParse::type_declaration*)%(schema_name_upper)s_types[%(index_in_schema)d]);"
simpletype_impl_explicit_constructor = "data_ = e;"
simpletype_impl_constructor = (
"data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]); set_value(0, v);"
"data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]); set_attribute_value(0, v);"
)
simpletype_impl_constructor_templated = "data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]); set_value(0, v->generalize());"
simpletype_impl_cast = "return *data_->getArgument(0);"
simpletype_impl_constructor_templated = "data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]); set_attribute_value(0, v->generalize());"
simpletype_impl_cast = "return data_.get_attribute_value(0);"
simpletype_impl_cast_templated = (
"aggregate_of_instance::ptr es = *data_->getArgument(0); return es->as< %(underlying_type)s >();"
"aggregate_of_instance::ptr es = data_.get_attribute_value(0); return es->as< %(underlying_type)s >();"
)
simpletype_impl_declaration = "return *((IfcParse::type_declaration*)%(schema_name_upper)s_types[%(index_in_schema)d]);"
@@ -154,7 +153,7 @@ public:
virtual const IfcParse::enumeration_type& declaration() const;
static const IfcParse::enumeration_type& Class();
%(name)s (IfcEntityInstanceData* e);
%(name)s (IfcEntityInstanceData&& e);
%(name)s (Value v);
%(name)s (const std::string& v);
operator Value() const;
@@ -166,7 +165,7 @@ class IFC_PARSE_API %(name)s : %(superclass)s {
public:
%(attributes)s %(inverse)s virtual const IfcParse::entity& declaration() const;
static const IfcParse::entity& Class();
%(name)s (IfcEntityInstanceData* e);
%(name)s (IfcEntityInstanceData&& e);
%(name)s (%(constructor_arguments)s);
typedef aggregate_of< %(name)s > list;
};
@@ -180,18 +179,16 @@ enumeration_function = """
const IfcParse::enumeration_type& %(schema_name)s::%(name)s::declaration() const { return *((IfcParse::enumeration_type*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
const IfcParse::enumeration_type& %(schema_name)s::%(name)s::Class() { return *((IfcParse::enumeration_type*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
%(schema_name)s::%(name)s::%(name)s(IfcEntityInstanceData* e) {
data_ = e;
}
%(schema_name)s::%(name)s::%(name)s(IfcEntityInstanceData&& e)
: IfcBaseType(std::move(e))
{}
%(schema_name)s::%(name)s::%(name)s(Value v) {
data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]);
set_value(0, IfcWrite::IfcWriteArgument::EnumerationReference(v,ToString(v)));
set_attribute_value(0, EnumerationReference(&declaration(), static_cast<size_t>(v)));
}
%(schema_name)s::%(name)s::%(name)s(const std::string& v) {
data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]);
set_value(0, IfcWrite::IfcWriteArgument::EnumerationReference(FromString(v),ToString(FromString(v))));
set_attribute_value(0, EnumerationReference(&declaration(), declaration().lookup_enum_offset(v)));
}
const char* %(schema_name)s::%(name)s::ToString(Value v) {
@@ -203,7 +200,7 @@ const char* %(schema_name)s::%(name)s::ToString(Value v) {
}
%(schema_name)s::%(name)s::operator %(schema_name)s::%(name)s::Value() const {
return FromString((std::string) *data_->getArgument(0));
return (%(schema_name)s::%(name)s::Value) data_.storage_.get<EnumerationReference>(0).index();
}
"""
@@ -212,10 +209,13 @@ entity_implementation = """// Function implementations for %(name)s
%(inverse)s
const IfcParse::entity& %(schema_name)s::%(name)s::declaration() const { return *((IfcParse::entity*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
const IfcParse::entity& %(schema_name)s::%(name)s::Class() { return *((IfcParse::entity*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
%(schema_name)s::%(name)s::%(name)s(IfcEntityInstanceData* e) : %(superclass)s { data_ = e; }
%(schema_name)s::%(name)s::%(name)s(%(constructor_arguments)s) : %(superclass)s {data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]); %(constructor_implementation)s }
%(schema_name)s::%(name)s::%(name)s(IfcEntityInstanceData&& e) : %(superclass)s { }
%(schema_name)s::%(name)s::%(name)s(%(constructor_arguments)s) : %(superclass_num_attrs)s { %(constructor_implementation)s }
"""
# data_ = e;
# data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]);
optional_attribute_description = "/// Whether the optional attribute %s is defined for this %s"
function = "%(return_type)s %(schema_name)s::%(class_name)s::%(name)s(%(arguments)s) { %(body)s }"
@@ -241,41 +241,41 @@ parent_type_stmt = " if(v==%(name)s%(padding)s) { return %(parent)s; }"
parent_type_test = " || %s::is(v)"
optional_attr_stmt = "return !data_->getArgument(%(index)d)->isNull();"
optional_attr_stmt = "return !data_.get_attribute_value(%(index)d).isNull();"
get_attr_stmt = "%(null_check)s %(non_optional_type)s v = *data_->getArgument(%(index)d); return v;"
get_attr_stmt_enum = "%(null_check)s return %(non_optional_type)s::FromString(*data_->getArgument(%(index)d));"
get_attr_stmt_entity = "%(null_check)s return ((IfcUtil::IfcBaseClass*)(*data_->getArgument(%(index)d)))->as<%(non_optional_type_no_pointer)s>(true);"
get_attr_stmt_array = "%(null_check)s aggregate_of_instance::ptr es = *data_->getArgument(%(index)d); return es->as< %(list_instance_type)s >();"
get_attr_stmt_nested_array = "%(null_check)s aggregate_of_aggregate_of_instance::ptr es = *data_->getArgument(%(index)d); return es->as< %(list_instance_type)s >();"
get_attr_stmt = "%(null_check)s %(non_optional_type)s v = data_.get_attribute_value(%(index)d); return v;"
get_attr_stmt_enum = "%(null_check)s return %(non_optional_type)s::FromString(data_.get_attribute_value(%(index)d));"
get_attr_stmt_entity = "%(null_check)s return ((IfcUtil::IfcBaseClass*)(data_.get_attribute_value(%(index)d)))->as<%(non_optional_type_no_pointer)s>(true);"
get_attr_stmt_array = "%(null_check)s aggregate_of_instance::ptr es = data_.get_attribute_value(%(index)d); return es->as< %(list_instance_type)s >();"
get_attr_stmt_nested_array = "%(null_check)s aggregate_of_aggregate_of_instance::ptr es = data_.get_attribute_value(%(index)d); return es->as< %(list_instance_type)s >();"
get_inverse = "return data_->getInverse(%(schema_name_upper)s_types[%(type_index)d], %(index)d)->as<%(type)s>();"
get_inverse = "if (!file_) { return nullptr; } return file_->getInverse(id_, %(schema_name_upper)s_types[%(type_index)d], %(index)d)->as<%(type)s>();"
set_attr_stmt = (
"%(check_optional_set_begin)sset_value(%(index)d, %(star_if_optional)sv);%(check_optional_set_else)sunset_value(%(index)d);%(check_optional_set_end)s"
"%(check_optional_set_begin)sset_attribute_value(%(index)d, %(star_if_optional)sv);%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s"
)
set_attr_instance = (
"%(check_optional_set_begin)sset_value(%(index)d, v->as<IfcUtil::IfcBaseClass>());%(check_optional_set_else)sunset_value(%(index)d);%(check_optional_set_end)s"
"%(check_optional_set_begin)sset_attribute_value(%(index)d, v->as<IfcUtil::IfcBaseClass>());%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s"
)
set_attr_stmt_enum = "%(check_optional_set_begin)sset_value(%(index)d, IfcWrite::IfcWriteArgument::EnumerationReference(%(star_if_optional)sv,%(non_optional_type)s::ToString(%(star_if_optional)sv)));%(check_optional_set_else)sunset_value(%(index)d);%(check_optional_set_end)s"
set_attr_stmt_enum = "%(check_optional_set_begin)sset_attribute_value(%(index)d, EnumerationReference(&%(non_optional_type)s::Class(), (size_t) %(star_if_optional)sv));%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s"
set_attr_stmt_array = (
"%(check_optional_set_begin)sset_value(%(index)d, (%(star_if_optional)sv)->generalize());%(check_optional_set_else)sunset_value(%(index)d);%(check_optional_set_end)s"
"%(check_optional_set_begin)sset_attribute_value(%(index)d, (%(star_if_optional)sv)->generalize());%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s"
)
constructor_stmt = (
"set_value(%(index)d, (%(name)s));"
"set_attribute_value(%(index)d, (%(name)s));"
)
constructor_stmt_enum = (
"set_value(%(index)d, (IfcWrite::IfcWriteArgument::EnumerationReference(%(name)s,%(type)s::ToString(%(name)s))));"
"set_attribute_value(%(index)d, (EnumerationReference(&%(type)s::Class(),(size_t)%(name)s)));"
)
constructor_stmt_array = (
"set_value(%(index)d, (%(name)s)->generalize());"
"set_attribute_value(%(index)d, (%(name)s)->generalize());"
)
constructor_stmt_derived = (
""
)
constructor_stmt_instance = (
"set_value(%(index)d, %(name)s ? %(name)s->as<IfcUtil::IfcBaseClass>() : (IfcUtil::IfcBaseClass*) nullptr);"
"set_attribute_value(%(index)d, %(name)s ? %(name)s->as<IfcUtil::IfcBaseClass>() : (IfcUtil::IfcBaseClass*) nullptr);"
)
constructor_stmt_optional = " if (%(name)s) {%(stmt)s }"
@@ -256,11 +256,12 @@ def assert_valid(
return True
def log_internal_cpp_errors(filename: str, logger: Logger) -> None:
def log_internal_cpp_errors(f: ifcopenshell.file, filename: str, logger: Logger) -> None:
import re
import bisect
chr_offset_re = re.compile(r"at offset (\d+)\s*")
for_instance_re = re.compile(r"\s*for instance #(\d+)\s*")
log = ifcopenshell.get_log()
msgs = list(map(json.loads, filter(None, log.split("\n"))))
@@ -286,6 +287,24 @@ def log_internal_cpp_errors(filename: str, logger: Logger) -> None:
else:
logger.error("For instance:\n %s\n%s", line, m)
instance_messages = [for_instance_re.findall(m["message"]) for m in msgs]
if instance_messages:
for instid, msg in zip(instance_messages, msgs):
if instid:
m = for_instance_re.sub("", msg["message"])
try:
inst = f[int(instid[0])]
except:
inst = None
if hasattr(logger, "set_state"):
logger.set_state("instance", inst)
logger.set_state("attribute", None)
logger.error(m)
elif inst:
logger.error("For instance:\n %s\n%s", inst, m)
else:
logger.error(m)
entity_attribute_map: dict[tuple[str, str], tuple[entity_type, tuple[attribute]]] = {}
@@ -368,7 +387,7 @@ def validate(f: Union[ifcopenshell.file, str], logger: Logger, express_rules=Fal
logger.error(f"Unsupported schema: {schema_name}")
return
log_internal_cpp_errors(filename, logger)
log_internal_cpp_errors(f, filename, logger)
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(f.schema_identifier)
used_guids: dict[str, ifcopenshell.entity_instance] = dict()
@@ -490,7 +509,7 @@ def validate(f: Union[ifcopenshell.file, str], logger: Logger, express_rules=Fal
# Re capturing the log when validate() is finished
# iterating over every instance so that all attribute counts
# are verified.
log_internal_cpp_errors(filename, logger)
log_internal_cpp_errors(f, filename, logger)
# Restore the original value for 'use_attribute_value_derived'
ifcopenshell.ifcopenshell_wrapper.set_feature("use_attribute_value_derived", attribute_value_derived_org)
@@ -5,6 +5,6 @@ FILE_NAME('','2023-04-13T10:27:43',(),(),'IfcOpenShell v0.7.0-198fa67cc','IfcOpe
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#1=IFCPRESENTATIONSTYLEASSIGNMENT((IFCNULLSTYLE('NOT_EXISTING_ENUM')));
#1=IFCPRESENTATIONSTYLEASSIGNMENT((IFCNULLSTYLE(.NOT_EXISTING_ENUM.)));
ENDSEC;
END-ISO-10303-21;
@@ -0,0 +1,10 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
FILE_NAME('','2023-04-13T10:27:43',(),(),'IfcOpenShell v0.7.0-198fa67cc','IfcOpenShell v0.7.0-198fa67cc','');
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#1=IFCPROPERTYSINGLEVALUE('Test',$,IFCCOMPLEXNUMBER((0.,0.)),$);
ENDSEC;
END-ISO-10303-21;
@@ -5,6 +5,6 @@ FILE_NAME('','2023-04-13T10:27:43',(),(),'IfcOpenShell v0.7.0-198fa67cc','IfcOpe
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#1=IFCPRESENTATIONSTYLEASSIGNMENT((IFCNULLSTYLE('NULL')));
#1=IFCPRESENTATIONSTYLEASSIGNMENT((IFCNULLSTYLE(.NULL.)));
ENDSEC;
END-ISO-10303-21;
@@ -28,9 +28,11 @@ class TestOpen:
def test_open_ifcspf(self):
assert ifcopenshell.open(TEST_FILE_DIR / "WallInstance_IFC4Add2.ifc")
@pytest.mark.skip("IFC-XML temporarily disabled")
def test_open_ifcxml(self):
assert ifcopenshell.open(TEST_FILE_DIR / "wall-with-opening-and-window.ifcxml")
@pytest.mark.skip("IFC-XML temporarily disabled")
def test_open_ifc_zip_ifcxml_format(self):
assert ifcopenshell.open(TEST_FILE_DIR / "wall-with-opening-and-window_ifcxml_format.ifczip")
@@ -49,16 +51,19 @@ class TestOpen:
".ifcZIP",
)
@pytest.mark.skip("IFC-XML temporarily disabled")
def test_open_anyextension_ifcxml_format(self):
assert ifcopenshell.open(
TEST_FILE_DIR / "wall-with-opening-and-window_ifcxml_format.anyextension",
".ifcXML",
)
@pytest.mark.skip("IFC-XML temporarily disabled")
def test_invalid_ifcspf(self):
with pytest.raises(ifcopenshell.Error):
assert ifcopenshell.open(TEST_FILE_DIR / "invalid.ifc")
@pytest.mark.skip("IFC-XML temporarily disabled")
def test_invalid_ifcxml(self):
with pytest.raises(IOError):
assert ifcopenshell.open(TEST_FILE_DIR / "invalid.ifcxml")
-33
View File
@@ -29,11 +29,7 @@
#include <string>
#include <vector>
class aggregate_of_instance;
class aggregate_of_aggregate_of_instance;
namespace IfcUtil {
class IfcBaseClass;
IFC_PARSE_API const char* ArgumentTypeToString(ArgumentType argument_type);
@@ -41,34 +37,5 @@ IFC_PARSE_API const char* ArgumentTypeToString(ArgumentType argument_type);
IFC_PARSE_API bool valid_binary_string(const std::string& string);
} // namespace IfcUtil
class IFC_PARSE_API Argument {
public:
virtual operator int() const;
virtual operator bool() const;
virtual operator boost::logic::tribool() const;
virtual operator double() const;
virtual operator std::string() const;
virtual operator boost::dynamic_bitset<>() const;
virtual operator IfcUtil::IfcBaseClass*() const;
virtual operator std::vector<int>() const;
virtual operator std::vector<double>() const;
virtual operator std::vector<std::string>() const;
virtual operator std::vector<boost::dynamic_bitset<>>() const;
virtual operator boost::shared_ptr<aggregate_of_instance>() const;
virtual operator std::vector<std::vector<int>>() const;
virtual operator std::vector<std::vector<double>>() const;
virtual operator boost::shared_ptr<aggregate_of_aggregate_of_instance>() const;
virtual bool isNull() const = 0;
virtual unsigned int size() const = 0;
virtual IfcUtil::ArgumentType type() const = 0;
virtual Argument* operator[](unsigned int index) const = 0;
virtual std::string toString(bool upper = false) const = 0;
virtual ~Argument(){};
};
#endif
File diff suppressed because it is too large Load Diff
+5397 -5726
View File
File diff suppressed because it is too large Load Diff
+934 -934
View File
File diff suppressed because it is too large Load Diff
+1116 -1116
View File
File diff suppressed because it is too large Load Diff
+6320 -6735
View File
File diff suppressed because it is too large Load Diff
+1113 -1113
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+6495 -6916
View File
File diff suppressed because it is too large Load Diff
+1141 -1141
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+6593 -7028
View File
File diff suppressed because it is too large Load Diff
+1163 -1163
View File
File diff suppressed because it is too large Load Diff
+14 -14
View File
@@ -56,7 +56,6 @@
#define SCHEMA_HAS_IfcBSplineCurveForm
#define SCHEMA_HAS_IfcBSplineSurfaceForm
#define SCHEMA_HAS_IfcBeamTypeEnum
#define SCHEMA_HAS_IfcBearingTypeDisplacementEnum
#define SCHEMA_HAS_IfcBearingTypeEnum
#define SCHEMA_HAS_IfcBenchmarkEnum
#define SCHEMA_HAS_IfcBendingParameterSelect
@@ -142,8 +141,6 @@
#define SCHEMA_HAS_IfcDocumentStatusEnum
#define SCHEMA_HAS_IfcDoorPanelOperationEnum
#define SCHEMA_HAS_IfcDoorPanelPositionEnum
#define SCHEMA_HAS_IfcDoorStyleConstructionEnum
#define SCHEMA_HAS_IfcDoorStyleOperationEnum
#define SCHEMA_HAS_IfcDoorTypeEnum
#define SCHEMA_HAS_IfcDoorTypeOperationEnum
#define SCHEMA_HAS_IfcDoseEquivalentMeasure
@@ -219,6 +216,7 @@
#define SCHEMA_HAS_IfcIonConcentrationMeasure
#define SCHEMA_HAS_IfcIsothermalMoistureCapacityMeasure
#define SCHEMA_HAS_IfcJunctionBoxTypeEnum
#define SCHEMA_HAS_IfcKerbTypeEnum
#define SCHEMA_HAS_IfcKinematicViscosityMeasure
#define SCHEMA_HAS_IfcKnotType
#define SCHEMA_HAS_IfcLabel
@@ -279,7 +277,6 @@
#define SCHEMA_HAS_IfcNormalisedRatioMeasure
#define SCHEMA_HAS_IfcNumericMeasure
#define SCHEMA_HAS_IfcObjectReferenceSelect
#define SCHEMA_HAS_IfcObjectTypeEnum
#define SCHEMA_HAS_IfcObjectiveEnum
#define SCHEMA_HAS_IfcOccupantTypeEnum
#define SCHEMA_HAS_IfcOpeningElementTypeEnum
@@ -386,6 +383,7 @@
#define SCHEMA_HAS_IfcStairFlightTypeEnum
#define SCHEMA_HAS_IfcStairTypeEnum
#define SCHEMA_HAS_IfcStateEnum
#define SCHEMA_HAS_IfcStrippedOptional
#define SCHEMA_HAS_IfcStructuralActivityAssignmentSelect
#define SCHEMA_HAS_IfcStructuralCurveActivityTypeEnum
#define SCHEMA_HAS_IfcStructuralCurveMemberTypeEnum
@@ -456,8 +454,6 @@
#define SCHEMA_HAS_IfcWasteTerminalTypeEnum
#define SCHEMA_HAS_IfcWindowPanelOperationEnum
#define SCHEMA_HAS_IfcWindowPanelPositionEnum
#define SCHEMA_HAS_IfcWindowStyleConstructionEnum
#define SCHEMA_HAS_IfcWindowStyleOperationEnum
#define SCHEMA_HAS_IfcWindowTypeEnum
#define SCHEMA_HAS_IfcWindowTypePartitioningEnum
#define SCHEMA_HAS_IfcWorkCalendarTypeEnum
@@ -1789,6 +1785,7 @@
#define SCHEMA_IfcIndexedPolyCurve_HAS_Segments
#define SCHEMA_IfcIndexedPolyCurve_Segments_IS_OPTIONAL
#define SCHEMA_IfcIndexedPolyCurve_HAS_SelfIntersect
#define SCHEMA_IfcIndexedPolyCurve_SelfIntersect_IS_OPTIONAL
#define SCHEMA_HAS_IfcIndexedPolygonalFace
#define SCHEMA_IfcIndexedPolygonalFace_HAS_CoordIndex
#define SCHEMA_IfcIndexedPolygonalFace_HAS_ToFaceSet
@@ -1833,9 +1830,10 @@
#define SCHEMA_HAS_IfcJunctionBoxType
#define SCHEMA_IfcJunctionBoxType_HAS_PredefinedType
#define SCHEMA_HAS_IfcKerb
#define SCHEMA_IfcKerb_HAS_Mountable
#define SCHEMA_IfcKerb_HAS_PredefinedType
#define SCHEMA_IfcKerb_PredefinedType_IS_OPTIONAL
#define SCHEMA_HAS_IfcKerbType
#define SCHEMA_IfcKerbType_HAS_Mountable
#define SCHEMA_IfcKerbType_HAS_PredefinedType
#define SCHEMA_HAS_IfcLShapeProfileDef
#define SCHEMA_IfcLShapeProfileDef_HAS_Depth
#define SCHEMA_IfcLShapeProfileDef_HAS_Width
@@ -2364,6 +2362,8 @@
#define SCHEMA_IfcPolygonalBoundedHalfSpace_HAS_Position
#define SCHEMA_IfcPolygonalBoundedHalfSpace_HAS_PolygonalBoundary
#define SCHEMA_HAS_IfcPolygonalFaceSet
#define SCHEMA_IfcPolygonalFaceSet_HAS_Closed
#define SCHEMA_IfcPolygonalFaceSet_Closed_IS_OPTIONAL
#define SCHEMA_IfcPolygonalFaceSet_HAS_Faces
#define SCHEMA_IfcPolygonalFaceSet_HAS_PnIndex
#define SCHEMA_IfcPolygonalFaceSet_PnIndex_IS_OPTIONAL
@@ -2901,11 +2901,11 @@
#define SCHEMA_IfcRelInterferesElements_HAS_RelatedElement
#define SCHEMA_IfcRelInterferesElements_HAS_InterferenceGeometry
#define SCHEMA_IfcRelInterferesElements_InterferenceGeometry_IS_OPTIONAL
#define SCHEMA_IfcRelInterferesElements_HAS_InterferenceSpace
#define SCHEMA_IfcRelInterferesElements_InterferenceSpace_IS_OPTIONAL
#define SCHEMA_IfcRelInterferesElements_HAS_InterferenceType
#define SCHEMA_IfcRelInterferesElements_InterferenceType_IS_OPTIONAL
#define SCHEMA_IfcRelInterferesElements_HAS_ImpliedOrder
#define SCHEMA_IfcRelInterferesElements_HAS_InterferenceSpace
#define SCHEMA_IfcRelInterferesElements_InterferenceSpace_IS_OPTIONAL
#define SCHEMA_HAS_IfcRelNests
#define SCHEMA_IfcRelNests_HAS_RelatingObject
#define SCHEMA_IfcRelNests_HAS_RelatedObjects
@@ -3691,8 +3691,6 @@
#define SCHEMA_IfcTendonType_SheathDiameter_IS_OPTIONAL
#define SCHEMA_HAS_IfcTessellatedFaceSet
#define SCHEMA_IfcTessellatedFaceSet_HAS_Coordinates
#define SCHEMA_IfcTessellatedFaceSet_HAS_Closed
#define SCHEMA_IfcTessellatedFaceSet_Closed_IS_OPTIONAL
#define SCHEMA_IfcTessellatedFaceSet_HAS_HasColours
#define SCHEMA_IfcTessellatedFaceSet_HAS_HasTextures
#define SCHEMA_HAS_IfcTessellatedItem
@@ -3814,6 +3812,8 @@
#define SCHEMA_HAS_IfcTriangulatedFaceSet
#define SCHEMA_IfcTriangulatedFaceSet_HAS_Normals
#define SCHEMA_IfcTriangulatedFaceSet_Normals_IS_OPTIONAL
#define SCHEMA_IfcTriangulatedFaceSet_HAS_Closed
#define SCHEMA_IfcTriangulatedFaceSet_Closed_IS_OPTIONAL
#define SCHEMA_IfcTriangulatedFaceSet_HAS_CoordIndex
#define SCHEMA_IfcTriangulatedFaceSet_HAS_PnIndex
#define SCHEMA_IfcTriangulatedFaceSet_PnIndex_IS_OPTIONAL
@@ -4039,7 +4039,6 @@
#define SCHEMA_HAS_IfcCorrectDimensions
#define SCHEMA_HAS_IfcCorrectFillAreaStyle
#define SCHEMA_HAS_IfcCorrectLocalPlacement
#define SCHEMA_HAS_IfcCorrectObjectAssignment
#define SCHEMA_HAS_IfcCorrectUnitAssignment
#define SCHEMA_HAS_IfcCrossProduct
#define SCHEMA_HAS_IfcCurveDim
@@ -4049,7 +4048,6 @@
#define SCHEMA_HAS_IfcDotProduct
#define SCHEMA_HAS_IfcFirstProjAxis
#define SCHEMA_HAS_IfcGetBasisSurface
#define SCHEMA_HAS_IfcGradient
#define SCHEMA_HAS_IfcListToArray
#define SCHEMA_HAS_IfcLoopHeadToTail
#define SCHEMA_HAS_IfcMakeArrayOfArray
@@ -4057,6 +4055,7 @@
#define SCHEMA_HAS_IfcNormalise
#define SCHEMA_HAS_IfcOrthogonalComplement
#define SCHEMA_HAS_IfcPathHeadToTail
#define SCHEMA_HAS_IfcPointDim
#define SCHEMA_HAS_IfcPointListDim
#define SCHEMA_HAS_IfcSameAxis2Placement
#define SCHEMA_HAS_IfcSameCartesianPoint
@@ -4065,6 +4064,7 @@
#define SCHEMA_HAS_IfcSameValue
#define SCHEMA_HAS_IfcScalarTimesVector
#define SCHEMA_HAS_IfcSecondProjAxis
#define SCHEMA_HAS_IfcSegmentDim
#define SCHEMA_HAS_IfcShapeRepresentationTypes
#define SCHEMA_HAS_IfcSurfaceWeightsPositive
#define SCHEMA_HAS_IfcTaperedSweptAreaProfiles
+3742 -17055
View File
File diff suppressed because one or more lines are too long
+10088 -15679
View File
File diff suppressed because one or more lines are too long
+1304 -1618
View File
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
+7060 -7547
View File
File diff suppressed because it is too large Load Diff
+1251 -1251
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+7060 -7547
View File
File diff suppressed because it is too large Load Diff
+1251 -1251
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+7014 -7499
View File
File diff suppressed because it is too large Load Diff
+1251 -1251
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+7075 -7566
View File
File diff suppressed because it is too large Load Diff
+1260 -1260
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+7033 -7526
View File
File diff suppressed because it is too large Load Diff
+1253 -1253
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+7041 -7534
View File
File diff suppressed because it is too large Load Diff
+1252 -1252
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+7030 -7517
View File
File diff suppressed because it is too large Load Diff
+1246 -1246
View File
File diff suppressed because it is too large Load Diff
+79 -31
View File
@@ -29,9 +29,12 @@
#include <atomic>
#include <boost/shared_ptr.hpp>
class Argument;
class aggregate_of_instance;
namespace IfcParse {
class IfcFile;
}
namespace IfcUtil {
class IFC_PARSE_API IfcBaseInterface {
@@ -54,6 +57,7 @@ class IFC_PARSE_API IfcBaseInterface {
virtual const IfcEntityInstanceData& data() const = 0;
virtual IfcEntityInstanceData& data() = 0;
virtual const IfcParse::declaration& declaration() const = 0;
virtual ~IfcBaseInterface() {}
template <class T>
T* as(bool do_throw = false) {
@@ -82,36 +86,42 @@ class IFC_PARSE_API IfcBaseInterface {
};
class IFC_PARSE_API IfcBaseClass : public virtual IfcBaseInterface {
private:
uint32_t identity_;
protected:
static std::atomic_uint32_t counter_;
protected:
IfcEntityInstanceData* data_;
uint32_t identity_;
public:
uint32_t id_;
IfcParse::IfcFile* file_;
protected:
IfcEntityInstanceData data_;
static bool is_null(const IfcBaseClass* not_this) {
return not_this == nullptr;
}
public:
IfcBaseClass(IfcEntityInstanceData&& data)
: identity_(counter_++)
, id_(0)
, file_(nullptr)
, data_(std::move(data))
{}
public:
IfcBaseClass() : identity_(counter_++),
data_(0) {}
IfcBaseClass(IfcEntityInstanceData* data) : identity_(counter_++),
data_(data) {}
virtual ~IfcBaseClass() { delete data_; }
const IfcEntityInstanceData& data() const { return *data_; }
IfcEntityInstanceData& data() { return *data_; }
void data(IfcEntityInstanceData* data);
const IfcEntityInstanceData& data() const { return data_; }
IfcEntityInstanceData& data() { return data_; }
virtual const IfcParse::declaration& declaration() const = 0;
template <typename T>
void set_value(int index, const T& value);
void set_attribute_value(size_t i, const T& t);
void unset_value(int index);
template <typename T>
void set_attribute_value(const std::string& name, const T& t);
void unset_attribute_value(size_t i);
uint32_t identity() const { return identity_; }
uint32_t id() const { return id_; }
void toString(std::ostream&, bool upper = false) const;
};
class IFC_PARSE_API IfcLateBoundEntity : public IfcBaseClass {
@@ -119,7 +129,7 @@ class IFC_PARSE_API IfcLateBoundEntity : public IfcBaseClass {
const IfcParse::declaration* decl_;
public:
IfcLateBoundEntity(const IfcParse::declaration* decl, IfcEntityInstanceData* data) : IfcBaseClass(data),
IfcLateBoundEntity(const IfcParse::declaration* decl, IfcEntityInstanceData&& data) : IfcBaseClass(std::move(data)),
decl_(decl) {}
virtual const IfcParse::declaration& declaration() const {
@@ -129,12 +139,15 @@ class IFC_PARSE_API IfcLateBoundEntity : public IfcBaseClass {
class IFC_PARSE_API IfcBaseEntity : public IfcBaseClass {
public:
IfcBaseEntity() : IfcBaseClass() {}
IfcBaseEntity(IfcEntityInstanceData* data) : IfcBaseClass(data) {}
IfcBaseEntity(IfcEntityInstanceData&& data) : IfcBaseClass(std::move(data)) {}
IfcBaseEntity(size_t n)
: IfcBaseClass(IfcEntityInstanceData(storage_t(n)))
{}
virtual const IfcParse::entity& declaration() const = 0;
Argument* get(const std::string& name) const;
AttributeValue get(const std::string& name) const;
template <typename T>
T get_value(const std::string& name) const;
@@ -143,13 +156,20 @@ class IFC_PARSE_API IfcBaseEntity : public IfcBaseClass {
T get_value(const std::string& name, const T& default_value) const;
boost::shared_ptr<aggregate_of_instance> get_inverse(const std::string& name) const;
unsigned set_id(const boost::optional<unsigned>& i);
};
// TODO: Investigate whether these should be template classes instead
class IFC_PARSE_API IfcBaseType : public IfcBaseClass {
public:
IfcBaseType() : IfcBaseClass() {}
IfcBaseType(IfcEntityInstanceData* data) : IfcBaseClass(data) {}
IfcBaseType(IfcEntityInstanceData&& data)\
: IfcBaseClass(std::move(data))
{}
IfcBaseType()
: IfcBaseClass(IfcEntityInstanceData(storage_t(1)))
{}
virtual const IfcParse::declaration& declaration() const = 0;
};
@@ -159,18 +179,46 @@ class IFC_PARSE_API IfcBaseType : public IfcBaseClass {
namespace IfcUtil {
template <typename T>
T IfcBaseEntity::get_value(const std::string& name) const {
auto* attr = get(name);
return (T)*attr;
auto attr = get(name);
return (T) attr;
}
template <typename T>
T IfcBaseEntity::get_value(const std::string& name, const T& default_value) const {
auto* attr = get(name);
if (attr->isNull()) {
auto attr = get(name);
if (attr.isNull()) {
return default_value;
}
return (T)*attr;
return (T) attr;
}
} // namespace IfcUtil
template <class U>
typename U::list::ptr aggregate_of_instance::as() {
typename U::list::ptr result(new typename U::list);
for (it i = begin(); i != end(); ++i) {
if ((*i)->template as<U>()) {
result->push((*i)->template as<U>());
}
}
return result;
}
template <class U>
typename aggregate_of_aggregate_of<U>::ptr aggregate_of_aggregate_of_instance::as() {
typename aggregate_of_aggregate_of<U>::ptr result(new aggregate_of_aggregate_of<U>);
for (outer_it outer = begin(); outer != end(); ++outer) {
const std::vector<IfcUtil::IfcBaseClass*>& from = *outer;
typename std::vector<U*> to;
for (inner_it inner = from.begin(); inner != from.end(); ++inner) {
if ((*inner)->template as<U>()) {
to.push_back((*inner)->template as<U>());
}
}
result->push(to);
}
return result;
}
#endif
+43 -22
View File
@@ -44,7 +44,7 @@
#define ARBITRARY (1 << 7)
#define EXTENDED2 (1 << 8)
#define EXTENDED4 (1 << 9)
#define HEX(N) (1 << (9 + N))
#define HEX(N) (1 << (9 + (N)))
#define THIRD_SOLIDUS (1 << 18)
#define ENDEXTENDED_X (1 << 19)
#define ENDEXTENDED_0 (1 << 20)
@@ -52,25 +52,24 @@
#define ENCOUNTERED_HEX (1 << 23)
// FIXME: These probably need to be less forgiving in terms of wrongly defined sequences
#define EXPECTS_ALPHABET(S) (S & FIRST_SOLIDUS)
#define EXPECTS_PAGE(S) (S & FIRST_SOLIDUS)
#define EXPECTS_ARBITRARY(S) (S & FIRST_SOLIDUS)
#define EXPECTS_N_OR_F(S) (S & FIRST_SOLIDUS && !(S & ARBITRARY))
#define EXPECTS_ARBITRARY2(S) (S & ARBITRARY && !(S & SECOND_SOLIDUS))
#define EXPECTS_ALPHABET_DEFINITION(S) (S & FIRST_SOLIDUS && S & ALPHABET)
#define EXPECTS_SOLIDUS(S) (S & ALPHABET_DEFINITION || S & PAGE || S & ARBITRARY || S & EXTENDED2 || S & EXTENDED4 || S & ENDEXTENDED_0 || S & IGNORED_DIRECTIVE || (S & EXTENDED4 && S & HEX(8)) || (S & EXTENDED2 && S & HEX(4)))
#define EXPECTS_CHARACTER(S) (S & PAGE && S & SECOND_SOLIDUS)
#define EXPECTS_HEX(S) (S & HEX(1) || S & HEX(3) || S & HEX(5) || S & HEX(6) || S & HEX(7) || (S & ARBITRARY && S & SECOND_SOLIDUS) || (S & EXTENDED2 && S & HEX(2)) || (S & EXTENDED4 && S & HEX(4)))
#define EXPECTS_ENDEXTENDED_X(S) (S & THIRD_SOLIDUS)
#define EXPECTS_ENDEXTENDED_0(S) (S & ENDEXTENDED_X)
#define EXPECTS_ALPHABET(S) ((S) & FIRST_SOLIDUS)
#define EXPECTS_PAGE(S) ((S) & FIRST_SOLIDUS)
#define EXPECTS_ARBITRARY(S) ((S) & FIRST_SOLIDUS)
#define EXPECTS_N_OR_F(S) ((S) & FIRST_SOLIDUS && !((S) & ARBITRARY))
#define EXPECTS_ARBITRARY2(S) ((S) & ARBITRARY && !((S) & SECOND_SOLIDUS))
#define EXPECTS_ALPHABET_DEFINITION(S) ((S) & FIRST_SOLIDUS && (S) & ALPHABET)
#define EXPECTS_SOLIDUS(S) ((S) & ALPHABET_DEFINITION || (S) & PAGE || (S) & ARBITRARY || (S) & EXTENDED2 || (S) & EXTENDED4 || (S) & ENDEXTENDED_0 || (S) & IGNORED_DIRECTIVE || ((S) & EXTENDED4 && (S) & HEX(8)) || ((S) & EXTENDED2 && (S) & HEX(4)))
#define EXPECTS_CHARACTER(S) ((S) & PAGE && (S) & SECOND_SOLIDUS)
#define EXPECTS_HEX(S) ((S) & HEX(1) || (S) & HEX(3) || (S) & HEX(5) || (S) & HEX(6) || (S) & HEX(7) || ((S) & ARBITRARY && (S) & SECOND_SOLIDUS) || ((S) & EXTENDED2 && (S) & HEX(2)) || ((S) & EXTENDED4 && (S) & HEX(4)))
#define EXPECTS_ENDEXTENDED_X(S) ((S) & THIRD_SOLIDUS)
#define EXPECTS_ENDEXTENDED_0(S) ((S) & ENDEXTENDED_X)
#define IS_VALID_ALPHABET_DEFINITION(C) (C >= 0x41 && C <= 0x49)
#define IS_HEXADECIMAL(C) ((C >= 0x30 && C <= 0x39) || (C >= 0x41 && C <= 0x46))
#define HEX_TO_INT(C) ((C >= 0x30 && C <= 0x39) ? C - 0x30 : (C + 10) - 0x41)
#define CLEAR_HEX(C) (C &= ~(HEX(1) | HEX(2) | HEX(3) | HEX(4) | HEX(5) | HEX(6) | HEX(7) | HEX(8)))
#define IS_VALID_ALPHABET_DEFINITION(C) ((C) >= 0x41 && (C) <= 0x49)
#define IS_HEXADECIMAL(C) (((C) >= 0x30 && (C) <= 0x39) || ((C) >= 0x41 && (C) <= 0x46))
#define HEX_TO_INT(C) (((C) >= 0x30 && (C) <= 0x39) ? (C) - 0x30 : ((C) + 10) - 0x41)
#define CLEAR_HEX(C) ((C) &= ~(HEX(1) | HEX(2) | HEX(3) | HEX(4) | HEX(5) | HEX(6) | HEX(7) | HEX(8)))
using namespace IfcParse;
using namespace IfcWrite;
IfcCharacterDecoder::IfcCharacterDecoder(IfcParse::IfcSpfStream* stream) {
stream_ = stream;
@@ -81,7 +80,7 @@ IfcCharacterDecoder::~IfcCharacterDecoder() {
}
namespace {
static unsigned int reference_helper = 0;
unsigned int reference_helper = 0;
class pure_impure_helper {
private:
@@ -420,14 +419,36 @@ std::wstring IfcUtil::convert_utf8(const std::string& string) {
// bug in msvc 2015 and 2017, unsure if fixed in later versions
std::u32string IfcUtil::convert_utf8_to_utf32(const std::string& s) {
auto converted = std::wstring_convert<std::codecvt_utf8<int32_t>, int32_t>().from_bytes(s);
return std::u32string(reinterpret_cast<char32_t const*>(converted.data()));
bool is_ascii = true;
for (char c : s) {
if (static_cast<unsigned char>(c) >= 128) {
is_ascii = false;
break;
}
}
if (is_ascii) {
return std::u32string(s.begin(), s.end());
} else {
auto converted = std::wstring_convert<std::codecvt_utf8<int32_t>, int32_t>().from_bytes(s);
return std::u32string(reinterpret_cast<char32_t const*>(converted.data()));
}
}
#else
std::u32string IfcUtil::convert_utf8_to_utf32(const std::string& string) {
return std::wstring_convert<std::codecvt_utf8<std::u32string::value_type>, std::u32string::value_type>().from_bytes(string);
std::u32string IfcUtil::convert_utf8_to_utf32(const std::string& s) {
bool is_ascii = true;
for (char c : s) {
if (static_cast<unsigned char>(c) >= 128) {
is_ascii = false;
break;
}
}
if (is_ascii) {
return std::u32string(s.begin(), s.end());
}
return std::wstring_convert<std::codecvt_utf8<std::u32string::value_type>, std::u32string::value_type>().from_bytes(s);
}
#endif
+1 -1
View File
@@ -68,7 +68,7 @@ class IFC_PARSE_API IfcCharacterDecoder {
} // namespace IfcParse
namespace IfcWrite {
namespace IfcParse {
class IFC_PARSE_API IfcCharacterEncoder {
private:
+127
View File
@@ -0,0 +1,127 @@
#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& /*unused*/) const { return 0; }
int operator()(const empty_aggregate_of_aggregate_t& /*unused*/) const { return 0; }
int operator()(const std::vector<int>& i) const { return (int)i.size(); }
int operator()(const std::vector<double>& i) const { return (int)i.size(); }
int operator()(const std::vector<std::vector<int>>& i) const { return (int)i.size(); }
int operator()(const std::vector<std::vector<double>>& i) const { return (int)i.size(); }
int operator()(const std::vector<std::string>& i) const { return (int)i.size(); }
int operator()(const std::vector<boost::dynamic_bitset<>>& i) const { return (int)i.size(); }
int operator()(const EnumerationReference& /*i*/) const { return -1; }
int operator()(const IfcUtil::IfcBaseClass* const& /*i*/) const { return -1; }
int operator()(const aggregate_of_instance::ptr& i) const { return i->size(); }
int operator()(const aggregate_of_aggregate_of_instance::ptr& i) const { return i->size(); }
};
AttributeValue::operator int() const
{
return array_->get<int>(index_);
}
AttributeValue::operator bool() const
{
return array_->get<bool>(index_);
}
AttributeValue::operator double() const
{
return array_->get<double>(index_);
}
AttributeValue::operator boost::logic::tribool() const
{
if (array_->has<bool>(index_)) {
return array_->get<bool>(index_);
}
return array_->get<boost::logic::tribool>(index_);
}
AttributeValue::operator std::string() const
{
if (array_->has<EnumerationReference>(index_)) {
// @todo this is silly, but the way things currently work,
// @todo also we don't really need to store a reference to the enumeration type, when this same type is already stored on the definition of the entity and no other value can be provided.
return array_->get<EnumerationReference>(index_).value();
}
return array_->get<std::string>(index_);
}
AttributeValue::operator boost::dynamic_bitset<>() const
{
return array_->get<boost::dynamic_bitset<>>(index_);
}
AttributeValue::operator IfcUtil::IfcBaseClass* () const
{
return array_->get<IfcUtil::IfcBaseClass*>(index_);
}
AttributeValue::operator std::vector<int>() const
{
return array_->get<std::vector<int>>(index_);
}
AttributeValue::operator std::vector<double>() const
{
return array_->get<std::vector<double>>(index_);
}
AttributeValue::operator std::vector<std::string>() const
{
return array_->get<std::vector<std::string>>(index_);
}
AttributeValue::operator std::vector<boost::dynamic_bitset<>>() const
{
return array_->get<std::vector<boost::dynamic_bitset<>>>(index_);
}
AttributeValue::operator boost::shared_ptr<aggregate_of_instance>() const
{
return array_->get<boost::shared_ptr<aggregate_of_instance>>(index_);
}
AttributeValue::operator std::vector<std::vector<int>>() const
{
return array_->get<std::vector<std::vector<int>>>(index_);
}
AttributeValue::operator std::vector<std::vector<double>>() const
{
return array_->get<std::vector<std::vector<double>>>(index_);
}
AttributeValue::operator boost::shared_ptr<aggregate_of_aggregate_of_instance>() const
{
return array_->get<boost::shared_ptr<aggregate_of_aggregate_of_instance>>(index_);
}
bool AttributeValue::isNull() const
{
return array_->has<Blank>(index_);
}
unsigned int AttributeValue::size() const
{
return array_->apply_visitor(SizeVisitor{}, index_);
}
IfcUtil::ArgumentType AttributeValue::type() const
{
return static_cast<IfcUtil::ArgumentType>(array_->index(index_));
}
+156 -67
View File
@@ -21,90 +21,179 @@
#define IFCENTITYINSTANCEDATA_H
#include "ArgumentType.h"
#include "variantarray.h"
#include "aggregate_of_instance.h"
#include "IfcSchema.h"
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/logic/tribool.hpp>
#include <boost/dynamic_bitset.hpp>
class Argument;
class aggregate_of_instance;
namespace IfcParse {
class IfcFile;
}
class EnumerationReference {
private:
const IfcParse::enumeration_type* enumeration_;
size_t index_;
public:
EnumerationReference(const IfcParse::enumeration_type* enumeration, size_t index)
: enumeration_(enumeration)
, index_(index)
{}
const char* value() const {
return enumeration_->lookup_enum_value(index_);
}
size_t index() const {
return index_;
}
const IfcParse::enumeration_type* enumeration() const {
return enumeration_;
}
};
class Blank {};
class Derived {};
class empty_aggregate_t {};
class empty_aggregate_of_aggregate_t {};
typedef VariantArray <
// A null argument, it will always serialize to $
Blank,
// @todo Derived is not really necessary anymore, just serialize correctly based on schema
// A derived argument, it will always serialize to *
Derived,
// An integer argument, e.g. 123
// SCALARS:
int,
// A boolean argument, it will serialize to either .T. or .F.
bool,
// A logical argument, it will serialize to either .T. or .F. or .U.
boost::logic::tribool,
// A floating point argument, e.g. 12.3
double,
// A character string argument, e.g. 'IfcOpenShell'
std::string,
// A binary argument, e.g. "092A" -> 100100101010
boost::dynamic_bitset<>,
// An enumeration argument, e.g. .USERDEFINED.
// To initialize the argument a string representation
// has to be explicitly passed of the enumeration value
// which is stored internally as an integer. The argument
// itself does not keep track of what schema enumeration
// type is represented.
EnumerationReference,
// An entity instance argument. It will either serialize to
// e.g. #123 or datatype identifier for simple types, e.g.
// IFCREAL(12.3)
IfcUtil::IfcBaseClass*,
// AGGREGATES:
empty_aggregate_t,
// An aggregate of integers, e.g. (1,2,3)
std::vector<int>,
// An aggregate of floats, e.g. (12.3,4.)
std::vector<double>,
// An aggregate of strings, e.g. ('Ifc','Open','Shell')
std::vector<std::string>,
// An aggregate of binaries, e.g. ("23B", "092A") -> (111011, 100100101010)
std::vector<boost::dynamic_bitset<>>,
// An aggregate of entity instances. It will either serialize to
// e.g. (#1,#2,#3) or datatype identifier for simple types,
// e.g. (IFCREAL(1.2),IFCINTEGER(3.))
aggregate_of_instance::ptr,
// AGGREGATES OF AGGREGATES:
empty_aggregate_of_aggregate_t,
// An aggregate of an aggregate of ints. E.g. ((1, 2), (3))
std::vector<std::vector<int>>,
// An aggregate of an aggregate of floats. E.g. ((1., 2.3), (4.))
std::vector<std::vector<double>>,
// An aggregate of an aggregate of entities. E.g. ((#1, #2), (#3))
aggregate_of_aggregate_of_instance::ptr
> storage_t;
struct MutableAttributeValue {
int name_;
uint8_t index_;
};
// short lived
struct AttributeValue {
const storage_t* array_;
uint8_t index_;
AttributeValue()
: array_(nullptr)
, index_(0)
{}
AttributeValue(const storage_t* arr, uint8_t index)
: array_(arr)
, index_(index)
{}
operator int() const;
operator bool() const;
operator boost::logic::tribool() const;
operator double() const;
operator std::string() const;
operator boost::dynamic_bitset<>() const;
operator IfcUtil::IfcBaseClass* () const;
operator std::vector<int>() const;
operator std::vector<double>() const;
operator std::vector<std::string>() const;
operator std::vector<boost::dynamic_bitset<>>() const;
operator boost::shared_ptr<aggregate_of_instance>() const;
operator std::vector<std::vector<int>>() const;
operator std::vector<std::vector<double>>() const;
operator boost::shared_ptr<aggregate_of_aggregate_of_instance>() const;
bool isNull() const;
unsigned int size() const;
IfcUtil::ArgumentType type() const;
};
class IFC_PARSE_API IfcEntityInstanceData {
public:
// Public for backwards compatibility
IfcParse::IfcFile* file;
storage_t storage_;
protected:
unsigned id_;
const IfcParse::declaration* type_;
mutable Argument** attributes_;
unsigned offset_in_file_;
IfcEntityInstanceData(storage_t&& storage)
: storage_(std::move(storage))
{}
public:
IfcEntityInstanceData(const IfcParse::declaration* type,
IfcParse::IfcFile* file,
unsigned id = 0,
unsigned offset_in_file = 0)
: file(file),
id_(id),
type_(type),
attributes_(0),
offset_in_file_(offset_in_file) {}
IfcEntityInstanceData(IfcEntityInstanceData&& other) noexcept
: storage_(std::move(other.storage_))
{}
IfcEntityInstanceData(IfcParse::IfcFile* file_, size_t size)
: file(file_),
id_(0),
type_(0),
attributes_(new Argument* [size] { 0 }),
offset_in_file_(0) {}
IfcEntityInstanceData(const IfcEntityInstanceData& data);
IfcEntityInstanceData(const IfcParse::declaration* type)
: file(0),
id_(0),
type_(type),
attributes_(new Argument* [getArgumentCount()] { 0 }),
offset_in_file_(0) {}
IfcEntityInstanceData& operator=(IfcEntityInstanceData&& other) {
if (this != &other) {
storage_ = std::move(other.storage_);
}
return *this;
}
void load() const;
AttributeValue get_attribute_value(size_t index) const;
IfcEntityInstanceData(const IfcEntityInstanceData& data);
/*
template <typename T>
void set_attribute_value(size_t index, const T& t);
virtual ~IfcEntityInstanceData();
void set_attribute_value(size_t index, AttributeValue&, IfcUtil::ArgumentType attr_type = IfcUtil::Argument_UNKNOWN);
*/
boost::shared_ptr<aggregate_of_instance> getInverse(const IfcParse::declaration* type, int attribute_index) const;
Argument* getArgument(size_t index) const;
// NB: This makes a copy of the argument if make_copy is set
void setArgument(size_t ibdex, Argument* argument, IfcUtil::ArgumentType attr_type = IfcUtil::Argument_UNKNOWN, bool make_copy = false);
virtual size_t getArgumentCount() const {
if (type_ == 0) {
return 0;
}
if (type_->as_entity() != nullptr) {
return type_->as_entity()->attribute_count();
}
return 1;
size_t size() const {
return storage_.size();
}
void clearArguments();
const IfcParse::declaration* type() const {
return type_;
}
std::string toString(bool upper = false) const;
unsigned int id() const { return id_; }
unsigned int offset_in_file() const { return offset_in_file_; }
// NB: const ommitted for lazy loading
Argument**& attributes() const { return attributes_; }
unsigned set_id(boost::optional<unsigned> id = boost::none);
void toString(std::ostream&, bool upper = false, const IfcParse::entity* ent = nullptr) const;
};
#endif
+274
View File
@@ -0,0 +1,274 @@
#include "IfcFile.h"
#include "IfcLogger.h"
IfcParse::parse_context::~parse_context() {
for (auto& t : tokens_) {
boost::apply_visitor([](auto& v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, parse_context*>) {
delete v;
}
}, t);
}
}
IfcParse::parse_context& IfcParse::parse_context::push() {
auto* pc = new IfcParse::parse_context;
tokens_.push_back(pc);
return *pc;
}
void IfcParse::parse_context::push(Token t) {
tokens_.push_back(t);
}
void IfcParse::parse_context::push(IfcUtil::IfcBaseClass* inst) {
tokens_.push_back(inst);
}
namespace {
template<typename Variant, typename T>
struct is_type_in_variant;
template<typename T, typename... Types>
struct is_type_in_variant<boost::variant<Types...>, T>
{
static constexpr bool value = (std::is_same<T, Types>::value || ...);
};
template<typename Variant, typename T>
constexpr bool is_type_in_variant_v = is_type_in_variant<Variant, T>::value;
struct InstanceReference {
int v;
operator int() const {
return v;
}
};
template <typename Fn>
void dispatch_token(IfcParse::Token t, IfcParse::declaration* decl, Fn fn) {
if (t.type == IfcParse::Token_BINARY) {
fn(IfcParse::TokenFunc::asBinary(t));
} else if (t.type == IfcParse::Token_BOOL) {
fn(IfcParse::TokenFunc::asBool(t));
} else if (t.type == IfcParse::Token_ENUMERATION) {
if (decl->as_enumeration_type()) {
try {
fn(EnumerationReference(decl->as_enumeration_type(), decl->as_enumeration_type()->lookup_enum_offset(IfcParse::TokenFunc::asStringRef(t))));
} catch (IfcParse::IfcException& e) {
Logger::Error(e);
}
}
} else if (t.type == IfcParse::Token_FLOAT) {
fn(IfcParse::TokenFunc::asFloat(t));
} else if (t.type == IfcParse::Token_IDENTIFIER) {
fn(IfcParse::reference_or_simple_type{ 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));
} else if (t.type == IfcParse::Token_OPERATOR && t.value_char == '*') {
// This is only in place for the validator
fn(Derived{});
}
}
template <size_t Depth, typename Fn>
void construct_(IfcParse::parse_context& p, const IfcParse::aggregation_type* aggr, Fn fn) {
if (p.tokens_.empty()) {
// @todo instead of ugly if-else we could also default initialize the respective
// variant types below.
if (aggr) {
auto aggr_type = IfcUtil::make_aggregate(IfcUtil::from_parameter_type(aggr->type_of_element()));
if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_INT) {
fn(std::vector<int>{});
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) {
fn(std::vector<double>{});
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_STRING) {
fn(std::vector<std::string>{});
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_BINARY) {
fn(std::vector<boost::dynamic_bitset<>>{});
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
fn(aggregate_of_instance::ptr(new aggregate_of_instance));
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT) {
fn(std::vector<std::vector<int>>{});
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE) {
fn(std::vector<std::vector<double>>{});
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) {
fn(aggregate_of_aggregate_of_instance::ptr(new aggregate_of_aggregate_of_instance));
}
}
return;
}
typedef boost::variant<
Blank,
std::vector<int>,
std::vector<double>,
std::vector<std::string>,
std::vector<boost::dynamic_bitset<>>,
std::vector<IfcParse::reference_or_simple_type>,
std::vector<std::vector<int>>,
std::vector<std::vector<double>>,
std::vector<std::vector<IfcParse::reference_or_simple_type>>
> possible_aggregation_types_t;
possible_aggregation_types_t aggregate_storage;
auto append_to_aggregate_storage = [&aggregate_storage](const auto& v) {
if constexpr (is_type_in_variant_v<possible_aggregation_types_t, std::vector<std::decay_t<decltype(v)>>>) {
if (aggregate_storage.which() == 0) {
aggregate_storage = std::vector<std::decay_t<decltype(v)>>{ v };
} else {
auto* vec_ptr = boost::get<std::vector<std::decay_t<decltype(v)>>>(&aggregate_storage);
if (vec_ptr) {
vec_ptr->push_back(v);
} else {
// @todo would be cool if we can trace this back to file offset
auto current = boost::apply_visitor([](auto v) {
if constexpr (!std::is_same_v<decltype(v), Blank>) {
return std::string(typeid(typename decltype(v)::value_type).name());
} else {
// Cannot occur as aggregate_storage.which() == 0
// is another branch several statements up. But is
// needed for consistency of return type.
return std::string{};
}
}, aggregate_storage);
Logger::Error("Inconsistent aggregate valuation while attempting to append " + std::string(typeid(decltype(v)).name()) + " to an aggregate of " + current);
// @todo boolean -> logical upgrade
// wait a second... there are no aggregate of bool / logical in the schema..
//
// if constexpr (std::is_same_v<std::decay_t<decltype(v)>, bool>) {
// auto* vec_ptr = boost::get<std::vector<boost::tribool>(&aggregate_storage);
// vec_ptr->push_back(v);
// }
// if constexpr (std::is_same_v<std::decay_t<decltype(v)>, boost::tribool>) {
// auto* vec_ptr = boost::get<std::vector<bool>(&aggregate_storage);
// std::vector<boost::tribool> ps(vec_ptr->begin(), vec_ptr->end());
// ps.push_back(v);
// aggregate_storage = ps;
// }
}
}
} else {
// @todo would be cool if we can trace this back to file offset
Logger::Error(std::string("Aggregates of ") + typeid(decltype(v)).name() + " are not supported in the IfcOpenShell parser");
}
};
for (auto& t : p.tokens_) {
boost::apply_visitor([&aggregate_storage, &append_to_aggregate_storage, aggr](const auto& v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::Token>) {
// @todo get aggregate of enumeration
dispatch_token(v, aggr && aggr->type_of_element()->as_named_type() ? aggr->type_of_element()->as_named_type()->declared_type() : nullptr, append_to_aggregate_storage);
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::parse_context*>) {
// nested list
if constexpr (Depth < 3) {
construct_<Depth + 1>(*v, nullptr, append_to_aggregate_storage);
}
} else {
append_to_aggregate_storage(IfcParse::reference_or_simple_type{ v });
}
}, t);
}
boost::apply_visitor(fn, aggregate_storage);
}
}
IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional<size_t> expected_size) {
std::vector<const IfcParse::parameter_type*> parameter_types;
std::unique_ptr<IfcParse::named_type> transient_named_type;
if ((decl != nullptr) && (decl->as_type_declaration() != nullptr)) {
parameter_types = { decl->as_type_declaration()->declared_type() };
} else if ((decl != nullptr) && (decl->as_enumeration_type() != nullptr)) {
transient_named_type.reset(new IfcParse::named_type(const_cast<IfcParse::declaration*>(decl)));
parameter_types = { &*transient_named_type };
} else if ((decl != nullptr) && (decl->as_entity() != nullptr)) {
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();
}
);
}
if (((decl != nullptr) && (tokens_.size() != parameter_types.size())) ||
expected_size && *expected_size != tokens_.size())
{
size_t expected = expected_size ? *expected_size : parameter_types.size();
Logger::Warning("Expected " + std::to_string(expected) + " attribute values, found " + std::to_string(tokens_.size()) + " for instance #" + std::to_string(name > 0 ? name : 0));
}
if (tokens_.empty()) {
return IfcEntityInstanceData(storage_t(0));
}
storage_t storage(decl != nullptr
? (std::min)(parameter_types.size(), tokens_.size())
: tokens_.size()
);
auto it = tokens_.begin();
auto kt = parameter_types.begin();
for (; it != tokens_.end() && ((decl == nullptr) || kt != parameter_types.end()); ++it) {
auto& token = *it;
// @todo coerce to expected type, e.g empty -> std::vector<int>, bool -> logical
const IfcParse::parameter_type* param_type = nullptr;
if (decl != nullptr) {
param_type = *kt;
}
auto index = (uint8_t) std::distance(tokens_.begin(), it);
boost::apply_visitor([this, &storage, name, &references_to_resolve, index, param_type](const auto& v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::Token>) {
dispatch_token(v, param_type && param_type->as_named_type() ? param_type->as_named_type()->declared_type() : nullptr, [this, &storage, name, &references_to_resolve, index](auto v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::reference_or_simple_type>) {
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 },
v
));
} else {
storage.set(index, v);
}
});
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::parse_context*>) {
const auto *pt = param_type;
if (pt) {
while (pt->as_named_type() && pt->as_named_type()->declared_type()->as_type_declaration()) {
pt = pt->as_named_type()->declared_type()->as_type_declaration()->declared_type();
}
}
construct_<0>(*v, pt ? pt->as_aggregation_type() : nullptr, [this, &storage, name, &references_to_resolve, index](const auto& v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<reference_or_simple_type>>) {
references_to_resolve.push_back({ {name, index }, v });
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<std::vector<reference_or_simple_type>>>) {
references_to_resolve.push_back({ {name, index }, v });
} else {
storage.set(index, v);
}
});
} else {
storage.set(index, v);
}
}, token);
if (decl != nullptr) {
++kt;
}
}
return IfcEntityInstanceData(std::move(storage));
}
+45 -22
View File
@@ -30,6 +30,7 @@
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/unordered_map.hpp>
#include <boost/variant.hpp>
#include <iterator>
#include <map>
@@ -64,15 +65,46 @@ class IFC_PARSE_API file_open_status {
}
};
typedef boost::variant<int, IfcUtil::IfcBaseClass*> reference_or_simple_type;
typedef std::list<std::pair<MutableAttributeValue, boost::variant<reference_or_simple_type, std::vector<reference_or_simple_type>, std::vector<std::vector<reference_or_simple_type>>>>> unresolved_references;
struct parse_context {
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(parse_context&&) = default;
parse_context& operator=(parse_context&&) = default;
parse_context& push();
void push(Token t);
void push(IfcUtil::IfcBaseClass* inst);
IfcEntityInstanceData construct(int name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional<size_t> expected_size);
};
/// This class provides several static convenience functions and variables
/// and provide access to the entities in an IFC file
class IFC_PARSE_API IfcFile {
public:
unresolved_references references_to_resolve;
typedef std::map<const IfcParse::declaration*, aggregate_of_instance::ptr> entities_by_type_t;
typedef boost::unordered_map<unsigned int, IfcUtil::IfcBaseClass*> entity_by_id_t;
typedef boost::unordered_map<uint32_t, IfcUtil::IfcBaseClass*> entity_by_iden_t;
typedef std::map<std::string, IfcUtil::IfcBaseClass*> entity_by_guid_t;
typedef std::tuple<int, int, int> inverse_attr_record;
typedef std::tuple<int, short, short> inverse_attr_record;
enum INVERSE_ATTR {
INSTANCE_ID,
INSTANCE_TYPE,
@@ -116,10 +148,6 @@ class IFC_PARSE_API IfcFile {
}
};
static bool lazy_load_;
static bool lazy_load() { return lazy_load_; }
static void lazy_load(bool b) { lazy_load_ = b; }
static bool guid_map_;
static bool guid_map() { return guid_map_; }
static void guid_map(bool b) { guid_map_ = b; }
@@ -127,21 +155,20 @@ class IFC_PARSE_API IfcFile {
private:
typedef std::map<uint32_t, IfcUtil::IfcBaseClass*> entity_entity_map_t;
bool parsing_complete_;
file_open_status good_ = file_open_status::SUCCESS;
const IfcParse::schema_definition* schema_;
const IfcParse::declaration* ifcroot_type_;
std::vector<Argument*> internal_attribute_vector_, internal_attribute_vector_simple_type_;
// std::vector<Argument*> internal_attribute_vector_, internal_attribute_vector_simple_type_;
entity_by_id_t byid_;
// this is for simple types
entity_by_iden_t byidentity_;
entities_by_type_t bytype_;
// entities_by_type_t bytype_;
entities_by_type_t bytype_excl_;
entities_by_ref_t byref_;
entities_by_ref_excl_t byref_excl_;
// entities_by_ref_t byref_;
entities_by_ref_t byref_excl_;
entity_by_guid_t byguid_;
entity_entity_map_t entity_file_map_;
@@ -195,8 +222,8 @@ class IFC_PARSE_API IfcFile {
type_iterator types_begin() const;
type_iterator types_end() const;
type_iterator types_incl_super_begin() const;
type_iterator types_incl_super_end() const;
// type_iterator types_incl_super_begin() const;
// type_iterator types_incl_super_end() const;
/// Returns all entities in the file that match the template argument.
/// NOTE: This also returns subtypes of the requested type, for example:
@@ -247,11 +274,11 @@ class IFC_PARSE_API IfcFile {
/// Performs a depth-first traversal, returning all entity instance
/// attributes as a flat list. NB: includes the root instance specified
/// in the first function argument.
aggregate_of_instance::ptr traverse(IfcUtil::IfcBaseClass* instance, int max_level = -1);
static aggregate_of_instance::ptr traverse(IfcUtil::IfcBaseClass* instance, int max_level = -1);
/// Same as traverse() but maintains topological order by using a
/// breadth-first search
aggregate_of_instance::ptr traverse_breadth_first(IfcUtil::IfcBaseClass* instance, int max_level = -1);
static aggregate_of_instance::ptr traverse_breadth_first(IfcUtil::IfcBaseClass* instance, int max_level = -1);
/// Get the attribute indices corresponding to the list of entity instances
/// returned by getInverse().
@@ -264,7 +291,7 @@ class IFC_PARSE_API IfcFile {
aggregate_of_instance::ptr getInverse(int instance_id, const IfcParse::declaration* type, int attribute_index);
int getTotalInverses(int instance_id);
size_t getTotalInverses(int instance_id);
unsigned int FreshId() { return ++MaxId; }
@@ -297,11 +324,10 @@ class IFC_PARSE_API IfcFile {
const IfcSpfHeader& header() const { return _header; }
IfcSpfHeader& header() { return _header; }
std::string createTimestamp() const;
static std::string createTimestamp() ;
size_t load(unsigned entity_instance_name, const IfcParse::entity* entity, Argument**& attributes, size_t num_attributes, int attribute_index = -1);
void seek_to(const IfcEntityInstanceData& data);
void try_read_semicolon();
void load(unsigned entity_instance_name, const IfcParse::entity* entity, parse_context&, int attribute_index = -1);
void try_read_semicolon() const;
void register_inverse(unsigned, const IfcParse::entity* from_entity, Token, int attribute_index);
void register_inverse(unsigned, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass*, int attribute_index);
@@ -311,9 +337,6 @@ class IFC_PARSE_API IfcFile {
std::pair<IfcUtil::IfcBaseClass*, double> getUnit(const std::string& unit_type);
bool parsing_complete() const { return parsing_complete_; }
bool& parsing_complete() { return parsing_complete_; }
void build_inverses();
entity_by_guid_t& internal_guid_map() { return byguid_; };
+1 -1
View File
@@ -94,7 +94,7 @@ IfcParse::IfcGlobalId::IfcGlobalId() {
uuid_data_ = gen();
std::vector<unsigned char> v(uuid_data_.size());
std::copy(uuid_data_.begin(), uuid_data_.end(), v.begin());
string_data_ = compress(&v[0]);
string_data_ = compress(v.data());
#if BOOST_VERSION < 104400
formatted_string = boost::lexical_cast<std::string>(uuid_data);
#else
+9 -31
View File
@@ -340,21 +340,15 @@ void set_children_of_relation(Ifc4x3_add2::IfcRelAggregates* t, aggregate_of_ins
#endif
IfcUtil::IfcBaseClass* get_parent_of_relation(IfcUtil::IfcBaseClass* t) {
return *t->data().getArgument(
t->declaration().as_entity()->attribute_index("RelatingObject"));
return t->as<IfcUtil::IfcBaseEntity>()->get("RelatingObject");
}
aggregate_of_instance::ptr get_children_of_relation(IfcUtil::IfcBaseClass* t) {
return *t->data().getArgument(
t->declaration().as_entity()->attribute_index("RelatedElements"));
return t->as<IfcUtil::IfcBaseEntity>()->get("RelatedElements");
}
void set_children_of_relation(IfcUtil::IfcBaseClass* t, aggregate_of_instance::ptr& cs) {
IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument;
attr->set(cs);
t->data().setArgument(
t->declaration().as_entity()->attribute_index("RelatedElements"),
attr);
return t->as<IfcUtil::IfcBaseEntity>()->set_attribute_value("RelatedElements", cs);
}
} // namespace
template <typename Schema>
@@ -440,35 +434,19 @@ class IFC_PARSE_API IfcHierarchyHelper : public IfcParse::IfcFile {
aggregate_of_instance::ptr related_objects(new aggregate_of_instance);
related_objects->push(related_object);
IfcEntityInstanceData* data = new IfcEntityInstanceData(&T::Class());
{
IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();
attr->set<std::string>(IfcParse::IfcGlobalId());
data->setArgument(0, attr);
}
{
IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();
attr->set(owner_hist);
data->setArgument(1, attr);
}
IfcEntityInstanceData data = IfcEntityInstanceData(storage_t(T::Class().attribute_count()));
data.storage_.set(0, (std::string)IfcParse::IfcGlobalId());
data.storage_.set(1, owner_hist);
int relating_index = 4;
int related_index = 5;
if (T::Class().name() == "IfcRelContainedInSpatialStructure" || std::is_base_of<typename Schema::IfcRelDefines, T>::value) {
// some classes have attributes reversed.
std::swap(relating_index, related_index);
}
{
IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();
attr->set(relating_object);
data->setArgument(relating_index, attr);
}
{
IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();
attr->set(related_objects);
data->setArgument(related_index, attr);
}
data.storage_.set(relating_index, relating_object);
data.storage_.set(related_index, related_objects);
T* t = (T*)Schema::get_schema().instantiate(data);
T* t = (T*)Schema::get_schema().instantiate(&T::Class(), std::move(data));
addEntity(t);
}
}
+15 -5
View File
@@ -65,12 +65,14 @@ void plain_text_message(T& out, const boost::optional<const IfcUtil::IfcBaseClas
out << "[" << severity_strings<typename T::char_type>::value[type] << "] ";
out << "[" << get_time(type <= Logger::LOG_PERF).c_str() << "] ";
if (current_product) {
std::string global_id = *((IfcUtil::IfcBaseEntity*)*current_product)->get("GlobalId");
std::string global_id = (*current_product)->as<IfcUtil::IfcBaseEntity>()->get("GlobalId");
out << "{" << global_id.c_str() << "} ";
}
out << message.c_str() << std::endl;
if (instance) {
std::string instance_string = instance->data().toString();
std::ostringstream oss;
instance->as<IfcUtil::IfcBaseClass>()->toString(oss);
auto instance_string = oss.str();
if (instance_string.size() > 259) {
instance_string = instance_string.substr(0, 256) + "...";
}
@@ -98,11 +100,15 @@ void json_message(T& out, const boost::optional<const IfcUtil::IfcBaseClass*>& c
property_tree.put(level_string, severity_strings<typename T::char_type>::value[type]);
if (current_product) {
property_tree.put(product_string, string_as<typename T::char_type>((**current_product).data().toString()));
std::ostringstream oss;
(*current_product)->toString(oss);
property_tree.put(product_string, string_as<typename T::char_type>(oss.str()));
}
property_tree.put(message_string, string_as<typename T::char_type>(message));
if (instance) {
property_tree.put(instance_string, string_as<typename T::char_type>(instance->data().toString()));
std::ostringstream oss;
instance->as<IfcUtil::IfcBaseClass>()->toString(oss);
property_tree.put(instance_string, string_as<typename T::char_type>(oss.str()));
}
property_tree.put(time_string, string_as<typename T::char_type>(get_time()));
@@ -141,6 +147,10 @@ void Logger::SetOutput(std::wostream* stream1, std::wostream* stream2) {
}
void Logger::Message(Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseInterface* instance) {
if (type < verbosity_) {
return;
}
static std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx);
@@ -160,7 +170,7 @@ void Logger::Message(Logger::Severity type, const std::string& message, const If
if (type > max_severity_) {
max_severity_ = type;
}
if (((log2_ != nullptr) || (wlog2_ != nullptr)) && type >= verbosity_) {
if (((log2_ != nullptr) || (wlog2_ != nullptr))) {
if (format_ == FMT_PLAIN) {
if (log2_ != nullptr) {
plain_text_message(*log2_, current_product_, type, message, instance);
+637 -980
View File
File diff suppressed because it is too large Load Diff
+3 -102
View File
@@ -148,8 +148,8 @@ Token NoneTokenPtr();
class IFC_PARSE_API IfcSpfLexer {
private:
IfcCharacterDecoder* decoder_;
unsigned int skipWhitespace();
unsigned int skipComment();
unsigned int skipWhitespace() const;
unsigned int skipComment() const;
public:
std::string& GetTempString() const {
@@ -164,106 +164,7 @@ class IFC_PARSE_API IfcSpfLexer {
void TokenString(unsigned int offset, std::string& result);
};
/// Argument of type list, e.g.
/// #1=IfcDirection((1.,0.,0.));
/// ==========
class IFC_PARSE_API ArgumentList : public Argument {
private:
size_t size_;
Argument** list_;
public:
ArgumentList() : size_(0),
list_(0) {}
ArgumentList(size_t n) : size_(n),
list_(new Argument* [size_] { 0 }) {}
~ArgumentList();
void read(IfcSpfLexer* lexer, std::vector<unsigned int>& ids);
IfcUtil::ArgumentType type() const;
operator std::vector<int>() const;
operator std::vector<double>() const;
operator std::vector<std::string>() const;
operator std::vector<boost::dynamic_bitset<>>() const;
operator aggregate_of_instance::ptr() const;
operator std::vector<std::vector<int>>() const;
operator std::vector<std::vector<double>>() const;
operator aggregate_of_aggregate_of_instance::ptr() const;
bool isNull() const;
unsigned int size() const;
Argument* operator[](unsigned int index) const;
std::string toString(bool upper = false) const;
Argument**& arguments() { return list_; }
size_t& size() { return size_; }
};
/// Argument being null, e.g. '$'
/// == ===
class IFC_PARSE_API NullArgument : public Argument {
public:
NullArgument() {}
IfcUtil::ArgumentType type() const { return IfcUtil::Argument_NULL; }
bool isNull() const { return true; }
unsigned int size() const { return 1; }
Argument* operator[](unsigned int /*i*/) const { throw IfcException("Argument is not a list of attributes"); }
std::string toString(bool /*upper=false*/) const { return "$"; }
};
/// Argument of type scalar or string, e.g.
/// #1=IfcVector(#2,1.0);
/// == ===
class IFC_PARSE_API TokenArgument : public Argument {
public:
Token token;
TokenArgument(const Token& token);
IfcUtil::ArgumentType type() const;
operator int() const;
operator bool() const;
operator boost::logic::tribool() const;
operator double() const;
operator std::string() const;
operator boost::dynamic_bitset<>() const;
operator IfcUtil::IfcBaseClass*() const;
bool isNull() const;
unsigned int size() const;
Argument* operator[](unsigned int index) const;
std::string toString(bool upper = false) const;
};
/// Argument of an IFC simple type
/// #1=IfcTrimmedCurve(#2,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.)),.T.,.PARAMETER.);
/// ===================== =====================
class IFC_PARSE_API EntityArgument : public Argument {
private:
IfcUtil::IfcBaseClass* entity_;
public:
EntityArgument(const Token& token);
~EntityArgument();
IfcUtil::ArgumentType type() const;
operator IfcUtil::IfcBaseClass*() const;
bool isNull() const;
unsigned int size() const;
Argument* operator[](unsigned int index) const;
std::string toString(bool upper = false) const;
};
IFC_PARSE_API IfcEntityInstanceData* read(unsigned int index, IfcFile* file, boost::optional<unsigned> offset = boost::none);
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);
+1 -1
View File
@@ -120,7 +120,7 @@ double IfcParse::get_SI_equivalent(typename Schema::IfcNamedUnit* named_unit) {
if (component->declaration().is(Schema::IfcSIUnit::Class())) {
si_unit = component->template as<typename Schema::IfcSIUnit>();
typename Schema::IfcValue* value = factor->ValueComponent();
scale = *value->data().getArgument(0);
scale = value->data().get_attribute_value(0);
}
} else if (named_unit->declaration().is(Schema::IfcSIUnit::Class())) {
si_unit = named_unit->template as<typename Schema::IfcSIUnit>();
+3 -3
View File
@@ -152,11 +152,11 @@ IfcParse::schema_definition::~schema_definition() {
delete factory_;
}
IfcUtil::IfcBaseClass* IfcParse::schema_definition::instantiate(IfcEntityInstanceData* data) const {
IfcUtil::IfcBaseClass* IfcParse::schema_definition::instantiate(const IfcParse::declaration* decl, IfcEntityInstanceData&& data) const {
if (factory_ != nullptr) {
return (*factory_)(data);
return (*factory_)(decl, std::move(data));
}
return new IfcUtil::IfcLateBoundEntity(data->type(), data);
return new IfcUtil::IfcLateBoundEntity(decl, std::move(data));
}
void IfcParse::register_schema(schema_definition* schema) {
+2 -2
View File
@@ -441,7 +441,7 @@ class IFC_PARSE_API instance_factory {
public:
virtual ~instance_factory() {}
virtual IfcUtil::IfcBaseClass* operator()(IfcEntityInstanceData* data) const = 0;
virtual IfcUtil::IfcBaseClass* operator()(const IfcParse::declaration* decl, IfcEntityInstanceData&& data) const = 0;
};
class IFC_PARSE_API schema_definition {
@@ -507,7 +507,7 @@ class IFC_PARSE_API schema_definition {
const std::string& name() const { return name_; }
IfcUtil::IfcBaseClass* instantiate(IfcEntityInstanceData* data) const;
IfcUtil::IfcBaseClass* instantiate(const IfcParse::declaration* decl, IfcEntityInstanceData&& data) const;
};
IFC_PARSE_API const schema_definition* schema_by_name(const std::string&);
+18 -11
View File
@@ -36,18 +36,22 @@ 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->tokens->Next();
f->load(-1, nullptr, pc, -1);
return pc.construct(-1, f->references_to_resolve, nullptr, s);
}
}
HeaderEntity::HeaderEntity(const char* const datatype, size_t size, IfcFile* file)
: datatype_(datatype)
, file_(file)
, data_(file ? read_from_file(file, size) : IfcEntityInstanceData(storage_t(size)))
{}
HeaderEntity::~HeaderEntity() {
clearArguments();
}
void IfcSpfHeader::readSemicolon() {
@@ -89,18 +93,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() {
+30 -27
View File
@@ -21,41 +21,41 @@
#define IFCSPFHEADER_H
#include "ifc_parse_api.h"
#include "IfcWrite.h"
#include "IfcEntityInstanceData.h"
namespace IfcParse {
class IfcFile;
class IFC_PARSE_API HeaderEntity : public IfcEntityInstanceData {
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:
IfcEntityInstanceData data_;
HeaderEntity(const char* const datatype, size_t size, IfcParse::IfcFile* file);
virtual ~HeaderEntity();
void setValue(unsigned int index, const std::string& string) {
IfcWrite::IfcWriteArgument* argument = new IfcWrite::IfcWriteArgument;
argument->set(string);
setArgument(index, argument);
data_.storage_.set(index, string);
}
void setValue(unsigned int index, const std::vector<std::string>& strings) {
IfcWrite::IfcWriteArgument* argument = new IfcWrite::IfcWriteArgument;
argument->set(strings);
setArgument(index, argument);
data_.storage_.set(index, strings);
}
public:
virtual size_t getArgumentCount() const {
return size_;
return data_.size();
}
std::string toString(bool upper = false) const {
std::stringstream stream;
stream << datatype_ << IfcEntityInstanceData::toString(upper);
stream << datatype_;
data_.toString(stream, upper);
return stream.str();
}
};
@@ -64,8 +64,8 @@ class IFC_PARSE_API FileDescription : public HeaderEntity {
public:
explicit FileDescription(IfcFile* = 0);
std::vector<std::string> description() const { return *getArgument(0); }
std::string implementation_level() const { return *getArgument(1); }
std::vector<std::string> description() const { return data_.get_attribute_value(0); }
std::string implementation_level() const { return data_.get_attribute_value(1); }
void description(const std::vector<std::string>& value) { setValue(0, value); }
void implementation_level(const std::string& value) { setValue(1, value); }
@@ -75,13 +75,13 @@ class IFC_PARSE_API FileName : public HeaderEntity {
public:
explicit FileName(IfcFile* = 0);
std::string name() const { return *getArgument(0); }
std::string time_stamp() const { return *getArgument(1); }
std::vector<std::string> author() const { return *getArgument(2); }
std::vector<std::string> organization() const { return *getArgument(3); }
std::string preprocessor_version() const { return *getArgument(4); }
std::string originating_system() const { return *getArgument(5); }
std::string authorization() const { return *getArgument(6); }
std::string name() const { return data_.get_attribute_value(0); }
std::string time_stamp() const { return data_.get_attribute_value(1); }
std::vector<std::string> author() const { return data_.get_attribute_value(2); }
std::vector<std::string> organization() const { return data_.get_attribute_value(3); }
std::string preprocessor_version() const { return data_.get_attribute_value(4); }
std::string originating_system() const { return data_.get_attribute_value(5); }
std::string authorization() const { return data_.get_attribute_value(6); }
void name(const std::string& value) { setValue(0, value); }
void time_stamp(const std::string& value) { setValue(1, value); }
@@ -96,7 +96,7 @@ class IFC_PARSE_API FileSchema : public HeaderEntity {
public:
explicit FileSchema(IfcFile* = 0);
std::vector<std::string> schema_identifiers() const { return *getArgument(0); }
std::vector<std::string> schema_identifiers() const { return data_.get_attribute_value(0); }
void schema_identifiers(const std::vector<std::string>& value) { setValue(0, value); }
};
@@ -117,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() {
+2 -2
View File
@@ -71,9 +71,9 @@ class IFC_PARSE_API IfcSpfStream {
/// Moves the file cursor to an arbitrary offset in the file
void Seek(unsigned int offset);
/// Returns the cursor position
unsigned int Tell();
unsigned int Tell() const;
bool is_eof_at(unsigned int);
bool is_eof_at(unsigned int) const;
void increment_at(unsigned int&);
char peek_at(unsigned int);
};
+22 -1
View File
@@ -56,6 +56,7 @@
#include "IfcBaseClass.h"
#include "IfcException.h"
#include "utils.h"
#include "IfcFile.h"
#include <algorithm>
#include <boost/algorithm/string/replace.hpp>
@@ -121,6 +122,7 @@ aggregate_of_instance::ptr aggregate_of_instance::unique() {
return return_value;
}
/*
//Note: some of these methods are overloaded in derived classes
Argument::operator int() const { throw IfcParse::IfcException("Argument is not an integer"); }
Argument::operator bool() const { throw IfcParse::IfcException("Argument is not a boolean"); }
@@ -137,6 +139,7 @@ Argument::operator aggregate_of_instance::ptr() const { throw IfcParse::IfcExcep
Argument::operator std::vector<std::vector<int>>() const { throw IfcParse::IfcException("Argument is not a list of list of ints"); }
Argument::operator std::vector<std::vector<double>>() const { throw IfcParse::IfcException("Argument is not a list of list of floats"); }
Argument::operator aggregate_of_aggregate_of_instance::ptr() const { throw IfcParse::IfcException("Argument is not a list of list of entity instances"); }
*/
static const char* const argument_type_string[] = {
"NULL",
@@ -199,16 +202,32 @@ void IfcUtil::unescape_xml(std::string& str) {
boost::replace_all(str, "&gt;", ">");
}
/*
Argument* IfcUtil::IfcBaseEntity::get(const std::string& name) const {
return data().getArgument(declaration().attribute_index(name));
}
*/
AttributeValue IfcUtil::IfcBaseEntity::get(const std::string& name) const
{
auto attrs = declaration().as_entity()->all_attributes();
auto iter = attrs.begin();
size_t idx = 0;
for (; iter != attrs.end(); ++iter, ++idx) {
if ((*iter)->name() == name) {
return data().get_attribute_value(idx);
}
}
throw IfcParse::IfcException(name + " not found on " + declaration().name());
}
aggregate_of_instance::ptr IfcUtil::IfcBaseEntity::get_inverse(const std::string& name) const {
const std::vector<const IfcParse::inverse_attribute*> attrs = declaration().as_entity()->all_inverse_attributes();
std::vector<const IfcParse::inverse_attribute*>::const_iterator iter = attrs.begin();
for (; iter != attrs.end(); ++iter) {
if ((*iter)->name() == name) {
return data().getInverse(
return file_->getInverse(
id_,
(*iter)->entity_reference(),
(int)(*iter)->entity_reference()->attribute_index((*iter)->attribute_reference()));
}
@@ -216,10 +235,12 @@ aggregate_of_instance::ptr IfcUtil::IfcBaseEntity::get_inverse(const std::string
throw IfcParse::IfcException(name + " not found on " + declaration().name());
}
/*
void IfcUtil::IfcBaseClass::data(IfcEntityInstanceData* data) {
delete data_;
data_ = data;
}
*/
IfcUtil::ArgumentType IfcUtil::make_aggregate(IfcUtil::ArgumentType elem_type) {
switch (elem_type) {
-341
View File
@@ -1,341 +0,0 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#include "IfcWrite.h"
#include "IfcCharacterDecoder.h"
#include <boost/algorithm/string.hpp>
#include <iomanip>
#include <limits>
#include <locale>
using namespace IfcWrite;
class SizeVisitor : public boost::static_visitor<int> {
public:
int operator()(const boost::blank& /*i*/) const { return -1; }
int operator()(const IfcWriteArgument::Derived& /*i*/) const { return -1; }
int operator()(const int& /*i*/) const { return -1; }
int operator()(const bool& /*i*/) const { return -1; }
int operator()(const boost::logic::tribool& /*i*/) const { return -1; }
int operator()(const double& /*i*/) const { return -1; }
int operator()(const std::string& /*i*/) const { return -1; }
int operator()(const boost::dynamic_bitset<>& /*i*/) const { return -1; }
int operator()(const IfcWriteArgument::empty_aggregate_t&) const { return 0; }
int operator()(const IfcWriteArgument::empty_aggregate_of_aggregate_t&) const { return 0; }
int operator()(const std::vector<int>& i) const { return (int)i.size(); }
int operator()(const std::vector<double>& i) const { return (int)i.size(); }
int operator()(const std::vector<std::vector<int>>& i) const { return (int)i.size(); }
int operator()(const std::vector<std::vector<double>>& i) const { return (int)i.size(); }
int operator()(const std::vector<std::string>& i) const { return (int)i.size(); }
int operator()(const std::vector<boost::dynamic_bitset<>>& i) const { return (int)i.size(); }
int operator()(const IfcWriteArgument::EnumerationReference& /*i*/) const { return -1; }
int operator()(const IfcUtil::IfcBaseClass* const& /*i*/) const { return -1; }
int operator()(const aggregate_of_instance::ptr& i) const { return i->size(); }
int operator()(const aggregate_of_aggregate_of_instance::ptr& i) const { return i->size(); }
};
class StringBuilderVisitor : public boost::static_visitor<void> {
private:
StringBuilderVisitor(const StringBuilderVisitor&); //N/A
StringBuilderVisitor& operator=(const StringBuilderVisitor&); //N/A
std::ostringstream& data_;
template <typename T>
void serialize(const std::vector<T>& i) {
data_ << "(";
for (typename std::vector<T>::const_iterator it = i.begin(); it != i.end(); ++it) {
if (it != i.begin()) {
data_ << ",";
}
data_ << *it;
}
data_ << ")";
}
// The REAL token definition from the IFC SPF standard does not necessarily match
// the output of the C++ ostream formatting operation.
// REAL = [ SIGN ] DIGIT { DIGIT } "." { DIGIT } [ "E" [ SIGN ] DIGIT { DIGIT } ] .
std::string format_double(const double& d) {
std::ostringstream oss;
oss.imbue(std::locale::classic());
oss << std::setprecision(std::numeric_limits<double>::digits10) << d;
const std::string str = oss.str();
oss.str("");
std::string::size_type e = str.find('e');
if (e == std::string::npos) {
e = str.find('E');
}
const std::string mantissa = str.substr(0, e);
oss << mantissa;
if (mantissa.find('.') == std::string::npos) {
oss << ".";
}
if (e != std::string::npos) {
oss << "E";
oss << str.substr(e + 1);
}
return oss.str();
}
std::string format_binary(const boost::dynamic_bitset<>& b) {
std::ostringstream oss;
oss.imbue(std::locale::classic());
oss.put('"');
oss << std::uppercase << std::hex << std::setw(1);
unsigned c = (unsigned)b.size();
unsigned n = (4 - (c % 4)) & 3;
oss << n;
for (unsigned i = 0; i < c + n;) {
unsigned accum = 0;
for (int j = 0; j < 4; ++j, ++i) {
unsigned bit = i < n ? 0 : b.test(c - i + n - 1) ? 1
: 0;
accum |= bit << (3 - j);
}
oss << accum;
}
oss.put('"');
return oss.str();
}
bool upper_;
public:
StringBuilderVisitor(std::ostringstream& stream, bool upper = false)
: data_(stream),
upper_(upper) {}
void operator()(const boost::blank& /*i*/) { data_ << "$"; }
void operator()(const IfcWriteArgument::Derived& /*i*/) { data_ << "*"; }
void operator()(const int& i) { data_ << i; }
void operator()(const bool& i) { data_ << (i ? ".T." : ".F."); }
void operator()(const boost::logic::tribool& i) { data_ << (i ? ".T." : (boost::logic::indeterminate(i) ? ".U." : ".F.")); }
void operator()(const double& i) { data_ << format_double(i); }
void operator()(const boost::dynamic_bitset<>& i) { data_ << format_binary(i); }
void operator()(const std::string& i) {
std::string s = i;
if (upper_) {
data_ << static_cast<std::string>(IfcCharacterEncoder(s));
} else {
data_ << '\'' << s << '\'';
}
}
void operator()(const std::vector<int>& i);
void operator()(const std::vector<double>& i);
void operator()(const std::vector<std::string>& i);
void operator()(const std::vector<boost::dynamic_bitset<>>& i);
void operator()(const IfcWriteArgument::EnumerationReference& i) {
data_ << "." << i.enumeration_value << ".";
}
void operator()(const IfcUtil::IfcBaseClass* const& i) {
const IfcEntityInstanceData& e = i->data();
if (e.type()->as_entity() == nullptr) {
data_ << e.toString(upper_);
} else {
data_ << "#" << e.id();
}
}
void operator()(const aggregate_of_instance::ptr& i) {
data_ << "(";
for (aggregate_of_instance::it it = i->begin(); it != i->end(); ++it) {
if (it != i->begin()) {
data_ << ",";
}
(*this)(*it);
}
data_ << ")";
}
void operator()(const std::vector<std::vector<int>>& i);
void operator()(const std::vector<std::vector<double>>& i);
void operator()(const aggregate_of_aggregate_of_instance::ptr& i) {
data_ << "(";
for (aggregate_of_aggregate_of_instance::outer_it outer_it = i->begin(); outer_it != i->end(); ++outer_it) {
if (outer_it != i->begin()) {
data_ << ",";
}
data_ << "(";
for (aggregate_of_aggregate_of_instance::inner_it inner_it = outer_it->begin(); inner_it != outer_it->end(); ++inner_it) {
if (inner_it != outer_it->begin()) {
data_ << ",";
}
(*this)(*inner_it);
}
data_ << ")";
}
data_ << ")";
}
void operator()(const IfcWriteArgument::empty_aggregate_t&) const { data_ << "()"; }
void operator()(const IfcWriteArgument::empty_aggregate_of_aggregate_t&) const { data_ << "()"; }
operator std::string() { return data_.str(); }
};
template <>
void StringBuilderVisitor::serialize(const std::vector<std::string>& i) {
data_ << "(";
for (std::vector<std::string>::const_iterator it = i.begin(); it != i.end(); ++it) {
if (it != i.begin()) {
data_ << ",";
}
std::string encoder = IfcCharacterEncoder(*it);
data_ << encoder;
}
data_ << ")";
}
template <>
void StringBuilderVisitor::serialize(const std::vector<double>& i) {
data_ << "(";
for (std::vector<double>::const_iterator it = i.begin(); it != i.end(); ++it) {
if (it != i.begin()) {
data_ << ",";
}
data_ << format_double(*it);
}
data_ << ")";
}
template <>
void StringBuilderVisitor::serialize(const std::vector<boost::dynamic_bitset<>>& i) {
data_ << "(";
for (std::vector<boost::dynamic_bitset<>>::const_iterator it = i.begin(); it != i.end(); ++it) {
if (it != i.begin()) {
data_ << ",";
}
data_ << format_binary(*it);
}
data_ << ")";
}
void StringBuilderVisitor::operator()(const std::vector<int>& i) { serialize(i); }
void StringBuilderVisitor::operator()(const std::vector<double>& i) { serialize(i); }
void StringBuilderVisitor::operator()(const std::vector<std::string>& i) { serialize(i); }
void StringBuilderVisitor::operator()(const std::vector<boost::dynamic_bitset<>>& i) { serialize(i); }
void StringBuilderVisitor::operator()(const std::vector<std::vector<int>>& i) {
data_ << "(";
for (std::vector<std::vector<int>>::const_iterator it = i.begin(); it != i.end(); ++it) {
if (it != i.begin()) {
data_ << ",";
}
serialize(*it);
}
data_ << ")";
}
void StringBuilderVisitor::operator()(const std::vector<std::vector<double>>& i) {
data_ << "(";
for (std::vector<std::vector<double>>::const_iterator it = i.begin(); it != i.end(); ++it) {
if (it != i.begin()) {
data_ << ",";
}
serialize(*it);
}
data_ << ")";
}
IfcWriteArgument::operator int() const { return as<int>(); }
IfcWriteArgument::operator bool() const { return as<bool>(); }
IfcWriteArgument::operator boost::logic::tribool() const { return as<boost::logic::tribool>(); }
IfcWriteArgument::operator double() const { return as<double>(); }
IfcWriteArgument::operator std::string() const {
if (type() == IfcUtil::Argument_ENUMERATION) {
return as<EnumerationReference>().enumeration_value;
}
return as<std::string>();
}
IfcWriteArgument::operator IfcUtil::IfcBaseClass*() const { return as<IfcUtil::IfcBaseClass*>(); }
IfcWriteArgument::operator boost::dynamic_bitset<>() const { return as<boost::dynamic_bitset<>>(); }
IfcWriteArgument::operator std::vector<double>() const { return as<std::vector<double>>(); }
IfcWriteArgument::operator std::vector<int>() const { return as<std::vector<int>>(); }
IfcWriteArgument::operator std::vector<std::string>() const { return as<std::vector<std::string>>(); }
IfcWriteArgument::operator std::vector<boost::dynamic_bitset<>>() const { return as<std::vector<boost::dynamic_bitset<>>>(); }
IfcWriteArgument::operator aggregate_of_instance::ptr() const { return as<aggregate_of_instance::ptr>(); }
IfcWriteArgument::operator std::vector<std::vector<int>>() const { return as<std::vector<std::vector<int>>>(); }
IfcWriteArgument::operator std::vector<std::vector<double>>() const { return as<std::vector<std::vector<double>>>(); }
IfcWriteArgument::operator aggregate_of_aggregate_of_instance::ptr() const { return as<aggregate_of_aggregate_of_instance::ptr>(); }
bool IfcWriteArgument::isNull() const { return type() == IfcUtil::Argument_NULL; }
Argument* IfcWriteArgument::operator[](unsigned int /*i*/) const { throw IfcParse::IfcException("Invalid cast"); }
std::string IfcWriteArgument::toString(bool upper) const {
std::ostringstream str;
str.imbue(std::locale::classic());
StringBuilderVisitor visitor(str, upper);
container_.apply_visitor(visitor);
return visitor;
}
unsigned int IfcWriteArgument::size() const {
SizeVisitor visitor;
const int size = container_.apply_visitor(visitor);
if (size == -1) {
throw IfcParse::IfcException("Invalid cast");
}
return size;
}
IfcUtil::ArgumentType IfcWriteArgument::type() const {
return static_cast<IfcUtil::ArgumentType>(container_.which());
}
// Overload to detect null values
void IfcWriteArgument::set(const aggregate_of_instance::ptr& value) {
if (value) {
container_ = value;
} else {
container_ = boost::blank();
}
}
// Overload to detect null values
void IfcWriteArgument::set(const aggregate_of_aggregate_of_instance::ptr& value) {
if (value) {
container_ = value;
} else {
container_ = boost::blank();
}
}
// Overload to detect null values
void IfcWriteArgument::set(IfcUtil::IfcBaseInterface* const& value) {
if (value != nullptr) {
container_ = value->as<IfcUtil::IfcBaseClass>();
} else {
container_ = boost::blank();
}
}
// Overloads to raise exceptions on non-finite values
void IfcWriteArgument::set(const double& v) {
if (!std::isfinite(v)) {
throw IfcParse::IfcException("Only finite values are allowed");
}
container_ = v;
}
void IfcWriteArgument::set(const std::vector<double>& v) {
if (std::any_of(v.begin(), v.end(), [](double v) {return !std::isfinite(v); })) {
throw IfcParse::IfcException("Only finite values are allowed");
}
container_ = v;
}
void IfcWriteArgument::set(const std::vector< std::vector<double> >& v) {
if (std::any_of(v.begin(), v.end(), [](const std::vector<double>& vs) {
return std::any_of(vs.begin(), vs.end(), [](double v) {return !std::isfinite(v); });
})) {
throw IfcParse::IfcException("Only finite values are allowed");
}
container_ = v;
}
-145
View File
@@ -28,149 +28,4 @@
#ifndef IFCWRITE_H
#define IFCWRITE_H
#include "aggregate_of_instance.h"
#include "ifc_parse_api.h"
#include "IfcBaseClass.h"
#include <boost/dynamic_bitset.hpp>
#include <boost/optional.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/variant.hpp>
namespace IfcWrite {
/// This class is a writable container for attributes. A fundamental
/// difference with the attribute types counterparts defined in the
/// IfcParse namespace is that this class has a Boost.Variant member
/// for storing its value, whereas the IfcParse classes only contain
/// lazy references to byte offsets in the IFC-SPF file.
class IFC_PARSE_API IfcWriteArgument : public Argument {
public:
class EnumerationReference {
public:
int data;
const char* enumeration_value;
EnumerationReference(int data, const char* enumeration_value)
: data(data),
enumeration_value(enumeration_value) {}
};
class Derived {};
class empty_aggregate_t {};
class empty_aggregate_of_aggregate_t {};
private:
boost::variant<
// A null argument, it will always serialize to $
boost::blank,
// A derived argument, it will always serialize to *
Derived,
// An integer argument, e.g. 123
// SCALARS:
int,
// A boolean argument, it will serialize to either .T. or .F.
bool,
// A logical argument, it will serialize to either .T. or .F. or .U.
boost::logic::tribool,
// A floating point argument, e.g. 12.3
double,
// A character string argument, e.g. 'IfcOpenShell'
std::string,
// A binary argument, e.g. "092A" -> 100100101010
boost::dynamic_bitset<>,
// An enumeration argument, e.g. .USERDEFINED.
// To initialize the argument a string representation
// has to be explicitly passed of the enumeration value
// which is stored internally as an integer. The argument
// itself does not keep track of what schema enumeration
// type is represented.
EnumerationReference,
// An entity instance argument. It will either serialize to
// e.g. #123 or datatype identifier for simple types, e.g.
// IFCREAL(12.3)
IfcUtil::IfcBaseClass*,
// AGGREGATES:
empty_aggregate_t,
// An aggregate of integers, e.g. (1,2,3)
std::vector<int>,
// An aggregate of floats, e.g. (12.3,4.)
std::vector<double>,
// An aggregate of strings, e.g. ('Ifc','Open','Shell')
std::vector<std::string>,
// An aggregate of binaries, e.g. ("23B", "092A") -> (111011, 100100101010)
std::vector<boost::dynamic_bitset<>>,
// An aggregate of entity instances. It will either serialize to
// e.g. (#1,#2,#3) or datatype identifier for simple types,
// e.g. (IFCREAL(1.2),IFCINTEGER(3.))
aggregate_of_instance::ptr,
// AGGREGATES OF AGGREGATES:
empty_aggregate_of_aggregate_t,
// An aggregate of an aggregate of ints. E.g. ((1, 2), (3))
std::vector<std::vector<int>>,
// An aggregate of an aggregate of floats. E.g. ((1., 2.3), (4.))
std::vector<std::vector<double>>,
// An aggregate of an aggregate of entities. E.g. ((#1, #2), (#3))
aggregate_of_aggregate_of_instance::ptr>
container_;
public:
template <typename T>
const T& as() const {
if (const T* val = boost::get<T>(&container_)) {
return *val;
}
throw IfcParse::IfcException("Invalid cast");
}
template <typename T>
typename boost::disable_if<boost::is_base_of<IfcUtil::IfcBaseInterface, typename boost::remove_pointer<T>::type>, void>::type
set(const T& type) {
container_ = type;
}
// Overload to detect null values
void set(const aggregate_of_instance::ptr& value);
// Overload to detect null values
void set(const aggregate_of_aggregate_of_instance::ptr& value);
// Overload to detect null values
void set(IfcUtil::IfcBaseInterface*const & v);
// Overloads to raise exceptions on non-finite values
void set(const double& v);
void set(const std::vector<double>& v);
void set(const std::vector< std::vector<double> >& v);
operator int() const;
operator bool() const;
operator boost::logic::tribool() const;
operator double() const;
operator std::string() const;
operator boost::dynamic_bitset<>() const;
operator IfcUtil::IfcBaseClass*() const;
operator std::vector<int>() const;
operator std::vector<double>() const;
operator std::vector<std::string>() const;
operator std::vector<boost::dynamic_bitset<>>() const;
operator aggregate_of_instance::ptr() const;
operator std::vector<std::vector<int>>() const;
operator std::vector<std::vector<double>>() const;
operator aggregate_of_aggregate_of_instance::ptr() const;
bool isNull() const;
Argument* operator[](unsigned int index) const;
std::string toString(bool upper = false) const;
unsigned int size() const;
IfcUtil::ArgumentType type() const;
};
} // namespace IfcWrite
#endif
+15 -24
View File
@@ -20,11 +20,19 @@
#ifndef IFCENTITYLIST_H
#define IFCENTITYLIST_H
#include "IfcBaseClass.h"
// #include "IfcBaseClass.h"
#include "ifc_parse_api.h"
#include <boost/shared_ptr.hpp>
#include <set>
namespace IfcParse {
class declaration;
}
namespace IfcUtil {
class IfcBaseClass;
}
template <class T>
class aggregate_of;
@@ -42,16 +50,10 @@ class IFC_PARSE_API aggregate_of_instance {
unsigned int size() const;
void reserve(unsigned capacity);
bool contains(IfcUtil::IfcBaseClass*) const;
template <class U>
typename U::list::ptr as() {
typename U::list::ptr result(new typename U::list);
for (it i = begin(); i != end(); ++i) {
if ((*i)->as<U>()) {
result->push((*i)->as<U>());
}
}
return result;
}
typename U::list::ptr as();
void remove(IfcUtil::IfcBaseClass*);
aggregate_of_instance::ptr filtered(const std::set<const IfcParse::declaration*>& entities);
aggregate_of_instance::ptr unique();
@@ -146,21 +148,10 @@ class IFC_PARSE_API aggregate_of_aggregate_of_instance {
}
return false;
}
template <class U>
typename aggregate_of_aggregate_of<U>::ptr as() {
typename aggregate_of_aggregate_of<U>::ptr result(new aggregate_of_aggregate_of<U>);
for (outer_it outer = begin(); outer != end(); ++outer) {
const std::vector<IfcUtil::IfcBaseClass*>& from = *outer;
typename std::vector<U*> to;
for (inner_it inner = from.begin(); inner != from.end(); ++inner) {
if ((*inner)->as<U>()) {
to.push_back((*inner)->as<U>());
}
}
result->push(to);
}
return result;
}
typename aggregate_of_aggregate_of<U>::ptr as();
};
template <class T>
+101 -74
View File
@@ -27,8 +27,35 @@
#include <boost/algorithm/string.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/any.hpp>
#include <libxml/parser.h>
namespace {
// Base case: when there are no more types left to check.
template <typename Fn>
void visit_any_impl(Fn& fn, const boost::any& a) {
}
// Recursive case: Check the first type in the pack.
template <typename Fn, typename T, typename... Types>
void visit_any_impl(Fn& fn, const boost::any& a) {
if (a.type() == typeid(T)) {
Fn(boost::any_cast<T>(a));
} else {
visit_any_impl<Types...>(a);
}
}
// Helper to prepend a type to a tuple
template <typename Fn, typename U>
void visit_any(Fn fn, const boost::any& a);
template <typename Fn, typename... Types>
void visit_any(Fn fn, const boost::any & a) {
visit_any_impl<Fn, Types...>(fn, a);
};
}
// For debug printing on release builds
// #undef NDEBUG
@@ -71,7 +98,8 @@ class stack_node {
node_header_entry
};
std::vector<Argument*> aggregate_elements;
// to be coerced into the correct type later on
std::vector<boost::any> aggregate_elements;
protected:
node_type type_;
@@ -90,11 +118,11 @@ class stack_node {
aggregate_elem_type_(nullptr) {}
public:
static stack_node instance(const std::string& id_in_file, IfcUtil::IfcBaseClass* inst) {
static stack_node instance(const std::string& id, IfcUtil::IfcBaseClass* inst) {
stack_node node;
node.type_ = node_instance;
node.inst_ = inst;
node.id_in_file_ = id_in_file;
node.id_in_file_ = id;
return node;
}
@@ -157,7 +185,7 @@ class stack_node {
int idx() const { return idx_; }
const IfcParse::inverse_attribute* inv_attr() const { return inv_; }
const std::string& tagname() const { return tagname_; }
const std::string& id_in_file() const { return id_in_file_; }
const std::string& id() const { return id_in_file_; }
const IfcParse::parameter_type* aggregate_elem_type() const { return aggregate_elem_type_; }
std::string repr() const {
@@ -181,7 +209,7 @@ struct ifcxml_parse_state {
IfcParse::IfcFile* file;
std::vector<stack_node> stack;
std::map<std::string, int> idmap;
std::vector<std::pair<IfcWrite::IfcWriteArgument*, std::string>> forward_references;
std::vector<std::tuple<IfcUtil::IfcBaseEntity*, size_t, std::string>> forward_references;
ifcxml_dialect dialect;
};
@@ -199,13 +227,12 @@ std::vector<T> split(const std::string& value) {
return r;
}
Argument* parse_attribute_value(const IfcParse::parameter_type* ty, const std::string& value) {
auto* v = new IfcWrite::IfcWriteArgument();
boost::any parse_attribute_value(const IfcParse::parameter_type* ty, const std::string& value) {
boost::any any;
auto cpp_type = IfcUtil::from_parameter_type(ty);
if (cpp_type == IfcUtil::Argument_STRING) {
v->set(value);
any = value;
} else if (cpp_type == IfcUtil::Argument_ENUMERATION) {
const auto* enum_type = ty->as_named_type()->declared_type()->as_enumeration_type();
@@ -214,28 +241,24 @@ Argument* parse_attribute_value(const IfcParse::parameter_type* ty, const std::s
enum_type->enumeration_items().end(),
boost::to_upper_copy(value));
if (iter != enum_type->enumeration_items().end()) {
v->set(IfcWrite::IfcWriteArgument::EnumerationReference(iter - enum_type->enumeration_items().begin(), iter->c_str()));
}
any = EnumerationReference(enum_type, std::distance(enum_type->enumeration_items().begin(), iter));
} else if (cpp_type == IfcUtil::Argument_INT) {
v->set(boost::lexical_cast<int>(value));
any = boost::lexical_cast<int>(value);
} else if (cpp_type == IfcUtil::Argument_DOUBLE) {
v->set(boost::lexical_cast<double>(value));
any = boost::lexical_cast<double>(value);
} else if (cpp_type == IfcUtil::Argument_BOOL) {
v->set(boost::to_lower_copy(value) == "true");
any = boost::to_lower_copy(value) == "true";
} else if (cpp_type == IfcUtil::Argument_AGGREGATE_OF_INT) {
v->set(split<int>(value));
any = split<int>(value);
} else if (cpp_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) {
v->set(split<double>(value));
any = split<double>(value);
}
if (v->isNull()) {
if (any.empty()) {
Logger::Error("Attribute '" + value + "' not successfully parsed");
delete v;
v = nullptr;
}
return v;
return any;
}
static void end_element(void* user, const xmlChar* tag) {
@@ -248,17 +271,20 @@ static void end_element(void* user, const xmlChar* tag) {
if (!state->stack.empty() && state->stack.back().ntype() == stack_node::node_aggregate) {
const auto& back = state->stack.back();
auto& elems = state->stack.back().aggregate_elements;
/*
auto* list = new IfcParse::ArgumentList(elems.size());
size_t i = 0;
for (auto& elem : elems) {
list->arguments()[i++] = elem;
}
back.inst()->data().attributes()[back.idx()] = list;
*/
// @todo
// back.inst()->data().storage_.set(back.idx(), elems);
}
if (state->dialect == ifcxml_dialect_ifc2x3 && state->stack.back().ntype() == stack_node::node_instance) {
if (state->stack.back().inst() != nullptr) {
state->idmap[state->stack.back().id_in_file()] = 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()->set_attribute_value(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;
}
@@ -414,32 +442,30 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
// XML identifiers need to start with a alphabetic character). This convention
// is not always followed, so a mapping is kept from XML string attribute to
// numeric index into the IfcParse::IfcFile.
std::string id_in_file;
std::string id;
// Create an attribute value from an instance. Potentially NULL in case it is a
// forward reference to an instance not yet encountered.
auto instance_to_attribute = [&state](const boost::variant<std::string, IfcUtil::IfcBaseClass*>& inst_or_ref, Argument*& attr, IfcUtil::IfcBaseClass*& inst) {
IfcWrite::IfcWriteArgument* wattr = new IfcWrite::IfcWriteArgument;
attr = wattr;
auto instance_to_attribute = [&state](const boost::variant<std::string, IfcUtil::IfcBaseClass*>& inst_or_ref, size_t attribute_index, IfcUtil::IfcBaseClass*& inst) {
if (inst_or_ref.which() == 0) {
inst = nullptr;
// This attribute is NULL initially and after parsing the complete
// file populated in a subsequent step.
state->forward_references.push_back(std::make_pair((IfcWrite::IfcWriteArgument*)attr, boost::get<std::string>(inst_or_ref)));
state->forward_references.push_back(std::make_tuple(inst->as<IfcUtil::IfcBaseEntity>(), attribute_index, boost::get<std::string>(inst_or_ref)));
} else {
inst = boost::get<IfcUtil::IfcBaseClass*>(inst_or_ref);
wattr->set(inst);
inst->set_attribute_value(attribute_index, inst);
}
};
// Create or reference an instance from the file and set attributes based on XML attributes.
auto create_instance = [&state, &attributes, &id_in_file](const IfcParse::declaration* decl) {
auto create_instance = [&state, &attributes](const IfcParse::declaration* decl) {
boost::optional<std::string> id;
boost::variant<std::string, IfcUtil::IfcBaseClass*> rv;
for (auto& pair : attributes) {
if (pair.first == "id" || pair.first == "href" || pair.first == "ref") {
id = id_in_file = pair.second;
id = id = pair.second;
if (pair.first == "href" || pair.first == "ref") {
if (state->idmap.find(pair.second) == state->idmap.end()) {
rv = pair.second;
@@ -453,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() != nullptr ? decl->as_entity()->attribute_count() : 1));
const IfcParse::entity* entity = decl->as_entity();
if (entity != nullptr) {
@@ -465,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.storage_.set(idx, v);
}, val);
}
} else {
Logger::Error("Unknown attribute '" + pair.first + "' on entity '" + entity->name() + "' with value '" + pair.second + "'");
@@ -475,14 +503,14 @@ 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, std::move(untyped));
if (state->dialect == ifcxml_dialect_ifc4) {
// In IFC2X3 not added directly because attrs such as GlobalId are in
// subsequent child nodes
newinst = state->file->addEntity(newinst);
if (id) {
state->idmap[*id] = newinst->data().id();
state->idmap[*id] = newinst->id();
}
}
@@ -499,12 +527,12 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
if (state_type == stack_node::node_select) {
const IfcParse::declaration* decl = state->file->schema()->declaration_by_name(tagname_copy);
Argument* attr;
// Argument* attr;
IfcUtil::IfcBaseClass* inst;
auto inst_ = create_instance(decl);
instance_to_attribute(inst_, attr, inst);
state->stack.back().inst()->data().setArgument(state->stack.back().idx(), attr);
state->stack.push_back(stack_node::instance(id_in_file, inst));
instance_to_attribute(inst_, state->stack.back().idx(), inst);
// state->stack.back().inst()->data().storage_.set(state->stack.back().idx(), attr);
state->stack.push_back(stack_node::instance(id, inst));
} else if (state_type == stack_node::node_aggregate) {
const IfcParse::parameter_type* attribute_type = state->stack.back().inst()->declaration().as_entity()->attribute_by_index(state->stack.back().idx())->type_of_attribute();
@@ -533,10 +561,11 @@ 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);
state->stack.push_back(stack_node::instance(id_in_file, inst));
// 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));
}
}
} else if (state_type == stack_node::node_instance) {
@@ -559,15 +588,12 @@ 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);
state->stack.push_back(stack_node::instance(id_in_file, inst));
inst->data().storage_.set(idx, state->stack.back().inst());
state->stack.push_back(stack_node::instance(id, inst));
} else {
Logger::Error("Unknown attribute " + tagname);
state->stack.push_back(state->stack.back());
@@ -589,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_in_file, newinst));
IfcUtil::IfcBaseClass* inst;
instance_to_attribute(inst_or_reference, idx, inst);
// @todo
state->stack.back().inst();
state->stack.push_back(stack_node::instance(id, boost::get<IfcUtil::IfcBaseClass*>(inst_or_reference)));
} else if (attribute_type->as_named_type()->declared_type()->as_select_type() != nullptr) {
// Select types cause an additional indirection, so the current stack node is simply repeated
state->stack.push_back(stack_node::select(state->stack.back().inst(), idx));
@@ -631,28 +657,25 @@ 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) {
// Type declaration, immediately populate attr 0
state->stack.push_back(stack_node::instance_attribute(inst, 0));
} else {
state->stack.push_back(stack_node::instance(id_in_file, inst));
state->stack.push_back(stack_node::instance(id, inst));
}
}
}
@@ -667,6 +690,8 @@ end:
#ifdef WITH_IFCXML
IFC_PARSE_API IfcParse::IfcFile* IfcParse::parse_ifcxml(const std::string& filename) {
throw std::runtime_error("IFC-XML import temporarily disabled");
ifcxml_parse_state state;
state.file = nullptr;
state.dialect = ifcxml_dialect_unknown;
@@ -680,16 +705,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();
}
+320
View File
@@ -0,0 +1,320 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/*
A dynamic sequence of variant types arranged in a way to reduce size impact due
to alignment by grouping the 1 byte type indices. Using heap allocation - hence
storing a pointer instead - for larger types so that the overall size of the
variant - which is the maximum size of its constituents - is reduced.
*/
#ifndef VARIANTARRAY_H
#define VARIANTARRAY_H
#include <iostream>
#include <stdexcept>
#include <type_traits>
#include <utility>
#include <memory>
#include <tuple>
#include "IfcException.h"
namespace impl {
// Trait to detect unique_ptr
template <typename...> struct is_unique_ptr : std::false_type {};
template<class T, typename... Args>
struct is_unique_ptr<std::unique_ptr<T, Args...>> : std::true_type {};
/*
// Trait to find index of type in parameter pack
template <typename T, typename... Ts>
struct TypeIndex;
template <typename T, typename... Ts>
struct TypeIndex<T, T, Ts...> : std::integral_constant<std::size_t, 0> {};
template <typename T, typename U, typename... Ts>
struct TypeIndex<T, U, Ts...> : std::integral_constant<std::size_t, 1 + TypeIndex<T, Ts...>::value> {};
template <typename T, typename... Ts>
constexpr std::size_t TypeIndex_v = TypeIndex<T, Ts...>::value;
*/
// Trait to find index of type in parameter pack considering inheritance
template <typename T, typename... Ts>
struct TypeIndex;
// Base case: When the first type in the pack is the type we're looking for, or is a base class of it
template <typename T, typename U, typename... Ts>
struct TypeIndex<T, U, Ts...>
: std::integral_constant<std::size_t, (std::is_pointer_v<T> ? std::is_base_of_v<std::remove_pointer_t<U>, std::remove_pointer_t<T>> : std::is_same_v<T, U>) ? 0 :
(TypeIndex<T, Ts...>::value == std::numeric_limits<std::size_t>::max()
? std::numeric_limits<std::size_t>::max()
: 1 + TypeIndex<T, Ts...>::value)> {};
// Recursion termination: When the parameter pack is empty
template <typename T>
struct TypeIndex<T> : std::integral_constant<std::size_t, std::numeric_limits<std::size_t>::max()> {};
// Helper variable template
template <typename T, typename... Ts>
constexpr std::size_t TypeIndex_v = TypeIndex<T, Ts...>::value;
// Trait to determine if a type is small enough to be stored directly
template <typename T>
struct is_small_object {
static constexpr bool value = sizeof(T) <= sizeof(void*) * 2;
};
// Metafunction to transform T to unique_ptr<T> based on size
template <typename T>
struct TransformType {
using type = typename std::conditional<
is_small_object<T>::value,
T,
std::unique_ptr<T>
>::type;
};
// Helper to prepend a type to a tuple
template <typename T, typename Tuple>
struct TuplePrepend;
template <typename T, typename... Types>
struct TuplePrepend<T, std::tuple<Types...>> {
using type = std::tuple<T, Types...>;
};
// Map types based on above size transform
template <typename... Types>
struct MapTypes;
template <typename FirstType, typename... RestTypes>
struct MapTypes<FirstType, RestTypes...> {
using type = typename TuplePrepend<
typename TransformType<FirstType>::type,
typename MapTypes<RestTypes...>::type
>::type;
};
template <>
struct MapTypes<> {
using type = std::tuple<>;
};
template <typename... Types>
using MapTypes_t = typename MapTypes<Types...>::type;
// Create aligned_union from paramater pack stored in tuple for storage in variant
template <typename T>
struct make_union_from_tuple {};
template <typename... Args>
struct make_union_from_tuple<std::tuple<Args...>> {
using type = typename std::aligned_union<0, Args...>::type;
};
}
template<typename... Types>
class VariantArray {
public:
using TypesTuple = impl::MapTypes_t<Types...>;
VariantArray(size_t size)
: size_and_indices_(new uint8_t[size + 1])
, storage_(size ? new StorageType[size] : nullptr)
{
if (size) {
size_and_indices_[0] = (uint8_t) size;
memset(size_and_indices_ + 1, 0, sizeof(uint8_t) * size);
for (size_t i = 0; i < size; ++i) {
// type 0 needs to be default constructable
set(i, typename std::tuple_element<0, std::tuple<Types...>>::type{});
}
}
}
VariantArray(VariantArray&& other) noexcept
: size_and_indices_(other.size_and_indices_)
, storage_(other.storage_)
{
other.size_and_indices_ = nullptr;
other.storage_ = nullptr;
}
VariantArray& operator=(VariantArray&& other) noexcept {
if (this != &other) {
free_();
size_and_indices_ = other.size_and_indices_;
storage_ = other.storage_;
other.size_and_indices_ = nullptr;
other.storage_ = nullptr;
}
return *this;
}
VariantArray(const VariantArray&) = delete;
VariantArray(const VariantArray&&) = delete;
VariantArray& operator= (const VariantArray&) = delete;
template<typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, VariantArray>>>
void set(std::size_t index, T&& value) {
using U = std::decay_t<T>;
static_assert(impl::TypeIndex_v<U, Types...> < sizeof...(Types), "Type not supported by variant");
if (index >= size_and_indices_[0]) {
throw std::out_of_range("Index out of range");
}
destroy_at_index(index);
size_and_indices_[index + 1] = impl::TypeIndex_v<U, Types...>;
using V = typename std::tuple_element<impl::TypeIndex_v<U, Types...>, impl::MapTypes_t<Types... >>::type;
// std::wcout << "setting " << index << " to " << typeid(V).name() << " (" << impl::TypeIndex_v<U, Types...> << ")" << std::endl;
if constexpr (impl::is_unique_ptr<V>::value) {
new(&storage_[index]) V(new U(value));
} else {
new(&storage_[index]) U(std::forward<T>(value));
}
}
~VariantArray() {
free_();
}
std::size_t index(std::size_t index) const noexcept {
return size_and_indices_[index + 1];
}
template<typename T>
T& get(std::size_t index) {
if (!has<T>(index)) {
throw std::bad_cast();
}
using V = typename std::tuple_element<impl::TypeIndex_v<T, Types...>, impl::MapTypes_t<Types... >>::type;
if constexpr (impl::is_unique_ptr<V>::value) {
return **reinterpret_cast<V*>(&storage_[index]);
} else {
return *reinterpret_cast<V*>(&storage_[index]);
}
}
template<typename T>
bool has(std::size_t index) const {
return size_and_indices_[index + 1] == impl::TypeIndex<T, Types...>::value;
}
template<typename T>
const T& get(std::size_t index) const {
if (size_and_indices_[index + 1] != impl::TypeIndex<T, Types...>::value) {
// @todo this IfcException is silly. Figure out what
// to do, but at the moment it is specifically caught
// in various places.
throw IfcParse::IfcException(
"Type held at index " + std::to_string(index) + " is " +
get_type_name(size_and_indices_[index + 1]) + " and not " + typeid(T).name()
);
}
using V = typename std::tuple_element<impl::TypeIndex_v<T, Types...>, impl::MapTypes_t<Types... >>::type;
if constexpr (impl::is_unique_ptr<V>::value) {
return **reinterpret_cast<const V*>(&storage_[index]);
} else {
return *reinterpret_cast<const V*>(&storage_[index]);
}
}
template<typename Visitor>
auto apply_visitor(Visitor&& visitor, std::size_t index) const {
return apply_visitor_impl(std::forward<Visitor>(visitor), index, std::integral_constant<std::size_t, sizeof...(Types)>{});
}
auto size() const {
return size_and_indices_ ? size_and_indices_[0] : 0;
}
private:
using StorageType = typename impl::make_union_from_tuple<impl::MapTypes_t<Types...>>::type;
uint8_t* size_and_indices_;
StorageType* storage_;
void destroy_at_index(std::size_t index) {
destroy_type_at_index(index, std::integral_constant<std::size_t, sizeof...(Types)>{});
}
void free_() {
if (size_and_indices_) {
for (std::size_t i = 0; i < size_and_indices_[0]; ++i) {
destroy_at_index(i);
}
delete[] size_and_indices_;
delete[] storage_;
}
}
template<std::size_t Index>
void destroy_type_at_index(std::size_t index, std::integral_constant<std::size_t, Index>) {
if (size_and_indices_[index + 1] == Index - 1) {
using T = typename std::tuple_element_t<Index - 1, impl::MapTypes_t<Types...>>;
if constexpr (!std::is_trivially_destructible<T>::value) {
reinterpret_cast<T*>(&storage_[index])->~T();
}
size_and_indices_[index + 1] = sizeof...(Types);
} else {
destroy_type_at_index(index, std::integral_constant<std::size_t, Index - 1>{});
}
}
void destroy_type_at_index(std::size_t, std::integral_constant<std::size_t, 0>) {}
template<typename Visitor, std::size_t Index>
auto apply_visitor_impl(Visitor&& visitor, std::size_t idx, std::integral_constant<std::size_t, Index>) const {
if (size_and_indices_[idx + 1] == Index - 1) {
using T = typename std::tuple_element_t<Index - 1, impl::MapTypes_t<Types...>>;
if constexpr (impl::is_unique_ptr<T>::value) {
return visitor(**reinterpret_cast<T*>(&storage_[idx]));
} else {
return visitor(*reinterpret_cast<T*>(&storage_[idx]));
}
}
return apply_visitor_impl(std::forward<Visitor>(visitor), idx, std::integral_constant<std::size_t, Index - 1>{});
}
template<typename Visitor>
auto apply_visitor_impl(Visitor&&, std::size_t, std::integral_constant<std::size_t, 0>) const {
throw std::runtime_error("Invalid variant index");
if constexpr (!std::is_void_v<decltype(std::declval<Visitor>()(std::declval<typename std::tuple_element_t<0, impl::MapTypes_t<Types...>> &>()))>) {
return decltype(std::declval<Visitor>()(std::declval<typename std::tuple_element_t<0, impl::MapTypes_t<Types...>> &>())){};
}
}
template <size_t I>
const char* get_type_name_impl(size_t i) const {
if constexpr (I == 0) {
return "";
} else {
if (i == I - 1) {
return typeid(std::tuple_element_t<I - 1, std::tuple<Types...>>).name();
} else {
return get_type_name_impl<I - 1>(i);
}
}
}
const char* get_type_name(size_t i) const {
return get_type_name_impl<sizeof...(Types)>(i);
}
};
#endif
+4 -4
View File
@@ -219,7 +219,7 @@ std::string taxonomy_item_repr(ifcopenshell::geometry::taxonomy::item::ptr i) {
if ((ent = self->instance->as<IfcUtil::IfcBaseEntity>()) == nullptr) {
return 0;
}
return ent->data().id();
return ent->id();
}
}
@@ -741,7 +741,7 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
template <typename Schema>
static boost::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> helper_fn_create_shape(const std::string& geometry_library, ifcopenshell::geometry::Settings& settings, IfcUtil::IfcBaseClass* instance, IfcUtil::IfcBaseClass* representation = 0) {
IfcParse::IfcFile* file = instance->data().file;
IfcParse::IfcFile* file = instance->file_;
ifcopenshell::geometry::Converter kernel(geometry_library, file, settings);
@@ -854,7 +854,7 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
throw IfcParse::IfcException("Failed to process shape");
}
IfcGeom::Representation::BRep brep(settings, instance->declaration().name(), to_locale_invariant_string(instance->data().id()), shapes);
IfcGeom::Representation::BRep brep(settings, instance->declaration().name(), to_locale_invariant_string(instance->as<IfcUtil::IfcBaseEntity>()->id()), shapes);
try {
if (settings.get<ifcopenshell::geometry::settings::IteratorOutput>().get() == ifcopenshell::geometry::settings::SERIALIZED) {
return new IfcGeom::Representation::Serialization(brep);
@@ -902,7 +902,7 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type
%inline %{
ifcopenshell::geometry::taxonomy::item::ptr map_shape(ifcopenshell::geometry::Settings& settings, IfcUtil::IfcBaseClass* instance) {
std::unique_ptr<ifcopenshell::geometry::abstract_mapping> mapping(ifcopenshell::geometry::impl::mapping_implementations().construct(instance->data().file, settings));
std::unique_ptr<ifcopenshell::geometry::abstract_mapping> mapping(ifcopenshell::geometry::impl::mapping_implementations().construct(instance->file_, settings));
return mapping->map(instance);
}
%}
+90 -185
View File
@@ -30,6 +30,8 @@ private:
%ignore IfcParse::IfcFile::begin;
%ignore IfcParse::IfcFile::end;
%ignore parse_context;
%ignore operator<<;
%ignore IfcParse::FileDescription::FileDescription;
@@ -54,6 +56,24 @@ private:
%rename("add") addEntity;
%rename("remove") removeEntity;
%{
template<typename T>
struct is_std_vector : std::false_type {};
template<typename T, typename Alloc>
struct is_std_vector<std::vector<T, Alloc>> : std::true_type {};
template<typename T>
constexpr bool is_std_vector_v = is_std_vector<T>::value;
template<typename T>
struct is_std_vector_vector : std::false_type {};
template<typename T, typename Alloc, typename Alloc2>
struct is_std_vector_vector<std::vector<std::vector<T, Alloc>, Alloc2>> : std::true_type {};
template<typename T>
constexpr bool is_std_vector_vector_v = is_std_vector_vector<T>::value;
%}
class attribute_value_derived {};
%{
class attribute_value_derived {};
@@ -127,15 +147,15 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
}
aggregate_of_instance::ptr get_inverse(IfcUtil::IfcBaseClass* e) {
return $self->getInverse(e->data().id(), 0, -1);
return $self->getInverse(e->as<IfcUtil::IfcBaseEntity>()->id(), 0, -1);
}
std::vector<int> get_inverse_indices(IfcUtil::IfcBaseClass* e) {
return $self->get_inverse_indices(e->data().id());
return $self->get_inverse_indices(e->as<IfcUtil::IfcBaseEntity>()->id());
}
int get_total_inverses(IfcUtil::IfcBaseClass* e) {
return $self->getTotalInverses(e->data().id());
return $self->getTotalInverses(e->as<IfcUtil::IfcBaseEntity>()->id());
}
void write(const std::string& fn) {
@@ -166,6 +186,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
return ts;
}
/*
std::vector<std::string> types_with_super() const {
const size_t n = std::distance($self->types_incl_super_begin(), $self->types_incl_super_end());
std::vector<std::string> ts;
@@ -173,6 +194,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
std::transform($self->types_incl_super_begin(), $self->types_incl_super_end(), std::back_inserter(ts), helper_fn_declaration_get_name);
return ts;
}
*/
std::string schema_name() const {
if ($self->schema() == 0) return "";
@@ -220,7 +242,9 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
// to expose it to the Python wrapper it is simply duplicated here.
// Same applies to the two methods reimplemented below.
int id() const {
return $self->data().id();
return $self->as<IfcUtil::IfcBaseEntity>() != nullptr
? $self->as<IfcUtil::IfcBaseEntity>()->id()
: 0;
}
int __len__() const {
@@ -279,13 +303,16 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
return t;
}
std::pair<IfcUtil::ArgumentType,Argument*> get_argument(unsigned i) {
return std::pair<IfcUtil::ArgumentType,Argument*>($self->data().getArgument(i)->type(), $self->data().getArgument(i));
AttributeValue get_argument(unsigned i) {
return $self->data().get_attribute_value(i);
}
std::pair<IfcUtil::ArgumentType,Argument*> get_argument(const std::string& a) {
unsigned i = $self->declaration().as_entity()->attribute_index(a);
return std::pair<IfcUtil::ArgumentType,Argument*>($self->data().getArgument(i)->type(), $self->data().getArgument(i));
AttributeValue get_argument(const std::string& a) {
auto i = $self->declaration().as_entity()->attribute_index(a);
if (i == -1) {
throw std::runtime_error("Attribute '" + a + "' not found on entity named " + $self->declaration().name());
}
return $self->data().get_attribute_value((unsigned)i);
}
bool __eq__(IfcUtil::IfcBaseClass* other) const {
@@ -293,16 +320,20 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
}
std::string __repr__() const {
return $self->data().toString();
std::ostringstream oss;
$self->toString(oss);
return oss.str();
}
std::string to_string(bool valid_spf) const {
return $self->data().toString(valid_spf);
std::ostringstream oss;
$self->toString(oss, valid_spf);
return oss.str();
}
// Just something to have a somewhat sensible value to hash
size_t file_pointer() const {
return reinterpret_cast<size_t>($self->data().file);
return reinterpret_cast<size_t>($self->file_);
}
unsigned get_argument_index(const std::string& a) const {
@@ -341,7 +372,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsNull(unsigned int i) {
bool is_optional = $self->declaration().as_entity()->attribute_by_index(i)->optional();
if (is_optional) {
self->data().setArgument(i, new IfcWrite::IfcWriteArgument());
self->set_attribute_value(i, Blank{});
} else {
throw IfcParse::IfcException("Attribute not set");
}
@@ -350,13 +381,9 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsInt(unsigned int i, int v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_INT) {
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(v);
self->data().setArgument(i, arg);
self->set_attribute_value(i, v);
} else if ( (arg_type == IfcUtil::Argument_BOOL) && ( (v == 0) || (v == 1) ) ) {
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(v == 1);
self->data().setArgument(i, arg);
self->set_attribute_value(i, v);
} else {
throw IfcParse::IfcException("Attribute not set");
}
@@ -365,9 +392,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsBool(unsigned int i, bool v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_BOOL) {
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(v);
self->data().setArgument(i, arg);
self->set_attribute_value(i, v);
} else {
throw IfcParse::IfcException("Attribute not set");
}
@@ -376,9 +401,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsLogical(unsigned int i, boost::logic::tribool v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_LOGICAL) {
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(v);
self->data().setArgument(i, arg);
self->set_attribute_value(i, v);
} else {
throw IfcParse::IfcException("Attribute not set");
}
@@ -387,9 +410,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsDouble(unsigned int i, double v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_DOUBLE) {
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(v);
self->data().setArgument(i, arg);
self->set_attribute_value(i, v);
} else {
throw IfcParse::IfcException("Attribute not set");
}
@@ -398,31 +419,15 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsString(unsigned int i, const std::string& a) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_STRING) {
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(a);
self->data().setArgument(i, arg);
self->set_attribute_value(i, a);
} else if (arg_type == IfcUtil::Argument_ENUMERATION) {
const IfcParse::enumeration_type* enum_type = $self->declaration().schema()->declaration_by_name($self->declaration().type())->as_entity()->
attribute_by_index(i)->type_of_attribute()->as_named_type()->declared_type()->as_enumeration_type();
std::vector<std::string>::const_iterator it = std::find(
enum_type->enumeration_items().begin(),
enum_type->enumeration_items().end(),
a);
if (it == enum_type->enumeration_items().end()) {
throw IfcParse::IfcException(a + " does not name a valid item for " + enum_type->name());
}
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(IfcWrite::IfcWriteArgument::EnumerationReference(it - enum_type->enumeration_items().begin(), it->c_str()));
self->data().setArgument(i, arg);
self->set_attribute_value(i, EnumerationReference(enum_type, enum_type->lookup_enum_offset(a)));
} else if (arg_type == IfcUtil::Argument_BINARY) {
if (IfcUtil::valid_binary_string(a)) {
boost::dynamic_bitset<> bits(a);
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(bits);
self->data().setArgument(i, arg);
self->set_attribute_value(i, bits);
} else {
throw IfcParse::IfcException("String not a valid binary representation");
}
@@ -434,9 +439,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsAggregateOfInt(unsigned int i, const std::vector<int>& v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_INT) {
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(v);
self->data().setArgument(i, arg);
self->set_attribute_value(i, v);
} else {
throw IfcParse::IfcException("Attribute not set");
}
@@ -445,9 +448,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsAggregateOfDouble(unsigned int i, const std::vector<double>& v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) {
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(v);
self->data().setArgument(i, arg);
self->set_attribute_value(i, v);
} else {
throw IfcParse::IfcException("Attribute not set");
}
@@ -456,9 +457,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsAggregateOfString(unsigned int i, const std::vector<std::string>& v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_STRING) {
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(v);
self->data().setArgument(i, arg);
self->set_attribute_value(i, v);
} else if (arg_type == IfcUtil::Argument_AGGREGATE_OF_BINARY) {
std::vector< boost::dynamic_bitset<> > bits;
bits.reserve(v.size());
@@ -469,9 +468,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
throw IfcParse::IfcException("String not a valid binary representation");
}
}
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(bits);
self->data().setArgument(i, arg);
self->set_attribute_value(i, bits);
} else {
throw IfcParse::IfcException("Attribute not set");
}
@@ -480,9 +477,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsEntityInstance(unsigned int i, IfcUtil::IfcBaseClass* v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_ENTITY_INSTANCE) {
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(v);
self->data().setArgument(i, arg);
self->set_attribute_value(i, v);
} else {
throw IfcParse::IfcException("Attribute not set");
}
@@ -491,9 +486,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsAggregateOfEntityInstance(unsigned int i, aggregate_of_instance::ptr v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(v);
self->data().setArgument(i, arg);
self->set_attribute_value(i, v);
} else {
throw IfcParse::IfcException("Attribute not set");
}
@@ -502,9 +495,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsAggregateOfAggregateOfInt(unsigned int i, const std::vector< std::vector<int> >& v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT) {
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(v);
self->data().setArgument(i, arg);
self->set_attribute_value(i, v);
} else {
throw IfcParse::IfcException("Attribute not set");
}
@@ -513,9 +504,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsAggregateOfAggregateOfDouble(unsigned int i, const std::vector< std::vector<double> >& v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE) {
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(v);
self->data().setArgument(i, arg);
self->set_attribute_value(i, v);
} else {
throw IfcParse::IfcException("Attribute not set");
}
@@ -524,9 +513,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsAggregateOfAggregateOfEntityInstance(unsigned int i, aggregate_of_aggregate_of_instance::ptr v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) {
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(v);
self->data().setArgument(i, arg);
self->set_attribute_value(i, v);
} else {
throw IfcParse::IfcException("Attribute not set");
}
@@ -606,27 +593,8 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
IfcUtil::IfcBaseClass* new_IfcBaseClass(const std::string& schema_identifier, const std::string& name) {
const IfcParse::schema_definition* schema = IfcParse::schema_by_name(schema_identifier);
const IfcParse::declaration* decl = schema->declaration_by_name(name);
IfcEntityInstanceData* data = new IfcEntityInstanceData(decl);
for (size_t i = 0; i < data->getArgumentCount(); ++i) {
data->setArgument(i, new IfcWrite::IfcWriteArgument());
}
if (decl->as_entity()) {
const std::vector<bool>& derived = decl->as_entity()->derived();
std::vector<bool>::const_iterator it = derived.begin();
size_t index = 0;
for (; it != derived.end(); ++it, ++index) {
if (*it) {
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
arg->set(IfcWrite::IfcWriteArgument::Derived());
data->setArgument(index, arg);
}
}
}
return schema->instantiate(data);
IfcEntityInstanceData data(storage_t(decl->as_entity() ? decl->as_entity()->attribute_count() : 1));
return schema->instantiate(decl, std::move(data));
}
%}
@@ -789,92 +757,29 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
// @todo refactor this to remove duplication with the typemap.
// except this is calls the above function in case of instances.
PyObject* convert_cpp_attribute_to_python(IfcUtil::ArgumentType type, Argument& arg) {
if (!arg.isNull() && type != IfcUtil::Argument_DERIVED) {
try {
switch(type) {
case IfcUtil::Argument_INT: {
int v = arg;
return pythonize(v);
break; }
case IfcUtil::Argument_BOOL: {
bool v = arg;
return pythonize(v);
break; }
case IfcUtil::Argument_LOGICAL: {
boost::logic::tribool v = arg;
return pythonize(v);
break; }
case IfcUtil::Argument_DOUBLE: {
double v = arg;
return pythonize(v);
break; }
case IfcUtil::Argument_ENUMERATION:
case IfcUtil::Argument_STRING: {
std::string v = arg;
return pythonize(v);
break; }
case IfcUtil::Argument_BINARY: {
boost::dynamic_bitset<> v = arg;
return pythonize(v);
break; }
case IfcUtil::Argument_AGGREGATE_OF_INT: {
std::vector<int> v = arg;
PyObject* convert_cpp_attribute_to_python(AttributeValue arg) {
return arg.array_->apply_visitor([](auto& v){
using U = std::decay_t<decltype(v)>;
if constexpr (is_std_vector_vector_v<U>) {
return pythonize_vector2(v);
} else if constexpr (is_std_vector_v<U>) {
return pythonize_vector(v);
break; }
case IfcUtil::Argument_AGGREGATE_OF_DOUBLE: {
std::vector<double> v = arg;
return pythonize_vector(v);
break; }
case IfcUtil::Argument_AGGREGATE_OF_STRING: {
std::vector<std::string> v = arg;
return pythonize_vector(v);
break; }
case IfcUtil::Argument_ENTITY_INSTANCE: {
IfcUtil::IfcBaseClass* v = arg;
return get_info_cpp(v);
break; }
case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: {
aggregate_of_instance::ptr v = arg;
auto r = PyTuple_New(v->size());
for (unsigned i = 0; i < v->size(); ++i) {
PyTuple_SetItem(r, i, get_info_cpp((*v)[i]));
}
return r;
break; }
case IfcUtil::Argument_AGGREGATE_OF_BINARY: {
std::vector< boost::dynamic_bitset<> > v = arg;
return pythonize_vector(v);
break; }
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT: {
std::vector< std::vector<int> > v = arg;
return pythonize_vector2(v);
break; }
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE: {
std::vector< std::vector<double> > v = arg;
return pythonize_vector2(v);
break; }
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE: {
aggregate_of_aggregate_of_instance::ptr vs = arg;
auto rs = PyTuple_New(vs->size());
for (auto it = vs->begin(); it != vs->end(); ++it) {
aggregate_of_instance::ptr v_i = arg;
auto r = PyTuple_New(v_i->size());
for (unsigned i = 0; i < v_i->size(); ++i) {
PyTuple_SetItem(r, i, get_info_cpp((*v_i)[i]));
}
PyTuple_SetItem(rs, std::distance(vs->begin(), it), r);
}
return rs;
break; }
case IfcUtil::Argument_EMPTY_AGGREGATE: {
return PyTuple_New(0);
break; }
}
} catch(...) {}
}
Py_INCREF(Py_None);
return Py_None;
} else if constexpr (std::is_same_v<U, EnumerationReference>) {
return pythonize(std::string(v.value()));
} else if constexpr (std::is_same_v<U, Derived>) {
if (feature_use_attribute_value_derived) {
return SWIG_NewPointerObj(new attribute_value_derived, SWIGTYPE_p_attribute_value_derived, SWIG_POINTER_OWN);
} else {
Py_INCREF(Py_None);
return static_cast<PyObject*>(Py_None);
}
} else if constexpr (std::is_same_v<U, empty_aggregate_t> || std::is_same_v<U, empty_aggregate_of_aggregate_t> || std::is_same_v<U, Blank>) {
Py_INCREF(Py_None);
return static_cast<PyObject*>(Py_None);
} else {
return pythonize(v);
}
}, arg.index_);
}
%}
%inline %{
@@ -891,8 +796,8 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
auto attr_type = *dit
? IfcUtil::Argument_DERIVED
: IfcUtil::from_parameter_type((*it)->type_of_attribute());
auto value_cpp = v->data().getArgument(std::distance(attrs.begin(), it));
auto value_py = convert_cpp_attribute_to_python(attr_type, *value_cpp);
auto value_cpp = v->data().get_attribute_value(std::distance(attrs.begin(), it));
auto value_py = convert_cpp_attribute_to_python(value_cpp);
PyDict_SetItem(d, name_py, value_py);
Py_DECREF(name_py);
Py_DECREF(value_py);
@@ -900,15 +805,15 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
const std::string& id_cpp = "id";
auto id_py = pythonize(id_cpp);
auto id_v_py = pythonize(v->data().id());
auto id_v_py = pythonize(v->as<IfcUtil::IfcBaseEntity>()->id());
PyDict_SetItem(d, id_py, id_v_py);
Py_DECREF(id_py);
Py_DECREF(id_v_py);
} else {
const std::string& name_cpp = "wrappedValue";
auto name_py = pythonize(name_cpp);
auto value_cpp = v->data().getArgument(0);
auto value_py = convert_cpp_attribute_to_python(value_cpp->type(), *value_cpp);
auto value_cpp = v->data().get_attribute_value(0);
auto value_py = convert_cpp_attribute_to_python(value_cpp);
PyDict_SetItem(d, name_py, value_py);
Py_DECREF(name_py);
Py_DECREF(value_py);
+26 -85
View File
@@ -31,95 +31,36 @@
$result = SWIG_Python_str_FromChar(data_type_strings[(int)$1]);
}
%typemap(out) std::pair<IfcUtil::ArgumentType, Argument*> {
%typemap(out) AttributeValue {
// The SWIG %exception directive does not take care
// of our typemap. So the attribute conversion block
// is wrapped in a try-catch block manually.
try {
const Argument& arg = *($1.second);
const IfcUtil::ArgumentType type = $1.first;
if (arg.isNull()) {
Py_INCREF(Py_None);
$result = Py_None;
} else if (type == IfcUtil::Argument_DERIVED) {
if (feature_use_attribute_value_derived) {
$result = SWIG_NewPointerObj(new attribute_value_derived, SWIGTYPE_p_attribute_value_derived, SWIG_POINTER_OWN);
} else {
Py_INCREF(Py_None);
$result = Py_None;
}
} else {
switch(type) {
case IfcUtil::Argument_INT: {
int v = arg;
$result = pythonize(v);
break; }
case IfcUtil::Argument_BOOL: {
bool v = arg;
$result = pythonize(v);
break; }
case IfcUtil::Argument_LOGICAL: {
boost::logic::tribool v = arg;
$result = pythonize(v);
break; }
case IfcUtil::Argument_DOUBLE: {
double v = arg;
$result = pythonize(v);
break; }
case IfcUtil::Argument_ENUMERATION:
case IfcUtil::Argument_STRING: {
std::string v = arg;
$result = pythonize(v);
break; }
case IfcUtil::Argument_BINARY: {
boost::dynamic_bitset<> v = arg;
$result = pythonize(v);
break; }
case IfcUtil::Argument_AGGREGATE_OF_INT: {
std::vector<int> v = arg;
$result = pythonize_vector(v);
break; }
case IfcUtil::Argument_AGGREGATE_OF_DOUBLE: {
std::vector<double> v = arg;
$result = pythonize_vector(v);
break; }
case IfcUtil::Argument_AGGREGATE_OF_STRING: {
std::vector<std::string> v = arg;
$result = pythonize_vector(v);
break; }
case IfcUtil::Argument_ENTITY_INSTANCE: {
IfcUtil::IfcBaseClass* v = arg;
$result = pythonize(v);
break; }
case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: {
aggregate_of_instance::ptr v = arg;
$result = pythonize(v);
break; }
case IfcUtil::Argument_AGGREGATE_OF_BINARY: {
std::vector< boost::dynamic_bitset<> > v = arg;
$result = pythonize_vector(v);
break; }
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT: {
std::vector< std::vector<int> > v = arg;
$result = pythonize_vector2(v);
break; }
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE: {
std::vector< std::vector<double> > v = arg;
$result = pythonize_vector2(v);
break; }
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE: {
aggregate_of_aggregate_of_instance::ptr v = arg;
$result = pythonize(v);
break; }
case IfcUtil::Argument_EMPTY_AGGREGATE: {
$result = PyTuple_New(0);
break; }
case IfcUtil::Argument_UNKNOWN:
default:
SWIG_exception(SWIG_RuntimeError,"Unknown attribute type");
break;
}
}
$result = $1.array_->apply_visitor([](auto& v){
using U = std::decay_t<decltype(v)>;
if constexpr (is_std_vector_vector_v<U>) {
return pythonize_vector2(v);
} else if constexpr (is_std_vector_v<U>) {
return pythonize_vector(v);
} else if constexpr (std::is_same_v<U, EnumerationReference>) {
return pythonize(std::string(v.value()));
} else if constexpr (std::is_same_v<U, Derived>) {
if (feature_use_attribute_value_derived) {
return SWIG_NewPointerObj(new attribute_value_derived, SWIGTYPE_p_attribute_value_derived, SWIG_POINTER_OWN);
} else {
Py_INCREF(Py_None);
return static_cast<PyObject*>(Py_None);
}
} else if constexpr (std::is_same_v<U, empty_aggregate_t> || std::is_same_v<U, empty_aggregate_of_aggregate_t> || std::is_same_v<U, Blank>) {
Py_INCREF(Py_None);
return static_cast<PyObject*>(Py_None);
} else if constexpr (std::is_same_v<U, empty_aggregate_t> || std::is_same_v<U, empty_aggregate_of_aggregate_t> || std::is_same_v<U, Derived> || std::is_same_v<U, Blank>) {
Py_INCREF(Py_None);
return static_cast<PyObject*>(Py_None);
} else {
return pythonize(v);
}
}, $1.index_);
} catch(IfcParse::IfcException& e) {
SWIG_exception(SWIG_RuntimeError, e.what());
} catch(...) {

Some files were not shown because too many files have changed in this diff Show More