From 4ca71158e7b3a1a0e827cc036dd3a8e2cbf9e162 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 18 Oct 2017 19:19:28 +0100 Subject: Store hooks in a boost multi index with sequential name based access, including case insensitive. Simplify lookups and searches accordingly. --- slicer/db/sqlSelectDeserializer.cpp | 5 +---- slicer/slicer/modelParts.cpp | 6 ------ slicer/slicer/modelParts.h | 5 ++--- slicer/slicer/modelPartsTypes.cpp | 29 +++++++++++++++++++++-------- slicer/slicer/modelPartsTypes.h | 36 ++++++++++++++++++++++++------------ slicer/slicer/modelPartsTypes.impl.h | 29 ++++++++++++++++++++++------- slicer/test/conversions.h | 1 + slicer/tool/parser.cpp | 5 +++-- 8 files changed, 74 insertions(+), 42 deletions(-) diff --git a/slicer/db/sqlSelectDeserializer.cpp b/slicer/db/sqlSelectDeserializer.cpp index ec64545..3516265 100644 --- a/slicer/db/sqlSelectDeserializer.cpp +++ b/slicer/db/sqlSelectDeserializer.cpp @@ -2,7 +2,6 @@ #include "sqlSource.h" #include #include -#include namespace Slicer { SqlSelectDeserializer::SqlSelectDeserializer(DB::SelectCommand & c, IceUtil::Optional tc) : @@ -96,9 +95,7 @@ namespace Slicer { for (auto col = 0u; col < columnCount; col += 1) { const DB::Column & c = cmd[col]; if (!c.isNull()) { - auto fmpr = rmp->GetAnonChildRef([&c](const Slicer::HookCommon * h) { - return boost::iequals(c.name, h->name); - }); + auto fmpr = rmp->GetChildRef(c.name, NULL, false); if (fmpr) { auto fmp = fmpr.Child(); fmp->Create(); diff --git a/slicer/slicer/modelParts.cpp b/slicer/slicer/modelParts.cpp index e227c07..dbefdcd 100644 --- a/slicer/slicer/modelParts.cpp +++ b/slicer/slicer/modelParts.cpp @@ -130,12 +130,6 @@ namespace Slicer { { } - bool - HookCommon::filter(const HookFilter & flt, const std::string & name) - { - return (this->name == name && (!flt || flt(this))); - } - bool HookCommon::filter(const HookFilter & flt) { diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h index 982a010..46c4fbc 100644 --- a/slicer/slicer/modelParts.h +++ b/slicer/slicer/modelParts.h @@ -127,7 +127,6 @@ namespace Slicer { HookCommon(const std::string &); bool filter(const HookFilter & flt); - bool filter(const HookFilter & flt, const std::string &); void apply(const ChildHandler & ch, const ModelPartPtr & modelPart); virtual const Metadata & GetMetadata() const = 0; @@ -150,7 +149,7 @@ namespace Slicer { ModelPartPtr GetAnonChild(const HookFilter & = HookFilter()); ModelPartPtr GetChild(const std::string & memberName, const HookFilter & = HookFilter()); virtual ChildRef GetAnonChildRef(const HookFilter & = HookFilter()) = 0; - virtual ChildRef GetChildRef(const std::string & memberName, const HookFilter & = HookFilter()) = 0; + virtual ChildRef GetChildRef(const std::string & memberName, const HookFilter & = HookFilter(), bool matchCase = true) = 0; virtual ModelPartPtr GetSubclassModelPart(const std::string &); virtual TypeId GetTypeId() const; virtual IceUtil::Optional GetTypeIdProperty() const; @@ -182,7 +181,7 @@ namespace Slicer { virtual const std::string & GetRootName() const = 0; virtual ChildRef GetAnonChildRef(const HookFilter &) override; - virtual ChildRef GetChildRef(const std::string & name, const HookFilter &) override; + virtual ChildRef GetChildRef(const std::string & name, const HookFilter &, bool matchCase = true) override; virtual void OnEachChild(const ChildHandler & ch) override; virtual ModelPartType GetType() const override; virtual bool IsOptional() const override; diff --git a/slicer/slicer/modelPartsTypes.cpp b/slicer/slicer/modelPartsTypes.cpp index c6f72d1..a1575e2 100644 --- a/slicer/slicer/modelPartsTypes.cpp +++ b/slicer/slicer/modelPartsTypes.cpp @@ -1,4 +1,6 @@ #include "modelPartsTypes.impl.h" +#include +#include namespace Slicer { MODELPARTFOR(std::string, ModelPartForSimple); @@ -28,6 +30,12 @@ namespace Slicer { template<> const std::string Slicer::ModelPartForRoot>::rootName = "OptionalInt"; template<> const std::string Slicer::ModelPartForRoot>::rootName = "OptionalLong"; + bool + optionalCaseEq(const std::string & a, const std::string & b, bool matchCase) + { + return (matchCase ? boost::equals(a, b) : boost::iequals(a, b)); + } + // ModelPartForRootBase ModelPartForRootBase::ModelPartForRootBase(ModelPartPtr m) : mp(m) @@ -42,9 +50,9 @@ namespace Slicer { } ChildRef - ModelPartForRootBase::GetChildRef(const std::string & name, const HookFilter & hf) + ModelPartForRootBase::GetChildRef(const std::string & name, const HookFilter & hf, bool matchCase) { - if (name != GetRootName()) { + if (!optionalCaseEq(name, GetRootName(), matchCase)) { throw IncorrectElementName(name); } return GetAnonChildRef(hf); @@ -75,14 +83,14 @@ namespace Slicer { void ModelPartForSimpleBase::OnEachChild(const ChildHandler &) { } ChildRef ModelPartForSimpleBase::GetAnonChildRef(const HookFilter &) { return ChildRef(); } - ChildRef ModelPartForSimpleBase::GetChildRef(const std::string &, const HookFilter &) { return ChildRef(); } + ChildRef ModelPartForSimpleBase::GetChildRef(const std::string &, const HookFilter &, bool) { return ChildRef(); } bool ModelPartForSimpleBase::HasValue() const { return true; } ModelPartType ModelPartForSimpleBase::GetType() const { return type; } const ModelPartType ModelPartForSimpleBase::type = mpt_Simple; void ModelPartForConvertedBase::OnEachChild(const ChildHandler &) { } ChildRef ModelPartForConvertedBase::GetAnonChildRef(const HookFilter &) { return ChildRef(); } - ChildRef ModelPartForConvertedBase::GetChildRef(const std::string &, const HookFilter &) { return ChildRef(); } + ChildRef ModelPartForConvertedBase::GetChildRef(const std::string &, const HookFilter &, bool) { return ChildRef(); } bool ModelPartForConvertedBase::HasValue() const { return true; } ModelPartType ModelPartForConvertedBase::GetType() const { return type; } const ModelPartType ModelPartForConvertedBase::type = mpt_Simple; @@ -122,6 +130,11 @@ namespace Slicer { return "::" + std::string(buf.get()); } + std::string ModelPartForComplexBase::hookNameLower(const HookCommon & h) + { + return boost::algorithm::to_lower_copy(h.name); + } + void ModelPartForOptionalBase::OnEachChild(const ChildHandler & ch) { if (this->hasModel()) { @@ -144,10 +157,10 @@ namespace Slicer { return ChildRef(); } - ChildRef ModelPartForOptionalBase::GetChildRef(const std::string & name, const HookFilter & flt) + ChildRef ModelPartForOptionalBase::GetChildRef(const std::string & name, const HookFilter & flt, bool matchCase) { if (this->hasModel()) { - return modelPart->GetChildRef(name, flt); + return modelPart->GetChildRef(name, flt, matchCase); } return ChildRef(); } @@ -176,7 +189,7 @@ namespace Slicer { void ModelPartForEnumBase::OnEachChild(const ChildHandler &) { } ChildRef ModelPartForEnumBase::GetAnonChildRef(const HookFilter &) { return ChildRef(); } - ChildRef ModelPartForEnumBase::GetChildRef(const std::string &, const HookFilter &) { return ChildRef(); } + ChildRef ModelPartForEnumBase::GetChildRef(const std::string &, const HookFilter &, bool) { return ChildRef(); } bool ModelPartForEnumBase::HasValue() const { return true; } ModelPartType ModelPartForEnumBase::GetType() const { return type; } const ModelPartType ModelPartForEnumBase::type = mpt_Simple; @@ -191,7 +204,7 @@ namespace Slicer { // Streams ChildRef ModelPartForStreamBase::GetAnonChildRef(const Slicer::HookFilter &) { throw InvalidStreamOperation(__FUNCTION__); } - ChildRef ModelPartForStreamBase::GetChildRef(const std::string &, const Slicer::HookFilter &) { throw InvalidStreamOperation(__FUNCTION__); } + ChildRef ModelPartForStreamBase::GetChildRef(const std::string &, const Slicer::HookFilter &, bool) { throw InvalidStreamOperation(__FUNCTION__); } ModelPartType ModelPartForStreamBase::GetType() const { return mpt_Sequence; } bool ModelPartForStreamBase::HasValue() const { return true; } // Stream Roots diff --git a/slicer/slicer/modelPartsTypes.h b/slicer/slicer/modelPartsTypes.h index 630eec7..37bf824 100644 --- a/slicer/slicer/modelPartsTypes.h +++ b/slicer/slicer/modelPartsTypes.h @@ -3,6 +3,9 @@ #include "modelParts.h" #include +#include +#include +#include namespace Slicer { template @@ -10,6 +13,8 @@ namespace Slicer { static constexpr bool value = false; }; + DLL_PUBLIC bool optionalCaseEq(const std::string & a, const std::string & b, bool matchCase); + template class DLL_PUBLIC ModelPartForRoot : public ModelPartForRootBase { public: @@ -30,7 +35,7 @@ namespace Slicer { public: virtual void OnEachChild(const ChildHandler &) override; virtual ChildRef GetAnonChildRef(const HookFilter &) override; - virtual ChildRef GetChildRef(const std::string &, const HookFilter &) override; + virtual ChildRef GetChildRef(const std::string &, const HookFilter &, bool matchCase = true) override; virtual bool HasValue() const override; virtual ModelPartType GetType() const override; static const ModelPartType type; @@ -51,7 +56,7 @@ namespace Slicer { public: virtual void OnEachChild(const ChildHandler &) override; virtual ChildRef GetAnonChildRef(const HookFilter &) override; - virtual ChildRef GetChildRef(const std::string &, const HookFilter &) override; + virtual ChildRef GetChildRef(const std::string &, const HookFilter &, bool matchCase = true) override; virtual bool HasValue() const override; virtual ModelPartType GetType() const override; static const ModelPartType type; @@ -95,7 +100,7 @@ namespace Slicer { virtual void OnEachChild(const ChildHandler & ch) override; virtual void Complete() override; virtual ChildRef GetAnonChildRef(const HookFilter & flt) override; - virtual ChildRef GetChildRef(const std::string & name, const HookFilter & flt) override; + virtual ChildRef GetChildRef(const std::string & name, const HookFilter & flt, bool matchCase = true) override; virtual void SetValue(ValueSource && s) override; virtual bool HasValue() const override; virtual bool IsOptional() const override; @@ -130,6 +135,7 @@ namespace Slicer { static void unregisterClass(const std::string & className, const std::string * typeName); static TypeId GetTypeId(const std::string & id, const std::string & className); static std::string demangle(const char * mangled); + static std::string hookNameLower(const HookCommon &); }; template @@ -168,19 +174,25 @@ namespace Slicer { virtual void OnEachChild(const ChildHandler & ch) override; virtual ChildRef GetAnonChildRef(const HookFilter & flt) override; - ChildRef GetChildRef(const std::string & name, const HookFilter & flt) override; + ChildRef GetChildRef(const std::string & name, const HookFilter & flt, bool matchCase = true) override; virtual const Metadata & GetMetadata() const override; virtual T * GetModel() = 0; - typedef std::vector Hooks; + typedef boost::multi_index_container< + HookPtr, + boost::multi_index::indexed_by< + boost::multi_index::sequenced<>, + boost::multi_index::ordered_non_unique>, + boost::multi_index::ordered_non_unique> + >> Hooks; template - static void addHook(Hooks &, const P & ...); + DLL_PRIVATE static void addHook(Hooks &, const P & ...); - static const Hooks hooks; - static const Metadata metadata; + DLL_PRIVATE static const Hooks hooks; + DLL_PRIVATE static const Metadata metadata; }; template @@ -233,7 +245,7 @@ namespace Slicer { public: virtual void OnEachChild(const ChildHandler &) override; ChildRef GetAnonChildRef(const HookFilter &) override; - ChildRef GetChildRef(const std::string &, const HookFilter &) override; + ChildRef GetChildRef(const std::string &, const HookFilter &, bool matchCase = true) override; virtual bool HasValue() const override; virtual ModelPartType GetType() const override; static const ModelPartType type; @@ -277,7 +289,7 @@ namespace Slicer { ChildRef GetAnonChildRef(const HookFilter &) override; - ChildRef GetChildRef(const std::string &, const HookFilter &) override; + ChildRef GetChildRef(const std::string &, const HookFilter &, bool matchCase = true) override; virtual const Metadata & GetMetadata() const override; @@ -321,7 +333,7 @@ namespace Slicer { ChildRef GetAnonChildRef(const HookFilter &) override; - ChildRef GetChildRef(const std::string & name, const HookFilter &) override; + ChildRef GetChildRef(const std::string & name, const HookFilter &, bool matchCase = true) override; virtual const Metadata & GetMetadata() const override; @@ -345,7 +357,7 @@ namespace Slicer { virtual ModelPartType GetType() const override; virtual bool HasValue() const override; virtual ChildRef GetAnonChildRef(const HookFilter &) override; - virtual ChildRef GetChildRef(const std::string &, const HookFilter &) override; + virtual ChildRef GetChildRef(const std::string &, const HookFilter &, bool matchCase = true) override; virtual ModelPartPtr GetContainedModelPart() override = 0; virtual void OnEachChild(const ChildHandler & ch) override = 0; diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index a1a963a..9409c33 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -7,6 +7,10 @@ #include #include #include +#include +#include +#include +#include #define CUSTOMMODELPARTFOR(Type, BaseModelPart, ModelPartType) \ template class BaseModelPart; \ @@ -337,7 +341,7 @@ namespace Slicer { template ChildRef ModelPartForComplex::GetAnonChildRef(const HookFilter & flt) { - for (const auto & h : hooks) { + for (const auto & h : hooks.template get<0>()) { if (h->filter(flt)) { return ChildRef(h->Get(GetModel()), h->GetMetadata()); } @@ -345,12 +349,23 @@ namespace Slicer { return ChildRef(); } + template auto begin(const P & p) { return p.first; } + template auto end(const P & p) { return p.second; } template - ChildRef ModelPartForComplex::GetChildRef(const std::string & name, const HookFilter & flt) + ChildRef ModelPartForComplex::GetChildRef(const std::string & name, const HookFilter & flt, bool matchCase) { - for (const auto & h : hooks) { - if (h->filter(flt, name)) { - return ChildRef(h->Get(GetModel()), h->GetMetadata()); + if (matchCase) { + for (const auto & h : hooks.template get<1>().equal_range(name)) { + if (h->filter(flt)) { + return ChildRef(h->Get(GetModel()), h->GetMetadata()); + } + } + } + else { + for (const auto & h : hooks.template get<2>().equal_range(boost::algorithm::to_lower_copy(name))) { + if (h->filter(flt)) { + return ChildRef(h->Get(GetModel()), h->GetMetadata()); + } } } return ChildRef(); @@ -649,10 +664,10 @@ namespace Slicer { } template - ChildRef ModelPartForDictionary::GetChildRef(const std::string & name, const HookFilter &) + ChildRef ModelPartForDictionary::GetChildRef(const std::string & name, const HookFilter &, bool matchCase) { BOOST_ASSERT(this->Model); - if (name != pairName) { + if (!optionalCaseEq(name, pairName, matchCase)) { throw IncorrectElementName(name); } return ChildRef(new ModelPartForDictionaryElementInserter(this->Model)); diff --git a/slicer/test/conversions.h b/slicer/test/conversions.h index dfc76c6..c540e77 100644 --- a/slicer/test/conversions.h +++ b/slicer/test/conversions.h @@ -2,6 +2,7 @@ #define SLICER_TEST_CONVERSIONS_H #include +#include #include #include #include diff --git a/slicer/tool/parser.cpp b/slicer/tool/parser.cpp index 51e6f10..bc641f5 100644 --- a/slicer/tool/parser.cpp +++ b/slicer/tool/parser.cpp @@ -330,14 +330,15 @@ namespace Slicer { fprintbf(cpp, "// Sequence %s\n", s->name()); fprintbf(cpp, "template<>\n"); - fprintbf(cpp, "ChildRef ModelPartForSequence< %s >::GetChildRef(const std::string & name, const HookFilter & flt)\n{\n", + fprintbf(cpp, "ChildRef ModelPartForSequence< %s >::GetChildRef(const std::string & name, const HookFilter & flt, bool matchCase)\n{\n", s->scoped()); auto iname = metaDataValue("slicer:item:", s->getMetaData()); if (iname) { - fprintbf(cpp, "\tif (!name.empty() && name != \"%s\") { throw IncorrectElementName(name); }\n", + fprintbf(cpp, "\tif (!name.empty() && !optionalCaseEq(name, \"%s\", matchCase)) { throw IncorrectElementName(name); }\n", *iname); } else { + fprintbf(cpp, "\t(void)matchCase;\n"); fprintbf(cpp, "\t(void)name;\n"); } fprintbf(cpp, "\treturn GetAnonChildRef(flt);\n}\n\n"); -- cgit v1.2.3