diff options
-rw-r--r-- | slicer/slicer/Jamfile.jam | 6 | ||||
-rw-r--r-- | slicer/slicer/enum-test.cpp | 22 | ||||
-rw-r--r-- | slicer/slicer/enumMap.h | 31 | ||||
-rw-r--r-- | slicer/slicer/hook-test.cpp | 55 | ||||
-rw-r--r-- | slicer/slicer/hookMap.h | 97 | ||||
-rw-r--r-- | slicer/slicer/modelPartsTypes.impl.h | 7 |
6 files changed, 172 insertions, 46 deletions
diff --git a/slicer/slicer/Jamfile.jam b/slicer/slicer/Jamfile.jam index f1ba4b1..38a0c66 100644 --- a/slicer/slicer/Jamfile.jam +++ b/slicer/slicer/Jamfile.jam @@ -2,9 +2,13 @@ import package ; lib stdc++fs ; +obj enum-test : enum-test.cpp ; +obj hook-test : hook-test.cpp : <use>..//adhocutil <implicit-dependency>common ; + obj common : common.ice : <toolset>tidy:<checker>none ; + lib slicer : - [ glob *.cpp ] + [ glob *.cpp : *-test.cpp ] common : <library>..//Ice diff --git a/slicer/slicer/enum-test.cpp b/slicer/slicer/enum-test.cpp new file mode 100644 index 0000000..166804f --- /dev/null +++ b/slicer/slicer/enum-test.cpp @@ -0,0 +1,22 @@ +#include "enumMap.h" + +enum class Es { one, two, three }; +const std::string one {"one"}, two {"two"}, three {"three"}; + +constexpr Slicer::EnumMapImpl<Es, 3> em {{{ + {Es::one, "one", &one}, + {Es::two, "two", &two}, + {Es::three, "three", &three}, +}}}; + +static_assert(em.arr.size() == 3); +static_assert(em.arr[0].value == Es::one); +static_assert(em.arr[1].name == "two"); +static_assert(em.arr[1].nameStr == &two); +static_assert(em.arr[2].value == Es::three); + +static_assert(em.find<Slicer::EnumMapKey::Name>("one")->value == Es::one); +static_assert(em.find<Slicer::EnumMapKey::Name>("three")->value == Es::three); +static_assert(em.find<Slicer::EnumMapKey::Value>(Es::one)->name == "one"); +static_assert(em.find<Slicer::EnumMapKey::Value>(Es::three)->name == "three"); +static_assert(!em.find<Slicer::EnumMapKey::Name>("four")); diff --git a/slicer/slicer/enumMap.h b/slicer/slicer/enumMap.h index 98ecd04..a7b42c2 100644 --- a/slicer/slicer/enumMap.h +++ b/slicer/slicer/enumMap.h @@ -1,6 +1,10 @@ #ifndef SLICER_ENUM_MAP_H #define SLICER_ENUM_MAP_H +#include <array> +#include <string> +#include <string_view> + namespace Slicer { enum class EnumMapKey { Value, @@ -16,12 +20,10 @@ namespace Slicer { }; template<EnumMapKey Key, typename T> - constexpr inline const Node * - find(const T & v) const + [[nodiscard]] constexpr inline const Node * + find(const T & v) const noexcept { - auto b = begin(); - const auto e = end(); - while (b != e) { + for (auto b = begin; b != end; b++) { if constexpr (Key == EnumMapKey::Value) { if (b->value == v) { return b; @@ -32,13 +34,12 @@ namespace Slicer { return b; } } - ++b; } return nullptr; } - virtual constexpr const Node * begin() const = 0; - virtual constexpr const Node * end() const = 0; + const Node * begin {}; + const Node * end {}; }; template<typename E, std::size_t N> class EnumMapImpl : public EnumMap<E> { @@ -46,19 +47,11 @@ namespace Slicer { using NodeType = typename EnumMap<E>::Node; template<std::size_t n> using Arr = std::array<NodeType, n>; - constexpr const NodeType * - begin() const override + inline constexpr EnumMapImpl(Arr<N> a) : arr(std::move(a)) { - return arr.begin(); + EnumMap<E>::begin = arr.begin(); + EnumMap<E>::end = arr.end(); } - - constexpr const NodeType * - end() const override - { - return arr.end(); - } - - inline constexpr EnumMapImpl(Arr<N> a) : arr(std::move(a)) { } const Arr<N> arr; }; } diff --git a/slicer/slicer/hook-test.cpp b/slicer/slicer/hook-test.cpp new file mode 100644 index 0000000..11641c2 --- /dev/null +++ b/slicer/slicer/hook-test.cpp @@ -0,0 +1,55 @@ +#include "hookMap.h" +#include "modelPartsTypes.impl.h" + +#include <string> + +struct S { + int aa; + int aA; + int Aa; + int AA; + std::string b; +}; +const std::string aa {"aa"}, aA {"aA"}, Aa {"Aa"}, AA {"AA"}, b {"b"}; + +using C = Slicer::ModelPartForComplex<S>; +constexpr C::Hook<int, Slicer::ModelPartForSimple<int>> haa {&S::aa, "aa", "aa", &aa}; +constexpr C::Hook<int, Slicer::ModelPartForSimple<int>> haA {&S::aA, "aA", "aa", &aA}; +constexpr C::Hook<int, Slicer::ModelPartForSimple<int>> hAa {&S::Aa, "Aa", "aa", &Aa}; +constexpr C::Hook<int, Slicer::ModelPartForSimple<int>> hAA {&S::AA, "AA", "aa", &AA}; +constexpr C::Hook<std::string, Slicer::ModelPartForSimple<std::string>> hb {&S::b, "b", "b", &b}; +constexpr Slicer::HooksImpl<S, 5> h {{{&haa, &haA, &hAa, &hAA, &hb}}}; + +static_assert(h.arr.size() == 5); +static_assert(h.arr[0]->name == "aa"); +static_assert(h.arr[0]->nameLower == "aa"); +static_assert(h.arr[0]->nameStr == &aa); +static_assert(h.arr[1]->name == "aA"); +static_assert(h.arr[1]->nameLower == "aa"); +static_assert(h.arr[1]->nameStr == &aA); +static_assert(h.arr[4]->name == "b"); +static_assert(h.arr[4]->nameLower == "b"); +static_assert(h.arr[4]->nameStr == &b); + +constexpr auto aas = h.equal_range("aa"); +constexpr auto bbs = h.equal_range("bb"); +static_assert(aas.begin() != aas.end()); +static_assert(bbs.begin() == bbs.end()); +static_assert(aas.begin()->name == "aa"); + +constexpr auto aa0 = aas.begin(); +static_assert(aa0->name == "aa"); +constexpr auto aa1 = aa0 + 1; +static_assert(aa1 == aas.end()); +static_assert(std::distance(aas.begin(), aas.end()) == 1); +static_assert(std::distance(bbs.begin(), bbs.end()) == 0); + +constexpr auto laas = h.equal_range_lower("aa"); +constexpr auto lAAs = h.equal_range_lower("AA"); +static_assert(std::distance(laas.begin(), laas.end()) == 4); +static_assert(std::distance(lAAs.begin(), lAAs.end()) == 0); +static_assert(laas.begin()->name == "aa"); +static_assert((laas.begin() + 1)->name == "aA"); +static_assert((laas.begin() + 2)->name == "Aa"); +static_assert((laas.begin() + 3)->name == "AA"); +static_assert((laas.begin() + 4) == laas.end()); diff --git a/slicer/slicer/hookMap.h b/slicer/slicer/hookMap.h index fb75b33..5b99f96 100644 --- a/slicer/slicer/hookMap.h +++ b/slicer/slicer/hookMap.h @@ -15,43 +15,75 @@ namespace Slicer { 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) + constexpr inline iter(const eq<K> * const r, const HookPtr * c) : range(r), cur(c) { - operator++(); // move to first match + moveMatch(); } - HookPtr + constexpr inline HookPtr operator*() const { return *cur; } - void + constexpr inline HookPtr + operator->() const + { + return *cur; + } + + constexpr inline void operator++() { - for (; cur != range->e && (*cur)->*(range->name) != range->key; cur++) { } + if (cur++ != range->e) { + moveMatch(); + } } - bool + constexpr inline iter + operator+(std::size_t n) const + { + auto i {*this}; + while (n--) { + ++i; + } + return i; + } + + constexpr inline bool operator!=(const iter & other) const { return cur != other.cur; } + constexpr inline bool + operator==(const iter & other) const + { + return cur == other.cur; + } + private: + constexpr void + moveMatch() + { + while (cur != range->e && (*cur)->*(range->name) != range->key) { + cur++; + } + } + const eq<K> * const range; const HookPtr * cur; }; template<typename K> class eq { public: - iter<K> + constexpr inline iter<K> begin() const { return {this, b}; } - iter<K> + constexpr inline iter<K> end() const { return {this, e}; @@ -63,15 +95,39 @@ namespace Slicer { }; template<typename K> + constexpr inline eq<K> + equal_range(K && k) const + { + return {std::move(k), &HookCommon::name, _begin, _end}; + } + + template<typename K> + constexpr inline eq<K> + equal_range_lower(K && k) const + { + return {std::move(k), &HookCommon::nameLower, _begin, _end}; + } + + template<typename K> inline eq<K> - equal_range(const K & k, bool matchCase) const + equal_range_nocase(const K & k) const { - return {matchCase ? k : boost::algorithm::to_lower_copy(k), - matchCase ? &HookCommon::name : &HookCommon::nameLower, begin(), end()}; + return equal_range_lower(boost::algorithm::to_lower_copy(k)); } - virtual constexpr const HookPtr * begin() const = 0; - virtual constexpr const HookPtr * end() const = 0; + constexpr inline auto + begin() const + { + return _begin; + } + constexpr inline auto + end() const + { + return _end; + } + + const HookPtr * _begin {}; + const HookPtr * _end {}; }; template<typename T, std::size_t N> class HooksImpl : public Hooks<T> { @@ -79,21 +135,12 @@ namespace Slicer { 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 + inline constexpr HooksImpl(Arr<N> a) : arr(std::move(a)) { - return arr.end(); + Hooks<T>::_begin = arr.begin(); + Hooks<T>::_end = arr.end(); } - private: const Arr<N> arr; }; } diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index ebfd6d9..409a4ed 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -436,7 +436,12 @@ namespace Slicer { ChildRef ModelPartForComplex<T>::GetChildRef(const std::string & name, const HookFilter & flt, bool matchCase) { - return GetChildRefFromRange(hooks().equal_range(name, matchCase), flt); + if (matchCase) { + return GetChildRefFromRange(hooks().equal_range(name), flt); + } + else { + return GetChildRefFromRange(hooks().equal_range_nocase(name), flt); + } } template<typename T> |