diff options
-rw-r--r-- | slicer/slicer/hookMap.h | 101 | ||||
-rw-r--r-- | slicer/slicer/modelParts.cpp | 8 | ||||
-rw-r--r-- | slicer/slicer/modelParts.h | 14 | ||||
-rw-r--r-- | slicer/slicer/modelPartsTypes.cpp | 3 | ||||
-rw-r--r-- | slicer/slicer/modelPartsTypes.h | 8 | ||||
-rw-r--r-- | slicer/slicer/modelPartsTypes.impl.h | 68 | ||||
-rw-r--r-- | slicer/tool/parser.cpp | 59 |
7 files changed, 165 insertions, 96 deletions
diff --git a/slicer/slicer/hookMap.h b/slicer/slicer/hookMap.h new file mode 100644 index 0000000..fb75b33 --- /dev/null +++ b/slicer/slicer/hookMap.h @@ -0,0 +1,101 @@ +#ifndef SLICER_HOOK_MAP_H +#define SLICER_HOOK_MAP_H + +#include "modelParts.h" +#include <array> +#include <boost/algorithm/string/case_conv.hpp> + +namespace Slicer { + template<typename T> class ModelPartForComplex; + template<typename T> class Hooks { + public: + using HookPtr = const typename ModelPartForComplex<T>::HookBase *; + + template<typename K> class eq; + + template<typename K> class iter : public std::iterator<std::bidirectional_iterator_tag, HookPtr> { + public: + iter(const eq<K> * const r, const HookPtr * c) : range(r), cur(c) + { + operator++(); // move to first match + } + + HookPtr + operator*() const + { + return *cur; + } + + void + operator++() + { + for (; cur != range->e && (*cur)->*(range->name) != range->key; cur++) { } + } + + bool + operator!=(const iter & other) const + { + return cur != other.cur; + } + + private: + const eq<K> * const range; + const HookPtr * cur; + }; + + template<typename K> class eq { + public: + iter<K> + begin() const + { + return {this, b}; + } + + iter<K> + end() const + { + return {this, e}; + } + + K key; + std::string_view HookCommon::*name; + const HookPtr *b, *e; + }; + + template<typename K> + inline eq<K> + equal_range(const K & k, bool matchCase) const + { + return {matchCase ? k : boost::algorithm::to_lower_copy(k), + matchCase ? &HookCommon::name : &HookCommon::nameLower, begin(), end()}; + } + + virtual constexpr const HookPtr * begin() const = 0; + virtual constexpr const HookPtr * end() const = 0; + }; + + template<typename T, std::size_t N> class HooksImpl : public Hooks<T> { + public: + using HookPtr = typename Hooks<T>::HookPtr; + template<std::size_t n> using Arr = std::array<HookPtr, n>; + + inline constexpr HooksImpl(Arr<N> a) : arr(std::move(a)) { } + + constexpr const HookPtr * + begin() const override + { + return arr.begin(); + } + + constexpr const HookPtr * + end() const override + { + return arr.end(); + } + + private: + const Arr<N> arr; + }; +} + +#endif diff --git a/slicer/slicer/modelParts.cpp b/slicer/slicer/modelParts.cpp index 2dd8df5..ccfd647 100644 --- a/slicer/slicer/modelParts.cpp +++ b/slicer/slicer/modelParts.cpp @@ -73,17 +73,15 @@ namespace Slicer { return shared_from_this(); } - HookCommon::HookCommon(std::string n) : name(std::move(n)) { } - bool - HookCommon::filter(const HookFilter & flt) + HookCommon::filter(const HookFilter & flt) const { return (!flt || flt(this)); } void - HookCommon::apply(const ChildHandler & ch, const ModelPartPtr & modelPart) + HookCommon::apply(const ChildHandler & ch, const ModelPartPtr & modelPart) const { - ch(this->name, modelPart, this); + ch(*this->nameStr, modelPart, this); } } diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h index a63d035..c3dd87d 100644 --- a/slicer/slicer/modelParts.h +++ b/slicer/slicer/modelParts.h @@ -69,7 +69,6 @@ namespace Slicer { using ModelPartPtr = std::shared_ptr<ModelPart>; using ModelPartForRootPtr = std::shared_ptr<ModelPartForRootBase>; - using HookCommonPtr = std::unique_ptr<HookCommon>; using TypeId = std::optional<std::string>; using ChildHandler = std::function<void(const std::string &, ModelPartPtr, const HookCommon *)>; using ClassRef = std::function<ModelPartPtr(void *)>; @@ -108,14 +107,19 @@ namespace Slicer { class DLL_PUBLIC HookCommon { public: - explicit HookCommon(std::string); + constexpr HookCommon(std::string_view n, std::string_view nl, const std::string * ns) : + name(n), nameLower(nl), nameStr(ns) + { + } - bool filter(const HookFilter & flt); - void apply(const ChildHandler & ch, const ModelPartPtr & modelPart); + bool filter(const HookFilter & flt) const; + void apply(const ChildHandler & ch, const ModelPartPtr & modelPart) const; [[nodiscard]] virtual const Metadata & GetMetadata() const = 0; - const std::string name; + std::string_view name; + std::string_view nameLower; + const std::string * nameStr; }; struct case_less { diff --git a/slicer/slicer/modelPartsTypes.cpp b/slicer/slicer/modelPartsTypes.cpp index 73e13bf..4ba7557 100644 --- a/slicer/slicer/modelPartsTypes.cpp +++ b/slicer/slicer/modelPartsTypes.cpp @@ -1,6 +1,9 @@ #include "modelPartsTypes.impl.h" #include <boost/algorithm/string/case_conv.hpp> #include <boost/algorithm/string/predicate.hpp> +#include <boost/multi_index/member.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <boost/multi_index_container.hpp> #include <cxxabi.h> namespace Slicer { diff --git a/slicer/slicer/modelPartsTypes.h b/slicer/slicer/modelPartsTypes.h index 35f6cab..a95b5c5 100644 --- a/slicer/slicer/modelPartsTypes.h +++ b/slicer/slicer/modelPartsTypes.h @@ -139,10 +139,10 @@ namespace Slicer { static const std::string & ToModelTypeName(const std::string &); }; + template<typename T> class Hooks; template<typename T> class DLL_PUBLIC ModelPartForComplex : public ModelPartForComplexBase { public: class DLL_PRIVATE HookBase; - using HookPtr = std::unique_ptr<HookBase>; template<typename MT, typename MP> class DLL_PRIVATE Hook; @@ -160,11 +160,7 @@ namespace Slicer { protected: template<typename R> DLL_PRIVATE ChildRef GetChildRefFromRange(const R & range, const HookFilter & flt); - class DLL_PRIVATE Hooks; - - template<typename H, typename... P> static void addHook(Hooks &, const P &...); - - static const Hooks hooks; + static const Hooks<T> & hooks(); static const Metadata metadata; }; diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index eaab54b..ebfd6d9 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -3,15 +3,11 @@ #include "common.h" #include "enumMap.h" +#include "hookMap.h" #include "modelPartsTypes.h" #include <Ice/StreamHelpers.h> #include <IceUtil/Optional.h> -#include <boost/algorithm/string/case_conv.hpp> -#include <boost/multi_index/global_fun.hpp> -#include <boost/multi_index/member.hpp> -#include <boost/multi_index/ordered_index.hpp> -#include <boost/multi_index/sequenced_index.hpp> -#include <boost/multi_index_container.hpp> +#include <boost/assert.hpp> #include <c++11Helpers.h> #define CUSTOMMODELPARTFOR(Type, BaseModelPart, ModelPartType) \ @@ -405,47 +401,23 @@ namespace Slicer { // ModelPartForComplex template<typename T> - class ModelPartForComplex<T>::Hooks : - public boost::multi_index_container<HookPtr, - boost::multi_index::indexed_by<boost::multi_index::sequenced<>, - boost::multi_index::ordered_non_unique< - boost::multi_index::member<HookCommon, const std::string, &HookCommon::name>, - std::less<>>, - boost::multi_index::ordered_non_unique< - boost::multi_index::member<HookCommon, const std::string, &HookCommon::name>, - case_less>>> { - }; - - template<typename T> void ModelPartForComplex<T>::OnEachChild(const ChildHandler & ch) { - for (const auto & h : hooks) { + for (const auto & h : hooks()) { h->apply(ch, h->Get(GetModel())); } } - template<typename P> - auto - begin(const P & p) - { - return p.first; - } - template<typename P> - auto - end(const P & p) - { - return p.second; - } template<typename T> template<typename R> ChildRef ModelPartForComplex<T>::GetChildRefFromRange(const R & range, const HookFilter & flt) { - const auto itr = std::find_if(boost::begin(range), boost::end(range), [&flt](auto && h) { + const auto itr = std::find_if(range.begin(), range.end(), [&flt](auto && h) { return h->filter(flt); }); - if (itr != boost::end(range)) { + if (itr != range.end()) { const auto & h = *itr; auto model = GetModel(); return ChildRef(h->Get(model), h->GetMetadata()); @@ -457,19 +429,14 @@ namespace Slicer { ChildRef ModelPartForComplex<T>::GetAnonChildRef(const HookFilter & flt) { - return GetChildRefFromRange(hooks.template get<0>(), flt); + return GetChildRefFromRange(hooks(), flt); } template<typename T> ChildRef ModelPartForComplex<T>::GetChildRef(const std::string & name, const HookFilter & flt, bool matchCase) { - if (matchCase) { - return GetChildRefFromRange(hooks.template get<1>().equal_range(name), flt); - } - else { - return GetChildRefFromRange(hooks.template get<2>().equal_range(name), flt); - } + return GetChildRefFromRange(hooks().equal_range(name, matchCase), flt); } template<typename T> @@ -479,19 +446,9 @@ namespace Slicer { return metadata; } - template<typename T> - template<typename H, typename... P> - void - ModelPartForComplex<T>::addHook(Hooks & h, const P &... p) - { - h.push_back(std::make_unique<H>(p...)); - } - template<typename T> class DLL_PRIVATE ModelPartForComplex<T>::HookBase : public HookCommon { public: - explicit HookBase(const std::string & n) : HookCommon(n) { } - SPECIAL_MEMBERS_DEFAULT(HookBase); - virtual ~HookBase() = default; + using HookCommon::HookCommon; virtual ModelPartPtr Get(T * t) const = 0; [[nodiscard]] const Metadata & @@ -505,7 +462,10 @@ namespace Slicer { template<typename MT, typename MP> class DLL_PRIVATE ModelPartForComplex<T>::Hook : public ModelPartForComplex<T>::HookBase { public: - Hook(MT T::*m, const std::string & n) : HookBase(n), member(m) { } + constexpr Hook(MT T::*m, std::string_view n, std::string_view nl, const std::string * ns) : + HookBase(n, nl, ns), member(m) + { + } ModelPartPtr Get(T * t) const override @@ -522,8 +482,8 @@ namespace Slicer { template<typename MT, typename MP> class DLL_PRIVATE ModelPartForComplex<T>::HookMetadata : public ModelPartForComplex<T>::template Hook<MT, MP> { public: - HookMetadata(MT T::*member, const std::string & n, Metadata md) : - Hook<MT, MP>(member, n), hookMetadata(std::move(md)) + HookMetadata(MT T::*member, std::string_view n, std::string_view nl, const std::string * ns, Metadata md) : + Hook<MT, MP>(member, n, nl, ns), hookMetadata(std::move(md)) { } diff --git a/slicer/tool/parser.cpp b/slicer/tool/parser.cpp index 5951d54..39dda2d 100644 --- a/slicer/tool/parser.cpp +++ b/slicer/tool/parser.cpp @@ -2,6 +2,7 @@ #include <Slice/CPlusPlusUtil.h> #include <Slice/Parser.h> #include <Slice/Preprocessor.h> +#include <boost/algorithm/string/case_conv.hpp> #include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/split.hpp> @@ -370,36 +371,41 @@ namespace Slicer { externType(dm->type()); } fprintbf(cpp, "using C%d = ModelPartForComplex< %s >;\n", components, it->scoped()); - fprintbf(cpp, "template<> DLL_PUBLIC\n"); - fprintbf(cpp, "const C%d::Hooks ", components); - fprintbf(cpp, "C%d::hooks ([](){\n", components); - fprintbf(cpp, "\t\tC%d::Hooks r;\n", components); + + size_t en = 0; for (const auto & dm : dataMembers) { + auto name = metaDataValue("slicer:name:", dm->getMetaData()).value_or(dm->name()); + fprintbf(cpp, "\tconst std::string hstr%d_%d { \"%s\" };\n", components, en, name); + auto c = Slice::ContainedPtr::dynamicCast(dm->container()); auto t = Slice::TypePtr::dynamicCast(dm->container()); if (!t) { t = Slice::ClassDefPtr::dynamicCast(dm->container())->declaration(); } - auto name = metaDataValue("slicer:name:", dm->getMetaData()).value_or(dm->name()); - fprintbf(cpp, "\t\tC%d::addHook<C%d::", components, components); auto type = dm->type(); - if (hasMetadata(dm->getMetaData())) { - fprintbf(cpp, "HookMetadata<"); - } - else { - fprintbf(cpp, "Hook<"); - } + fprintbf(cpp, "\t%s C%d::%s<", hasMetadata(dm->getMetaData()) ? "static" : "constexpr", components, + hasMetadata(dm->getMetaData()) ? "HookMetadata" : "Hook"); fprintbf(cpp, " %s, ", Slice::typeToString(type, dm->optional())); createNewModelPartPtrFor(type, dm, getAllMetadata(dm)); - fprintbf(cpp, " > >(r, &%s, \"%s\"", dm->scoped(), name); + fprintbf(cpp, " > hook%d_%d {&%s, \"%s\", \"%s\", &hstr%d_%d", components, en, dm->scoped(), name, + boost::algorithm::to_lower_copy(name), components, en); if (hasMetadata(dm->getMetaData())) { fprintbf(cpp, ", Metadata "); copyMetadata(dm->getMetaData()); } - fprintbf(cpp, ");\n"); + fprintbf(cpp, "};\n"); + en++; } - fprintbf(cpp, "\t\treturn r;\n"); - fprintbf(cpp, "\t}());\n\n"); + + en = 0; + fprintbf( + cpp, "constexpr const HooksImpl< %s, %d > hooks%d {{{\n", it->scoped(), dataMembers.size(), components); + for (const auto & dm : dataMembers) { + fprintbf(cpp, " &hook%d_%d, // %s\n", components, en++, dm->name()); + } + fprintbf(cpp, "\t}}};\n"); + fprintbf(cpp, "\ttemplate<> const Hooks< %s > & C%d::hooks() { return hooks%d; }\n", it->scoped(), components, + components); } void @@ -513,21 +519,22 @@ namespace Slicer { iname ? *iname : "element"); fprintbf(cpp, "using C%d = ModelPartForComplex< %s::value_type >;\n", components, d->scoped()); - fprintbf(cpp, "template<> DLL_PUBLIC\n"); - fprintbf(cpp, "const C%d::Hooks ", components); - fprintbf(cpp, "C%d::hooks ([](){\n", components); - fprintbf(cpp, "\t\tC%d::Hooks r;\n", components); auto addHook = [&](const std::string & name, const char * element, const Slice::TypePtr & t) { - fprintbf(cpp, "\t\t"); - fprintbf(cpp, "C%d::addHook< C%d::Hook< const %s, ", components, components, Slice::typeToString(t)); + fprintbf(cpp, "\tconst std::string hstr%d_%d { \"%s\" };\n", components, element, name); + fprintbf(cpp, "\tconstexpr C%d::Hook< const %s, ", components, Slice::typeToString(t)); createNewModelPartPtrFor(t); - fprintbf(cpp, " > >(r, &%s::value_type::%s, \"%s\");\n", d->scoped(), element, name); + fprintbf(cpp, " > hook%d_%s {&%s::value_type::%s, \"%s\", \"%s\", &hstr%d_%s};\n", components, element, + d->scoped(), element, name, boost::algorithm::to_lower_copy(name), components, element); }; addHook(metaDataValue("slicer:key:", d->getMetaData()).value_or("key"), "first", d->keyType()); addHook(metaDataValue("slicer:value:", d->getMetaData()).value_or("value"), "second", d->valueType()); - fprintbf(cpp, "\t\treturn r;\n"); - fprintbf(cpp, "\t}());\n"); - fprintbf(cpp, "\n"); + + fprintbf(cpp, "constexpr const HooksImpl< %s::value_type, 2 > hooks%d {{{\n", d->scoped(), components); + fprintbf(cpp, " &hook%d_first,\n", components); + fprintbf(cpp, " &hook%d_second,\n", components); + fprintbf(cpp, "\t}}};\n"); + fprintbf(cpp, "\ttemplate<> const Hooks< %s::value_type > & C%d::hooks() { return hooks%d; }\n", d->scoped(), + components, components); auto name = metaDataValue("slicer:root:", d->getMetaData()); defineRoot(d->scoped(), name ? *name : d->name(), d); |