diff --git a/octa/internal/hashtable.h b/octa/internal/hashtable.h index 3cdc22a..840f3f1 100644 --- a/octa/internal/hashtable.h +++ b/octa/internal/hashtable.h @@ -15,7 +15,70 @@ namespace octa { -template struct HashRange; +namespace detail { + template + struct HashChain { + T value; + HashChain *next; + }; +} + +template +struct HashRange: octa::InputRange, octa::ForwardRangeTag, T> { +private: + using Chain = octa::detail::HashChain; + + Chain **p_chains; + Chain *p_node; + octa::Size p_num; + + void advance() { + while (p_num > 0 && !p_chains[0]) { + --p_num; + ++p_chains; + } + if (p_num > 0) { + p_node = p_chains[0]; + --p_num; + ++p_chains; + } else { + p_node = nullptr; + } + } +public: + HashRange(): p_chains(), p_num(0) {} + HashRange(Chain **ch, octa::Size n): p_chains(ch), p_num(n) { + advance(); + } + HashRange(const HashRange &v): p_chains(v.p_chains), p_node(v.p_node), + p_num(v.p_num) {} + + HashRange &operator=(const HashRange &v) { + p_chains = v.p_chains; + p_node = v.p_node; + p_num = v.p_num; + return *this; + } + + bool empty() const { return !p_node && p_num <= 0; } + + bool pop_front() { + if (empty()) return false; + if (p_node->next) { + p_node = p_node->next; + return true; + } + p_node = nullptr; + advance(); + return true; + } + + bool equals_front(const HashRange &v) const { + return p_node == v.p_node; + } + + T &front() const { return p_node->value; } +}; namespace detail { template< @@ -29,10 +92,8 @@ namespace detail { > struct Hashtable { static constexpr octa::Size CHUNKSIZE = 64; - struct Chain { - E value; - Chain *next; - }; + using Chain = octa::detail::HashChain; + struct Chunk { Chain chains[CHUNKSIZE]; Chunk *next; @@ -196,66 +257,6 @@ namespace detail { }; } /* namespace detail */ -template -struct HashRange: octa::InputRange, octa::ForwardRangeTag, T> { -private: - struct Chain { - T value; - Chain *next; - }; - - Chain **p_chains; - Chain *p_node; - octa::Size p_num; - - void advance() { - while (p_num > 0 && !p_chains[0]) { - --p_num; - ++p_chains; - } - if (p_num > 0) { - p_node = p_chains[0]; - --p_num; - ++p_chains; - } else { - p_node = nullptr; - } - } -public: - HashRange(): p_chains(), p_num(0) {} - HashRange(void *ch, octa::Size n): p_chains((Chain **)ch), p_num(n) { - advance(); - } - HashRange(const HashRange &v): p_chains(v.p_chains), p_node(v.p_node), - p_num(v.p_num) {} - - HashRange &operator=(const HashRange &v) { - p_chains = v.p_chains; - p_node = v.p_node; - p_num = v.p_num; - return *this; - } - - bool empty() const { return !p_node && p_num <= 0; } - - bool pop_front() { - if (empty()) return false; - if (p_node->next) { - p_node = p_node->next; - return true; - } - p_node = nullptr; - advance(); - return true; - } - - bool equals_front(const HashRange &v) const { - return p_node == v.p_node; - } - - T &front() const { return p_node->value; } -}; - } /* namespace octa */ #endif \ No newline at end of file diff --git a/octa/string.h b/octa/string.h index c34ef88..052b549 100644 --- a/octa/string.h +++ b/octa/string.h @@ -344,7 +344,7 @@ static inline bool operator!=(const char *lhs, const String &rhs) { } template -String concat(const T v, const String &sep, F func) { +String concat(const T &v, const String &sep, F func) { String ret; auto range = octa::each(v); if (range.empty()) return octa::move(ret);