summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--slicer/slicer/hookMap.h101
-rw-r--r--slicer/slicer/modelParts.cpp8
-rw-r--r--slicer/slicer/modelParts.h14
-rw-r--r--slicer/slicer/modelPartsTypes.cpp3
-rw-r--r--slicer/slicer/modelPartsTypes.h8
-rw-r--r--slicer/slicer/modelPartsTypes.impl.h68
-rw-r--r--slicer/tool/parser.cpp59
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);