From 876e40db376ae5cb0bc3c97c5fd70b2b1bee4d46 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 20 Aug 2023 01:35:19 +0100 Subject: Logical inversion Removes ChildRef and changes ModelPart returning ModelPart functions with functions accepting a callback. Removes the need to maintain and pass around ModelPart pointers. ~30% performance increase processing large DB datasets. --- slicer/db/sqlInsertSerializer.cpp | 7 +- slicer/db/sqlSelectDeserializer.cpp | 58 ++++++------ slicer/db/sqlTablePatchSerializer.cpp | 17 ++-- slicer/db/sqlUpdateSerializer.cpp | 7 +- slicer/json/serializer.cpp | 121 ++++++++++++++++--------- slicer/slicer/modelParts.cpp | 33 +++---- slicer/slicer/modelParts.h | 42 +++------ slicer/slicer/modelPartsTypes.cpp | 113 ++++++----------------- slicer/slicer/modelPartsTypes.h | 47 ++++------ slicer/slicer/modelPartsTypes.impl.h | 85 +++++++++--------- slicer/slicer/slicer.cpp | 23 ----- slicer/test/compilation.cpp | 73 ++++++++------- slicer/xml/serializer.cpp | 165 ++++++++++++++++++++-------------- 13 files changed, 385 insertions(+), 406 deletions(-) diff --git a/slicer/db/sqlInsertSerializer.cpp b/slicer/db/sqlInsertSerializer.cpp index c99df57..0881a1b 100644 --- a/slicer/db/sqlInsertSerializer.cpp +++ b/slicer/db/sqlInsertSerializer.cpp @@ -49,9 +49,10 @@ namespace Slicer { void SqlInsertSerializer::SerializeSequence(ModelPartParam mp) const { - auto ins = createInsert(mp->GetContainedModelPart()); - mp->OnEachChild([&ins, this](auto &&, auto && cmp, auto &&) { - bindObjectAndExecute(cmp, ins.get()); + mp->OnContained([this, mp](auto && cmp) { + mp->OnEachChild([ins = createInsert(cmp), this](auto &&, auto && chmp, auto &&) { + bindObjectAndExecute(chmp, ins.get()); + }); }); } diff --git a/slicer/db/sqlSelectDeserializer.cpp b/slicer/db/sqlSelectDeserializer.cpp index 526f4b7..e11493e 100644 --- a/slicer/db/sqlSelectDeserializer.cpp +++ b/slicer/db/sqlSelectDeserializer.cpp @@ -47,10 +47,11 @@ namespace Slicer { return; } if (!(*cmd)[0].isNull()) { - auto fmp = mp->GetAnonChild(); - fmp->Create(); - fmp->SetValue(SqlSource((*cmd)[0])); - fmp->Complete(); + mp->OnAnonChild([this](auto && fmp, auto &&) { + fmp->Create(); + fmp->SetValue(SqlSource((*cmd)[0])); + fmp->Complete(); + }); } if (cmd->fetch()) { throw TooManyRowsReturned(); @@ -60,10 +61,11 @@ namespace Slicer { void SqlSelectDeserializer::DeserializeSequence(ModelPartParam omp) { - auto mp = omp->GetAnonChild(); - while (cmd->fetch()) { - DeserializeRow(mp); - } + omp->OnAnonChild([this](auto && mp, auto &&) { + while (cmd->fetch()) { + DeserializeRow(mp); + } + }); } void @@ -85,29 +87,33 @@ namespace Slicer { void SqlSelectDeserializer::DeserializeRow(ModelPartParam mp) { - auto rmp = mp->GetAnonChild(); - if (rmp) { + mp->OnAnonChild([this](auto && rmp, auto &&) { switch (rmp->GetType()) { case Slicer::ModelPartType::Complex: { + auto apply = [this](auto && rcmp) { + rcmp->Create(); + for (auto col = 0U; col < columnCount; col += 1) { + const DB::Column & c = (*cmd)[col]; + if (!c.isNull()) { + rcmp->OnChild( + [&c](auto && fmp, auto &&) { + if (fmp) { + fmp->Create(); + fmp->SetValue(SqlSource(c)); + fmp->Complete(); + } + }, + c.name, nullptr, false); + } + } + rcmp->Complete(); + }; if (typeIdColIdx) { std::string subclass; (*cmd)[*typeIdColIdx] >> subclass; - rmp = rmp->GetSubclassModelPart(subclass); - } - rmp->Create(); - for (auto col = 0U; col < columnCount; col += 1) { - const DB::Column & c = (*cmd)[col]; - if (!c.isNull()) { - auto fmpr = rmp->GetChildRef(c.name, nullptr, false); - if (fmpr) { - auto fmp = fmpr.Child(); - fmp->Create(); - fmp->SetValue(SqlSource(c)); - fmp->Complete(); - } - } + return rmp->OnSubclass(apply, subclass); } - rmp->Complete(); + apply(rmp); } break; case Slicer::ModelPartType::Simple: { rmp->Create(); @@ -120,6 +126,6 @@ namespace Slicer { default: throw UnsupportedModelType(); } - } + }); } } diff --git a/slicer/db/sqlTablePatchSerializer.cpp b/slicer/db/sqlTablePatchSerializer.cpp index da5b0b2..ec0e344 100644 --- a/slicer/db/sqlTablePatchSerializer.cpp +++ b/slicer/db/sqlTablePatchSerializer.cpp @@ -32,14 +32,15 @@ namespace Slicer { SqlInsertSerializer ins(db, tablePatch.src); ins.Serialize(mpr); - auto mp = mpr->GetContainedModelPart(); - mp->OnEachChild([this](const auto & name, const auto &, const auto & h) { - if (isPKey(h)) { - tablePatch.pk.insert(name); - } - if (isBind(h)) { - tablePatch.cols.insert(name); - } + mpr->OnContained([this](auto && mp) { + mp->OnEachChild([this](const auto & name, const auto &, const auto & h) { + if (isPKey(h)) { + tablePatch.pk.insert(name); + } + if (isBind(h)) { + tablePatch.cols.insert(name); + } + }); }); db->patchTable(&tablePatch); diff --git a/slicer/db/sqlUpdateSerializer.cpp b/slicer/db/sqlUpdateSerializer.cpp index c054764..152c923 100644 --- a/slicer/db/sqlUpdateSerializer.cpp +++ b/slicer/db/sqlUpdateSerializer.cpp @@ -49,9 +49,10 @@ namespace Slicer { void SqlUpdateSerializer::SerializeSequence(ModelPartParam mp) const { - auto ins = createUpdate(mp->GetContainedModelPart()); - mp->OnEachChild([&ins](auto &&, auto && cmp, auto &&) { - bindObjectAndExecute(cmp, ins.get()); + mp->OnContained([this, mp](auto && cmp) { + mp->OnEachChild([upd = createUpdate(cmp)](auto &&, auto && chmp, auto &&) { + bindObjectAndExecute(chmp, upd.get()); + }); }); } diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index 9bbd508..5b2725b 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -151,9 +151,9 @@ namespace Slicer { class DocumentTreeIterate { public: static void - visit(ModelPartPtr && mp, const json::Value & v) + visit(ModelPartParam mp, const json::Value & v) { - std::visit(DocumentTreeIterate {std::move(mp)}, v); + std::visit(DocumentTreeIterate {mp}, v); } template @@ -174,34 +174,47 @@ namespace Slicer { void operator()(const json::Object & o) const { + auto apply = [&o](auto && objectModelPart) { + objectModelPart->Create(); + if (objectModelPart->GetMetadata().flagSet(md_object)) { + for (const auto & element : o) { + objectModelPart->OnAnonChild([&element](auto && emp, auto &&) { + emp->Create(); + emp->OnChild( + [&element](auto && key, auto &&) { + key->Create(); + key->SetValue(JsonValueSource(element.first)); + key->Complete(); + }, + keyName); + emp->OnChild( + [&element](auto && value, auto &&) { + visit(value, element.second); + }, + valueName); + emp->Complete(); + }); + } + } + else { + for (const auto & element : o) { + objectModelPart->OnChild( + [&element](auto && emp, auto &&) { + visit(emp, element.second); + emp->Complete(); + }, + element.first); + } + objectModelPart->Complete(); + } + }; if (auto typeIdName = modelPart->GetTypeIdProperty()) { auto typeAttrItr = o.find(*typeIdName); if (typeAttrItr != o.end() && std::holds_alternative(typeAttrItr->second)) { - modelPart = modelPart->GetSubclassModelPart(std::get(typeAttrItr->second)); - } - } - modelPart->Create(); - if (modelPart->GetMetadata().flagSet(md_object)) { - for (const auto & element : o) { - auto emp = modelPart->GetAnonChild(); - emp->Create(); - auto key = emp->GetChild(keyName); - key->Create(); - key->SetValue(JsonValueSource(element.first)); - key->Complete(); - visit(emp->GetChild(valueName), element.second); - emp->Complete(); + return modelPart->OnSubclass(apply, std::get(typeAttrItr->second)); } } - else { - for (const auto & element : o) { - if (auto emp = modelPart->GetChild(element.first)) { - visit(std::move(emp), element.second); - emp->Complete(); - } - } - modelPart->Complete(); - } + apply(modelPart); } void @@ -209,16 +222,15 @@ namespace Slicer { { modelPart->Create(); for (const auto & element : a) { - if (auto emp = modelPart->GetAnonChild()) { - emp->Create(); - visit(std::move(emp), element); + modelPart->OnAnonChild([&element](auto && emp, auto &&) { + visit(emp, element); emp->Complete(); - } + }); } modelPart->Complete(); } - ModelPartPtr && modelPart; + ModelPartParam modelPart; }; void ModelTreeIterateTo(const std::function &, ModelPartParam mp); @@ -243,15 +255,23 @@ namespace Slicer { if (!mp->HasValue()) { return; } - ModelTreeIterateTo( - [&d, mp]() -> json::Value & { - json::Object::key_type k; - json::Value kv; - mp->GetChild(keyName)->GetValue(JsonValueTarget(kv)); - JsonValueSource(kv).set(k); - return d[std::move(k)]; + mp->OnChild( + [&d, mp](auto && cmp, auto &&) { + ModelTreeIterateTo( + [&d, mp]() -> json::Value & { + json::Object::key_type k; + json::Value kv; + mp->OnChild( + [&kv](auto && emp, auto &&) { + emp->GetValue(JsonValueTarget(kv)); + }, + keyName); + JsonValueSource(kv).set(k); + return d[std::move(k)]; + }, + cmp); }, - mp->GetChild(valueName)); + valueName); } void @@ -291,8 +311,11 @@ namespace Slicer { }; if (auto typeIdName = mp->GetTypeIdProperty()) { if (auto typeId = mp->GetTypeId()) { - oec(mp->GetSubclassModelPart(*typeId))->emplace(*typeIdName, *typeId); - return; + return mp->OnSubclass( + [&oec, &typeIdName, &typeId](auto && lmp) { + oec(lmp)->emplace(*typeIdName, *typeId); + }, + *typeId); } } oec(mp); @@ -331,7 +354,11 @@ namespace Slicer { void JsonStreamDeserializer::Deserialize(ModelPartForRootParam modelRoot) { - DocumentTreeIterate::visit(modelRoot->GetAnonChild(), json::parseValue(strm)); + modelRoot->OnAnonChild( + [this](auto && mp, auto &&) { + DocumentTreeIterate::visit(mp, json::parseValue(strm)); + }, + {}); } void @@ -349,7 +376,11 @@ namespace Slicer { JsonFileDeserializer::Deserialize(ModelPartForRootParam modelRoot) { std::ifstream inFile(path); - DocumentTreeIterate::visit(modelRoot->GetAnonChild(), json::parseValue(inFile)); + modelRoot->OnAnonChild( + [&inFile](auto && mp, auto &&) { + DocumentTreeIterate::visit(mp, json::parseValue(inFile)); + }, + {}); } JsonValueDeserializer::JsonValueDeserializer(const json::Value & v) : value(v) { } @@ -357,7 +388,11 @@ namespace Slicer { void JsonValueDeserializer::Deserialize(ModelPartForRootParam modelRoot) { - DocumentTreeIterate::visit(modelRoot->GetAnonChild(), value); + modelRoot->OnAnonChild( + [this](auto && mp, auto &&) { + DocumentTreeIterate::visit(mp, value); + }, + {}); } void diff --git a/slicer/slicer/modelParts.cpp b/slicer/slicer/modelParts.cpp index abe94d8..07b4095 100644 --- a/slicer/slicer/modelParts.cpp +++ b/slicer/slicer/modelParts.cpp @@ -11,10 +11,10 @@ namespace Slicer { { } - ModelPartPtr - ModelPart::GetSubclassModelPart(const std::string &) + void + ModelPart::OnSubclass(const ModelPartHandler &, const std::string &) { - throw std::logic_error {"GetSubclassModelPart not supported on this ModelPart"}; + throw std::logic_error {"OnSubclass not supported on this ModelPart"}; } TypeId @@ -46,30 +46,33 @@ namespace Slicer { return emptyMetadata; } - ModelPartPtr - ModelPart::GetAnonChild(const HookFilter & flt) + bool + ModelPart::IsOptional() const { - auto ref = GetAnonChildRef(flt); - return ref ? ref.Child() : ModelPartPtr(nullptr); + return false; } - ModelPartPtr - ModelPart::GetChild(std::string_view memberName, const HookFilter & flt) + void + ModelPart::OnEachChild(const ChildHandler &) { - auto ref = GetChildRef(memberName, flt); - return ref ? ref.Child() : ModelPartPtr(nullptr); } bool - ModelPart::IsOptional() const + ModelPart::OnAnonChild(const SubPartHandler &, const HookFilter &) { return false; } - ModelPartPtr - ModelPart::GetContainedModelPart() + bool + ModelPart::OnChild(const SubPartHandler &, const std::string_view, const HookFilter &, bool) + { + return false; + } + + void + ModelPart::OnContained(const ModelPartHandler &) { - throw std::logic_error {"GetContainedModelPart not supported on this ModelPart"}; + throw std::logic_error {"OnContained not supported on this ModelPart"}; } bool diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h index 1f1a50e..39149fd 100644 --- a/slicer/slicer/modelParts.h +++ b/slicer/slicer/modelParts.h @@ -83,10 +83,12 @@ namespace Slicer { using ModelPartParam = any_ptr; using ModelPartForRootParam = any_ptr; using TypeId = std::optional; + using Metadata = MetaData<>; using ChildHandler = std::function; - using ClassRef = std::function; + using ModelPartHandler = std::function; + using SubPartHandler = std::function; + using ClassRef = std::function; using HookFilter = std::function; - using Metadata = MetaData<>; constexpr Metadata emptyMetadata; enum class ModelPartType { @@ -103,21 +105,6 @@ namespace Slicer { Value, }; - class DLL_PUBLIC ChildRef { - public: - explicit ChildRef(); - explicit ChildRef(ModelPartPtr); - explicit ChildRef(ModelPartPtr, const Metadata &); - - [[nodiscard]] ModelPartPtr Child() const; - [[nodiscard]] const Metadata & ChildMetaData() const; - explicit operator bool() const; - - private: - ModelPartPtr mpp; - const Metadata & mdr; - }; - class DLL_PUBLIC HookCommon { public: constexpr HookCommon(std::string_view n, std::string_view nl, const std::string * ns) : @@ -156,14 +143,11 @@ namespace Slicer { template static ModelPartPtr CreateFor(Default &&); template static ModelPartForRootPtr CreateRootFor(T & t); - virtual void OnEachChild(const ChildHandler &) = 0; - ModelPartPtr GetAnonChild(const HookFilter & = HookFilter()); - ModelPartPtr GetChild(std::string_view memberName, const HookFilter & = HookFilter()); - virtual ChildRef GetAnonChildRef(const HookFilter & = HookFilter()) = 0; - virtual ChildRef GetChildRef( - std::string_view memberName, const HookFilter & = HookFilter(), bool matchCase = true) - = 0; - virtual ModelPartPtr GetSubclassModelPart(const std::string &); + virtual void OnEachChild(const ChildHandler &); + virtual bool OnAnonChild(const SubPartHandler &, const HookFilter & = HookFilter()); + virtual bool OnChild(const SubPartHandler &, std::string_view memberName, const HookFilter & = HookFilter(), + bool matchCase = true); + virtual void OnSubclass(const ModelPartHandler &, const std::string &); virtual TypeId GetTypeId() const; virtual std::optional GetTypeIdProperty() const; virtual ModelPartType GetType() const = 0; @@ -174,7 +158,7 @@ namespace Slicer { virtual bool HasValue() const = 0; virtual const Metadata & GetMetadata() const; virtual bool IsOptional() const; - virtual ModelPartPtr GetContainedModelPart(); + virtual void OnContained(const ModelPartHandler &); }; template class DLL_PUBLIC ModelPartModel { @@ -189,14 +173,14 @@ namespace Slicer { explicit ModelPartForRootBase(ModelPartPtr mp); virtual const std::string & GetRootName() const = 0; - ChildRef GetAnonChildRef(const HookFilter &) override; - ChildRef GetChildRef(std::string_view name, const HookFilter &, bool matchCase = true) override; + bool OnAnonChild(const SubPartHandler &, const HookFilter &) override; + bool OnChild(const SubPartHandler &, std::string_view name, const HookFilter &, bool matchCase = true) override; void OnEachChild(const ChildHandler & ch) override; ModelPartType GetType() const override; bool IsOptional() const override; virtual void Write(::Ice::OutputStream &) const = 0; virtual void Read(::Ice::InputStream &) = 0; - ModelPartPtr GetContainedModelPart() override; + void OnContained(const ModelPartHandler &) override; ModelPartPtr mp; }; diff --git a/slicer/slicer/modelPartsTypes.cpp b/slicer/slicer/modelPartsTypes.cpp index bd130bf..da38efe 100644 --- a/slicer/slicer/modelPartsTypes.cpp +++ b/slicer/slicer/modelPartsTypes.cpp @@ -110,20 +110,22 @@ namespace Slicer { // ModelPartForRootBase ModelPartForRootBase::ModelPartForRootBase(ModelPartPtr m) : mp(std::move(m)) { } - ChildRef - ModelPartForRootBase::GetAnonChildRef(const HookFilter &) + bool + ModelPartForRootBase::OnAnonChild(const SubPartHandler & h, const HookFilter &) { mp->Create(); - return ChildRef(mp); + h(mp, emptyMetadata); + return true; } - ChildRef - ModelPartForRootBase::GetChildRef(std::string_view name, const HookFilter & hf, bool matchCase) + bool + ModelPartForRootBase::OnChild( + const SubPartHandler & h, std::string_view name, const HookFilter & hf, bool matchCase) { if (!optionalCaseEq(name, GetRootName(), matchCase)) { throw IncorrectElementName(std::string {name}); } - return GetAnonChildRef(hf); + return OnAnonChild(h, hf); } void @@ -144,27 +146,10 @@ namespace Slicer { return mp->IsOptional(); } - ModelPartPtr - ModelPartForRootBase::GetContainedModelPart() - { - return mp->GetContainedModelPart(); - } - void - ModelPartForSimpleBase::OnEachChild(const ChildHandler &) - { - } - - ChildRef - ModelPartForSimpleBase::GetAnonChildRef(const HookFilter &) - { - return ChildRef(); - } - - ChildRef - ModelPartForSimpleBase::GetChildRef(std::string_view, const HookFilter &, bool) + ModelPartForRootBase::OnContained(const ModelPartHandler & h) { - return ChildRef(); + return mp->OnContained(h); } bool @@ -181,23 +166,6 @@ namespace Slicer { const ModelPartType ModelPartForSimpleBase::type = ModelPartType::Simple; - void - ModelPartForConvertedBase::OnEachChild(const ChildHandler &) - { - } - - ChildRef - ModelPartForConvertedBase::GetAnonChildRef(const HookFilter &) - { - return ChildRef(); - } - - ChildRef - ModelPartForConvertedBase::GetChildRef(std::string_view, const HookFilter &, bool) - { - return ChildRef(); - } - bool ModelPartForConvertedBase::HasValue() const { @@ -245,11 +213,11 @@ namespace Slicer { } } - ModelPartPtr - ModelPartForComplexBase::getSubclassModelPart(const std::string & name, void * m) + void + ModelPartForComplexBase::onSubclass(const std::string & name, void * m, const ModelPartHandler & h) { if (const auto ref = refs->find(ToModelTypeName(name)); ref != refs->end()) { - return ref->second(m); + return ref->second(m, h); } throw UnknownType(name); } @@ -284,22 +252,23 @@ namespace Slicer { } } - ChildRef - ModelPartForOptionalBase::GetAnonChildRef(const HookFilter & flt) + bool + ModelPartForOptionalBase::OnAnonChild(const SubPartHandler & h, const HookFilter & flt) { if (this->hasModel()) { - return modelPart->GetAnonChildRef(flt); + return modelPart->OnAnonChild(h, flt); } - return ChildRef(); + return false; } - ChildRef - ModelPartForOptionalBase::GetChildRef(std::string_view name, const HookFilter & flt, bool matchCase) + bool + ModelPartForOptionalBase::OnChild( + const SubPartHandler & h, std::string_view name, const HookFilter & flt, bool matchCase) { if (this->hasModel()) { - return modelPart->GetChildRef(name, flt, matchCase); + return modelPart->OnChild(h, name, flt, matchCase); } - return ChildRef(); + return false; } void @@ -328,23 +297,6 @@ namespace Slicer { return modelPart->GetMetadata(); } - void - ModelPartForEnumBase::OnEachChild(const ChildHandler &) - { - } - - ChildRef - ModelPartForEnumBase::GetAnonChildRef(const HookFilter &) - { - return ChildRef(); - } - - ChildRef - ModelPartForEnumBase::GetChildRef(std::string_view, const HookFilter &, bool) - { - return ChildRef(); - } - bool ModelPartForEnumBase::HasValue() const { @@ -371,13 +323,14 @@ namespace Slicer { return type; } - ChildRef - ModelPartForSequenceBase::GetChildRef(std::string_view name, const HookFilter & flt, bool matchCase) + bool + ModelPartForSequenceBase::OnChild( + const SubPartHandler & h, std::string_view name, const HookFilter & flt, bool matchCase) { if (!name.empty() && !optionalCaseEq(name, GetElementName(), matchCase)) { throw IncorrectElementName(std::string {name}); } - return GetAnonChildRef(flt); + return OnAnonChild(h, flt); } const ModelPartType ModelPartForSequenceBase::type = ModelPartType::Sequence; @@ -397,20 +350,6 @@ namespace Slicer { const ModelPartType ModelPartForDictionaryBase::type = ModelPartType::Dictionary; // Streams - // NOLINTNEXTLINE(hicpp-no-array-decay) - ChildRef - ModelPartForStreamBase::GetAnonChildRef(const Slicer::HookFilter &) - { - throw InvalidStreamOperation(__FUNCTION__); - } - - // NOLINTNEXTLINE(hicpp-no-array-decay) - ChildRef - ModelPartForStreamBase::GetChildRef(std::string_view, const Slicer::HookFilter &, bool) - { - throw InvalidStreamOperation(__FUNCTION__); - } - ModelPartType ModelPartForStreamBase::GetType() const { diff --git a/slicer/slicer/modelPartsTypes.h b/slicer/slicer/modelPartsTypes.h index b6e7b3c..ab262f3 100644 --- a/slicer/slicer/modelPartsTypes.h +++ b/slicer/slicer/modelPartsTypes.h @@ -41,9 +41,6 @@ namespace Slicer { class DLL_PUBLIC ModelPartForSimpleBase : public ModelPart { public: - void OnEachChild(const ChildHandler &) override; - ChildRef GetAnonChildRef(const HookFilter &) override; - ChildRef GetChildRef(std::string_view, const HookFilter &, bool matchCase = true) override; bool HasValue() const override; ModelPartType GetType() const override; static const ModelPartType type; @@ -62,9 +59,6 @@ namespace Slicer { class DLL_PUBLIC ModelPartForConvertedBase : public ModelPart { public: - void OnEachChild(const ChildHandler &) override; - ChildRef GetAnonChildRef(const HookFilter &) override; - ChildRef GetChildRef(std::string_view, const HookFilter &, bool matchCase = true) override; bool HasValue() const override; ModelPartType GetType() const override; static const ModelPartType type; @@ -109,8 +103,9 @@ namespace Slicer { public: void OnEachChild(const ChildHandler & ch) override; void Complete() override; - ChildRef GetAnonChildRef(const HookFilter & flt) override; - ChildRef GetChildRef(std::string_view name, const HookFilter & flt, bool matchCase = true) override; + bool OnAnonChild(const SubPartHandler &, const HookFilter & flt) override; + bool OnChild( + const SubPartHandler &, std::string_view name, const HookFilter & flt, bool matchCase = true) override; void SetValue(ValueSource && s) override; bool HasValue() const override; bool IsOptional() const override; @@ -142,7 +137,7 @@ namespace Slicer { static const ModelPartType type; protected: - ModelPartPtr getSubclassModelPart(const std::string & name, void * m); + void onSubclass(const std::string & name, void * m, const ModelPartHandler &); static void registerClass(const std::string & className, const std::string * typeName, const ClassRef &); static void unregisterClass(const std::string & className, const std::string * typeName); @@ -163,15 +158,16 @@ namespace Slicer { void OnEachChild(const ChildHandler & ch) override; - ChildRef GetAnonChildRef(const HookFilter & flt) override; - ChildRef GetChildRef(std::string_view name, const HookFilter & flt, bool matchCase = true) override; + bool OnAnonChild(const SubPartHandler &, const HookFilter & flt) override; + bool OnChild( + const SubPartHandler &, std::string_view name, const HookFilter & flt, bool matchCase = true) override; const Metadata & GetMetadata() const override; virtual T * GetModel() = 0; protected: - template ChildRef GetChildRefFromRange(const R & range, const HookFilter & flt); + template bool OnChildFromRange(const SubPartHandler &, const R & range, const HookFilter & flt); static const Hooks & hooks(); }; @@ -187,7 +183,7 @@ namespace Slicer { T * GetModel() override; - ModelPartPtr GetSubclassModelPart(const std::string & name) override; + void OnSubclass(const ModelPartHandler &, const std::string & name) override; [[nodiscard]] bool HasValue() const override; @@ -199,7 +195,7 @@ namespace Slicer { static const std::string * className; static const std::string * typeName; - static ModelPartPtr CreateModelPart(void *); + static void CreateModelPart(void *, const ModelPartHandler &); private: static void initClassName(); @@ -221,9 +217,6 @@ namespace Slicer { class DLL_PUBLIC ModelPartForEnumBase : public ModelPart { public: - void OnEachChild(const ChildHandler &) override; - ChildRef GetAnonChildRef(const HookFilter &) override; - ChildRef GetChildRef(std::string_view, const HookFilter &, bool matchCase = true) override; bool HasValue() const override; ModelPartType GetType() const override; static const ModelPartType type; @@ -252,7 +245,7 @@ namespace Slicer { public: bool HasValue() const override; ModelPartType GetType() const override; - ChildRef GetChildRef(std::string_view, const HookFilter &, bool matchCase = true) override; + bool OnChild(const SubPartHandler &, std::string_view, const HookFilter &, bool matchCase = true) override; virtual const std::string & GetElementName() const = 0; static const ModelPartType type; @@ -266,19 +259,19 @@ namespace Slicer { void OnEachChild(const ChildHandler & ch) override; - ChildRef GetAnonChildRef(const HookFilter &) override; + bool OnAnonChild(const SubPartHandler &, const HookFilter &) override; const std::string & GetElementName() const override; const Metadata & GetMetadata() const override; - ModelPartPtr GetContainedModelPart() override; + void OnContained(const ModelPartHandler &) override; static const Metadata metadata; static const std::string elementName; private: - ModelPartPtr elementModelPart(typename T::value_type &) const; + // ModelPartPtr elementModelPart(typename T::value_type &) const; }; template @@ -309,13 +302,13 @@ namespace Slicer { void OnEachChild(const ChildHandler & ch) override; - ChildRef GetAnonChildRef(const HookFilter &) override; + bool OnAnonChild(const SubPartHandler &, const HookFilter &) override; - ChildRef GetChildRef(std::string_view name, const HookFilter &, bool matchCase = true) override; + bool OnChild(const SubPartHandler &, std::string_view name, const HookFilter &, bool matchCase = true) override; const Metadata & GetMetadata() const override; - ModelPartPtr GetContainedModelPart() override; + void OnContained(const ModelPartHandler &) override; static const Metadata metadata; static const std::string pairName; @@ -337,10 +330,8 @@ namespace Slicer { public: ModelPartType GetType() const override; bool HasValue() const override; - ChildRef GetAnonChildRef(const HookFilter &) override; - ChildRef GetChildRef(std::string_view, const HookFilter &, bool matchCase = true) override; - ModelPartPtr GetContainedModelPart() override = 0; + void OnContained(const ModelPartHandler &) override = 0; void OnEachChild(const ChildHandler & ch) override = 0; }; @@ -348,7 +339,7 @@ namespace Slicer { public: using ModelPartModel>::ModelPartModel; - ModelPartPtr GetContainedModelPart() override; + void OnContained(const ModelPartHandler &) override; void OnEachChild(const ChildHandler & ch) override; }; diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index 0924de6..9cdbe47 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -354,8 +354,8 @@ namespace Slicer { template template - ChildRef - ModelPartForComplex::GetChildRefFromRange(const R & range, const HookFilter & flt) + bool + ModelPartForComplex::OnChildFromRange(const SubPartHandler & ch, const R & range, const HookFilter & flt) { const auto itr = std::find_if(range.begin(), range.end(), [&flt](auto && h) { return h->filter(flt); @@ -363,29 +363,31 @@ namespace Slicer { if (itr != range.end()) { const auto & h = *itr; auto model = GetModel(); - return ChildRef(h->Get(model), h->GetMetadata()); + ch(h->Get(model), h->GetMetadata()); + return true; } - return ChildRef(); + return false; } template - ChildRef - ModelPartForComplex::GetAnonChildRef(const HookFilter & flt) + bool + ModelPartForComplex::OnAnonChild(const SubPartHandler & ch, const HookFilter & flt) { - return GetChildRefFromRange(hooks(), flt); + return OnChildFromRange(ch, hooks(), flt); } template - ChildRef - ModelPartForComplex::GetChildRef(std::string_view name, const HookFilter & flt, bool matchCase) + bool + ModelPartForComplex::OnChild( + const SubPartHandler & ch, std::string_view name, const HookFilter & flt, bool matchCase) { if (matchCase) { - return GetChildRefFromRange(hooks().equal_range(name), flt); + return OnChildFromRange(ch, hooks().equal_range(name), flt); } else { std::string i {name}; to_lower(i); - return GetChildRefFromRange(hooks().equal_range_lower(i), flt); + return OnChildFromRange(ch, hooks().equal_range_lower(i), flt); } } @@ -453,11 +455,11 @@ namespace Slicer { } template - ModelPartPtr - ModelPartForClass::GetSubclassModelPart(const std::string & name) + void + ModelPartForClass::OnSubclass(const ModelPartHandler & h, const std::string & name) { BOOST_ASSERT(this->Model); - return ModelPartForComplexBase::getSubclassModelPart(name, this->Model); + return ModelPartForComplexBase::onSubclass(name, this->Model, h); } template @@ -476,10 +478,10 @@ namespace Slicer { } template - ModelPartPtr - ModelPartForClass::CreateModelPart(void * p) + void + ModelPartForClass::CreateModelPart(void * p, const ModelPartHandler & h) { - return ::Slicer::ModelPart::CreateFor(*static_cast(p)); + return h(::Slicer::ModelPart::CreateFor(*static_cast(p))); } template @@ -598,16 +600,17 @@ namespace Slicer { { BOOST_ASSERT(this->Model); for (auto & element : *this->Model) { - ch(elementName, elementModelPart(element), NULL); + ch(elementName, ModelPart::CreateFor(element), NULL); } } template - ChildRef - ModelPartForSequence::GetAnonChildRef(const HookFilter &) + bool + ModelPartForSequence::OnAnonChild(const SubPartHandler & ch, const HookFilter &) { BOOST_ASSERT(this->Model); - return ChildRef(ModelPart::CreateFor(this->Model->emplace_back())); + ch(ModelPart::CreateFor(this->Model->emplace_back()), emptyMetadata); + return true; } template @@ -625,17 +628,10 @@ namespace Slicer { } template - ModelPartPtr - ModelPartForSequence::elementModelPart(typename T::value_type & e) const - { - return ModelPart::CreateFor(e); - } - - template - ModelPartPtr - ModelPartForSequence::GetContainedModelPart() + void + ModelPartForSequence::OnContained(const ModelPartHandler & h) { - return ModelPart::CreateFor(Default {}); + return h(ModelPart::CreateFor(Default {})); } // ModelPartForDictionaryElementInserter @@ -664,22 +660,25 @@ namespace Slicer { } template - ChildRef - ModelPartForDictionary::GetAnonChildRef(const HookFilter &) + bool + ModelPartForDictionary::OnAnonChild(const SubPartHandler & ch, const HookFilter &) { BOOST_ASSERT(this->Model); - return ChildRef(std::make_shared>(this->Model)); + ch(std::make_shared>(this->Model), emptyMetadata); + return true; } template - ChildRef - ModelPartForDictionary::GetChildRef(std::string_view name, const HookFilter &, bool matchCase) + bool + ModelPartForDictionary::OnChild( + const SubPartHandler & ch, std::string_view name, const HookFilter &, bool matchCase) { BOOST_ASSERT(this->Model); if (!optionalCaseEq(name, pairName, matchCase)) { throw IncorrectElementName(std::string {name}); } - return ChildRef(std::make_shared>(this->Model)); + ch(std::make_shared>(this->Model), emptyMetadata); + return true; } template @@ -690,18 +689,18 @@ namespace Slicer { } template - ModelPartPtr - ModelPartForDictionary::GetContainedModelPart() + void + ModelPartForDictionary::OnContained(const ModelPartHandler & h) { - return std::make_shared>(nullptr); + return h(std::make_shared>(nullptr)); } // ModelPartForStream template - ModelPartPtr - ModelPartForStream::GetContainedModelPart() + void + ModelPartForStream::OnContained(const ModelPartHandler & h) { - return ModelPart::CreateFor(Default {}); + return h(ModelPart::CreateFor(Default {})); } template diff --git a/slicer/slicer/slicer.cpp b/slicer/slicer/slicer.cpp index 2eda740..ff9a948 100644 --- a/slicer/slicer/slicer.cpp +++ b/slicer/slicer/slicer.cpp @@ -5,29 +5,6 @@ #include namespace Slicer { - Slicer::ChildRef::ChildRef() : mpp(), mdr(emptyMetadata) { } - - Slicer::ChildRef::ChildRef(ModelPartPtr m) : mpp(std::move(m)), mdr(emptyMetadata) { } - - Slicer::ChildRef::ChildRef(ModelPartPtr mp, const Slicer::Metadata & md) : mpp(std::move(mp)), mdr(md) { } - - ModelPartPtr - Slicer::ChildRef::Child() const - { - return mpp; - } - - Slicer::ChildRef::operator bool() const - { - return !!mpp; - } - - const Metadata & - Slicer::ChildRef::ChildMetaData() const - { - return mdr; - } - AdHocFormatter(InvalidEnumerationSymbolMsg, "Invalid enumeration symbol [%?] for type [%?]"); void diff --git a/slicer/test/compilation.cpp b/slicer/test/compilation.cpp index fbbbb5f..ba7c568 100644 --- a/slicer/test/compilation.cpp +++ b/slicer/test/compilation.cpp @@ -40,11 +40,15 @@ BOOST_TEST_DONT_PRINT_LOG_VALUE(Slicer::ModelPartType) #define StackTypeTest(Var, Explicit, Expected) TypeTest(Var, Var(), Explicit, Expected) +constexpr auto DontCall = [](auto &&...) { + BOOST_ERROR("Shouldn't be called"); +}; + BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_class) { TypeTest(TestModule::BuiltInsPtr, std::make_shared(), ModelPartForClass, ModelPartType::Complex); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } static void @@ -53,7 +57,7 @@ hookHandler(std::vector * names, const std::string & name, Slicer:: { names->push_back(name); BOOST_REQUIRE(mpp); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); BOOST_REQUIRE(h); BOOST_REQUIRE_EQUAL(h->name, name); } @@ -61,39 +65,42 @@ hookHandler(std::vector * names, const std::string & name, Slicer:: BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_sequenceclasses) { StackTypeTest(TestModule::Classes, ModelPartForSequence, ModelPartType::Sequence); - auto cmpp = mpp->GetContainedModelPart(); - BOOST_REQUIRE(cmpp); - BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); - std::vector names; - cmpp->OnEachChild([&](auto && PH1, auto && PH2, auto && PH3) { - hookHandler(&names, PH1, PH2, PH3); + mpp->OnContained([](auto && cmpp) { + BOOST_REQUIRE(cmpp); + BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); + std::vector names; + cmpp->OnEachChild([&](auto && PH1, auto && PH2, auto && PH3) { + hookHandler(&names, PH1, PH2, PH3); + }); + BOOST_REQUIRE_EQUAL(2, names.size()); + BOOST_REQUIRE_EQUAL("a", names.front()); + BOOST_REQUIRE_EQUAL("b", names.back()); }); - BOOST_REQUIRE_EQUAL(2, names.size()); - BOOST_REQUIRE_EQUAL("a", names.front()); - BOOST_REQUIRE_EQUAL("b", names.back()); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_sequencestructs) { StackTypeTest(TestModule::Structs, ModelPartForSequence, ModelPartType::Sequence); - auto cmpp = mpp->GetContainedModelPart(); - BOOST_REQUIRE(cmpp); - BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); - std::vector names; - cmpp->OnEachChild([&](auto && PH1, auto && PH2, auto && PH3) { - hookHandler(&names, PH1, PH2, PH3); + mpp->OnContained([](auto && cmpp) { + BOOST_REQUIRE(cmpp); + BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); + std::vector names; + cmpp->OnEachChild([&](auto && PH1, auto && PH2, auto && PH3) { + hookHandler(&names, PH1, PH2, PH3); + }); + BOOST_REQUIRE_EQUAL(2, names.size()); + BOOST_REQUIRE_EQUAL("a", names.front()); + BOOST_REQUIRE_EQUAL("b", names.back()); }); - BOOST_REQUIRE_EQUAL(2, names.size()); - BOOST_REQUIRE_EQUAL("a", names.front()); - BOOST_REQUIRE_EQUAL("b", names.back()); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_mapclasses) { StackTypeTest(TestModule::ClassMap, ModelPartForDictionary, ModelPartType::Dictionary); - auto cmpp = mpp->GetContainedModelPart(); - BOOST_REQUIRE(cmpp); - BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); + mpp->OnContained([](auto && cmpp) { + BOOST_REQUIRE(cmpp); + BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); + }); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_mapstructs) @@ -104,61 +111,61 @@ BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_mapstructs) BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_string) { StackTypeTest(std::string, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_bool) { StackTypeTest(bool, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_float) { StackTypeTest(Ice::Float, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_double) { StackTypeTest(Ice::Double, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_byte) { StackTypeTest(Ice::Byte, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_short) { StackTypeTest(Ice::Short, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_int) { StackTypeTest(Ice::Int, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_long) { StackTypeTest(Ice::Long, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_struct) { StackTypeTest(TestModule::StructType, ModelPartForStruct, ModelPartType::Complex); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_enum) { StackTypeTest(TestModule::SomeNumbers, ModelPartForEnum, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(normalClassTypeId) diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index 5eab4be..8e351b6 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -221,7 +221,7 @@ namespace Slicer { }; void DocumentTreeIterate(const xmlpp::Node * node, ModelPartParam mp); - void DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartParam mp, const ChildRef & c); + void DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartParam mp, const Metadata & md); void DocumentTreeIterate(const xmlpp::Document * doc, ModelPartParam mp); void DocumentTreeIterateDictAttrs(const xmlpp::Element::const_AttributeList & attrs, ModelPartParam dict); void DocumentTreeIterateDictElements(const xmlpp::Element * parent, ModelPartParam dict); @@ -229,18 +229,23 @@ namespace Slicer { void DocumentTreeIterateDictAttrs(const xmlpp::Element::const_AttributeList & attrs, ModelPartParam dict) { - using AttrMember = Glib::ustring (xmlpp::Attribute::*)() const; for (const auto & attr : attrs) { - auto emp = dict->GetAnonChild(); - emp->Create(); - const auto setChild = [&emp, &attr](const auto & childName, AttrMember attrMember) { - auto child = emp->GetChild(childName); - child->SetValue(XmlValueSource((attr->*attrMember)())); - child->Complete(); - }; - setChild(keyName, &xmlpp::Attribute::get_name); - setChild(valueName, &xmlpp::Attribute::get_value); - emp->Complete(); + dict->OnAnonChild([&attr](auto && emp, auto &&) { + emp->Create(); + emp->OnChild( + [&attr](auto && child, auto &&) { + child->SetValue(XmlValueSource(attr->get_name())); + child->Complete(); + }, + keyName); + emp->OnChild( + [&attr](auto && value, auto &&) { + value->SetValue(XmlValueSource(attr->get_value())); + value->Complete(); + }, + valueName); + emp->Complete(); + }); } } @@ -250,31 +255,38 @@ namespace Slicer { auto node = element->get_first_child(); while (node) { if (auto childElement = dynamic_cast(node)) { - auto emp = dict->GetAnonChild(); - emp->Create(); - auto key = emp->GetChild(keyName); - auto value = emp->GetChildRef(valueName); - key->SetValue(XmlValueSource(childElement->get_name())); - key->Complete(); - DocumentTreeIterateElement(childElement, value.Child(), value); - emp->Complete(); + dict->OnAnonChild([childElement](auto && emp, auto &&) { + emp->Create(); + emp->OnChild( + [childElement](auto && child, auto &&) { + child->SetValue(XmlValueSource(childElement->get_name())); + child->Complete(); + }, + keyName); + emp->OnChild( + [childElement](auto && value, auto && md) { + DocumentTreeIterateElement(childElement, value, md); + }, + valueName); + emp->Complete(); + }); } node = node->get_next_sibling(); } } void - DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartParam smp, const ChildRef & smpr) + DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartParam smp, const Metadata & md) { - auto oec = [&smpr, element](const auto & lmp) { + auto oec = [&md, element](const auto & lmp) { lmp->Create(); - if (smpr.ChildMetaData().flagSet(md_attributes)) { + if (md.flagSet(md_attributes)) { auto attrs(element->get_attributes()); if (!attrs.empty()) { DocumentTreeIterateDictAttrs(attrs, lmp); } } - else if (smpr.ChildMetaData().flagSet(md_elements)) { + else if (md.flagSet(md_elements)) { DocumentTreeIterateDictElements(element, lmp); } else { @@ -294,8 +306,7 @@ namespace Slicer { }; if (auto typeIdPropName = smp->GetTypeIdProperty()) { if (auto typeAttr = element->get_attribute(*typeIdPropName)) { - oec(smp->GetSubclassModelPart(typeAttr->get_value())); - return; + return smp->OnSubclass(oec, typeAttr->get_value()); } } oec(smp); @@ -306,40 +317,45 @@ namespace Slicer { { while (node) { if (auto element = dynamic_cast(node)) { - auto smpr = mp->GetChildRef(element->get_name().raw(), [](const auto & h) { - return h->GetMetadata().flagNotSet(md_attribute); - }); - if (smpr) { - auto smp = smpr.Child(); - if (smpr.ChildMetaData().flagSet(md_bare)) { - smp = smp->GetAnonChild(); - } - if (smp) { - DocumentTreeIterateElement(element, smp, smpr); - } - } + mp->OnChild( + [element](auto && smp, auto && md) { + if (md.flagSet(md_bare)) { + smp->OnAnonChild([element](auto && bmp, auto && bmd) { + DocumentTreeIterateElement(element, bmp, bmd); + }); + return; + } + DocumentTreeIterateElement(element, smp, md); + }, + element->get_name().raw(), + [](const auto & h) { + return h->GetMetadata().flagNotSet(md_attribute); + }); } else if (auto attribute = dynamic_cast(node)) { - auto smp = mp->GetChild(attribute->get_name().raw(), [](const auto & h) { - return h->GetMetadata().flagSet(md_attribute); - }); - if (smp) { - smp->Create(); - smp->SetValue(XmlValueSource(attribute)); - smp->Complete(); - } + mp->OnChild( + [attribute](auto && smp, auto &&) { + smp->Create(); + smp->SetValue(XmlValueSource(attribute)); + smp->Complete(); + }, + attribute->get_name().raw(), + [](const auto & h) { + return h->GetMetadata().flagSet(md_attribute); + }); } else if (auto content = dynamic_cast(node)) { - ModelPartPtr smp; + bool bare = false; if (!content->is_white_space()) { - smp = mp->GetAnonChild([](const auto & h) { - return h->GetMetadata().flagSet(md_text); - }); - } - if (smp) { - smp->SetValue(XmlValueSource(content)); + bare = (mp->OnAnonChild( + [content](auto && smp, auto &&) { + smp->SetValue(XmlValueSource(content)); + }, + [](const auto & h) { + return h->GetMetadata().flagSet(md_text); + })); } - else { + if (!bare) { mp->SetValue(XmlValueSource(content)); } } @@ -397,9 +413,17 @@ namespace Slicer { { dict->OnEachChild([element](const auto &, const auto & mp, const auto &) { if (mp->HasValue()) { - mp->GetChild(keyName)->GetValue(XmlValueTarget([&mp, element](const auto & name) { - mp->GetChild(valueName)->GetValue(XmlValueTarget(element, name)); - })); + mp->OnChild( + [mp, element](auto && key, auto &&) { + key->GetValue(XmlValueTarget([mp, element](const auto & name) { + mp->OnChild( + [element, &name](auto && value, auto &&) { + value->GetValue(XmlValueTarget(element, name)); + }, + valueName); + })); + }, + keyName); } }); } @@ -409,12 +433,20 @@ namespace Slicer { { dict->OnEachChild([element](const auto &, const auto & mp, const auto &) { if (mp->HasValue()) { - mp->GetChild(keyName)->GetValue(XmlValueTarget([&mp, element](const auto & name) { - CurrentElementCreator cec([&element, &name]() { - return element->add_child_element(name); - }); - ModelTreeProcessElement(cec, mp->GetChild(valueName), defaultElementCreator); - })); + mp->OnChild( + [mp, element](auto && key, auto &&) { + key->GetValue(XmlValueTarget([mp, element](const auto & name) { + CurrentElementCreator cec([&element, &name]() { + return element->add_child_element(name); + }); + mp->OnChild( + [&cec](auto && value, auto &&) { + ModelTreeProcessElement(cec, value, defaultElementCreator); + }, + valueName); + })); + }, + keyName); } }); } @@ -434,8 +466,11 @@ namespace Slicer { }; if (auto typeIdPropName = mp->GetTypeIdProperty()) { if (auto typeId = mp->GetTypeId()) { - oec(mp->GetSubclassModelPart(*typeId))->set_attribute(*typeIdPropName, *typeId); - return; + return mp->OnSubclass( + [oec, &typeIdPropName, &typeId](auto && smp) { + oec(smp)->set_attribute(*typeIdPropName, *typeId); + }, + *typeId); } } oec(mp); -- cgit v1.2.3