From 95a29dec7ba439b8cb41b023655e8d44b786beb5 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Tue, 8 Sep 2020 14:37:50 +0200 Subject: [PATCH] cpp changes for latebound schema manipulation from Python --- src/ifcparse/IfcBaseClass.h | 12 ++++ src/ifcparse/IfcSchema.cpp | 14 +++++ src/ifcparse/IfcSchema.h | 4 +- src/ifcwrap/utils/type_conversion.i | 2 + src/ifcwrap/utils/typemaps_in.i | 90 +++++++++++++++++++++++++++++ src/ifcwrap/utils/typemaps_out.i | 2 + 6 files changed, 123 insertions(+), 1 deletion(-) diff --git a/src/ifcparse/IfcBaseClass.h b/src/ifcparse/IfcBaseClass.h index 11ea7d95ba..917f4b8d26 100644 --- a/src/ifcparse/IfcBaseClass.h +++ b/src/ifcparse/IfcBaseClass.h @@ -74,6 +74,18 @@ namespace IfcUtil { } }; + class IFC_PARSE_API IfcLateBoundEntity : public IfcBaseClass { + private: + const IfcParse::declaration* decl_; + + public: + IfcLateBoundEntity(const IfcParse::declaration* decl, IfcEntityInstanceData* data) : IfcBaseClass(data), decl_(decl) {} + + virtual const IfcParse::declaration& declaration() const { + return *decl_; + } + }; + class IFC_PARSE_API IfcBaseEntity : public IfcBaseClass { public: IfcBaseEntity() : IfcBaseClass() {} diff --git a/src/ifcparse/IfcSchema.cpp b/src/ifcparse/IfcSchema.cpp index 5501b582ba..79c2ae05fb 100644 --- a/src/ifcparse/IfcSchema.cpp +++ b/src/ifcparse/IfcSchema.cpp @@ -1,4 +1,5 @@ #include "IfcSchema.h" +#include "../ifcparse/IfcBaseClass.h" #include @@ -62,6 +63,19 @@ IfcParse::schema_definition::~schema_definition() { } } +IfcUtil::IfcBaseClass* IfcParse::schema_definition::instantiate(IfcEntityInstanceData * data) const { + if (factory_) { + return (*factory_)(data); + } else { + return new IfcUtil::IfcLateBoundEntity(data->type(), data); + } +} + +void IfcParse::register_schema(schema_definition* s) { + schemas.insert({ s->name(), s }); +} + + #include "../ifcparse/Ifc2x3.h" #include "../ifcparse/Ifc4.h" #include "../ifcparse/Ifc4x1.h" diff --git a/src/ifcparse/IfcSchema.h b/src/ifcparse/IfcSchema.h index e7bd98fa2b..da8b6aca5d 100644 --- a/src/ifcparse/IfcSchema.h +++ b/src/ifcparse/IfcSchema.h @@ -443,10 +443,12 @@ namespace IfcParse { const std::string& name() const { return name_; } - IfcUtil::IfcBaseClass* instantiate(IfcEntityInstanceData* data) const { return (*factory_)(data); } + IfcUtil::IfcBaseClass* instantiate(IfcEntityInstanceData* data) const; }; const schema_definition* schema_by_name(const std::string&); + + void register_schema(schema_definition*); } #endif diff --git a/src/ifcwrap/utils/type_conversion.i b/src/ifcwrap/utils/type_conversion.i index cbbb479110..06d76f5b31 100644 --- a/src/ifcwrap/utils/type_conversion.i +++ b/src/ifcwrap/utils/type_conversion.i @@ -115,6 +115,8 @@ return SWIGTYPE_p_IfcParse__select_type; } else if (t->as_enumeration_type()) { return SWIGTYPE_p_IfcParse__enumeration_type; + } else { + throw std::runtime_error("Unexpected declaration type"); } } diff --git a/src/ifcwrap/utils/typemaps_in.i b/src/ifcwrap/utils/typemaps_in.i index f2e542d908..3f84249021 100644 --- a/src/ifcwrap/utils/typemaps_in.i +++ b/src/ifcwrap/utils/typemaps_in.i @@ -65,6 +65,96 @@ CREATE_VECTOR_TYPEMAP_IN(int, INTEGER, int) CREATE_VECTOR_TYPEMAP_IN(double, REAL, float) CREATE_VECTOR_TYPEMAP_IN(std::string, STRING, str) +// @todo use macros. + +%typemap(in) const std::vector& { + if (PySequence_Check($input)) { + $1 = new std::vector; + for(Py_ssize_t i = 0; i < PySequence_Size($input); ++i) { + PyObject* element = PySequence_GetItem($input, i); + void *arg = 0; + int res = SWIG_ConvertPtr(element, &arg, SWIGTYPE_p_IfcParse__declaration, 0); + auto decl = static_cast(SWIG_IsOK(res) ? arg : 0); + if (decl) { + $1->push_back(decl); + } else { + SWIG_exception(SWIG_TypeError, "Expected a schema declaration"); + } + } + } else { + SWIG_exception(SWIG_TypeError, "Expected an sequence type"); + } +} + +%typemap(in) const std::vector& { + if (PySequence_Check($input)) { + $1 = new std::vector; + for(Py_ssize_t i = 0; i < PySequence_Size($input); ++i) { + PyObject* element = PySequence_GetItem($input, i); + void *arg = 0; + int res = SWIG_ConvertPtr(element, &arg, SWIGTYPE_p_IfcParse__entity, 0); + auto decl = static_cast(SWIG_IsOK(res) ? arg : 0); + if (decl) { + $1->push_back(decl); + } else { + SWIG_exception(SWIG_TypeError, "Expected a schema entity"); + } + } + } else { + SWIG_exception(SWIG_TypeError, "Expected an sequence type"); + } +} + +%typemap(in) const std::vector& { + if (PySequence_Check($input)) { + $1 = new std::vector; + for(Py_ssize_t i = 0; i < PySequence_Size($input); ++i) { + PyObject* element = PySequence_GetItem($input, i); + void *arg = 0; + int res = SWIG_ConvertPtr(element, &arg, SWIGTYPE_p_IfcParse__attribute, 0); + auto decl = static_cast(SWIG_IsOK(res) ? arg : 0); + if (decl) { + $1->push_back(decl); + } else { + SWIG_exception(SWIG_TypeError, "Expected a schema attribute"); + } + } + } else { + SWIG_exception(SWIG_TypeError, "Expected an sequence type"); + } +} + +%typemap(in) const std::vector& { + if (PySequence_Check($input)) { + $1 = new std::vector; + for(Py_ssize_t i = 0; i < PySequence_Size($input); ++i) { + PyObject* element = PySequence_GetItem($input, i); + void *arg = 0; + int res = SWIG_ConvertPtr(element, &arg, SWIGTYPE_p_IfcParse__inverse_attribute, 0); + auto decl = static_cast(SWIG_IsOK(res) ? arg : 0); + if (decl) { + $1->push_back(decl); + } else { + SWIG_exception(SWIG_TypeError, "Expected a schema inverse attribute"); + } + } + } else { + SWIG_exception(SWIG_TypeError, "Expected an sequence type"); + } +} + +%typemap(in) const std::vector& { + if (PySequence_Check($input)) { + $1 = new std::vector; + for(Py_ssize_t i = 0; i < PySequence_Size($input); ++i) { + PyObject* element = PySequence_GetItem($input, i); + $1->push_back(PyObject_IsTrue(element)); + } + } else { + SWIG_exception(SWIG_TypeError, "Expected an sequence type"); + } +} + %typemap(in) IfcEntityList::ptr { if (PySequence_Check($input)) { $1 = IfcEntityList::ptr(new IfcEntityList()); diff --git a/src/ifcwrap/utils/typemaps_out.i b/src/ifcwrap/utils/typemaps_out.i index 651a8ab1d7..b21ba55799 100644 --- a/src/ifcwrap/utils/typemaps_out.i +++ b/src/ifcwrap/utils/typemaps_out.i @@ -21,6 +21,8 @@ $result = SWIG_NewPointerObj(SWIG_as_voidptr($1->as_simple_type()), SWIGTYPE_p_IfcParse__simple_type, 0); } else if ($1->as_aggregation_type()) { $result = SWIG_NewPointerObj(SWIG_as_voidptr($1->as_aggregation_type()), SWIGTYPE_p_IfcParse__aggregation_type, 0); + } else { + throw std::runtime_error("unexpected parameter type"); } }