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);  | 
