|
|
@@ -9,9 +9,10 @@
|
|
|
|
|
|
#include "trie.hpp"
|
|
|
|
|
|
-#include "iterator/end_aware_iterator.hpp"
|
|
|
-#include <list>
|
|
|
#include <stack>
|
|
|
+#include <vector>
|
|
|
+
|
|
|
+#include "iterator/end_aware_iterator.hpp"
|
|
|
|
|
|
namespace detail {
|
|
|
template <typename Iter> struct trie_iterator_next {
|
|
|
@@ -30,13 +31,11 @@ namespace detail {
|
|
|
};
|
|
|
|
|
|
template <typename Trie, typename Iter> class trie_iterator_base {
|
|
|
- protected:
|
|
|
- using helper = trie_iterator_next<Iter>;
|
|
|
- using impl_t = typename helper::iter_t;
|
|
|
- std::stack<Trie *> stk;
|
|
|
- std::list<typename Trie::key_type> keys;
|
|
|
- std::stack<impl_t> iters;
|
|
|
- bool done{false};
|
|
|
+ private:
|
|
|
+ std::stack<Trie *> parent_trie_;
|
|
|
+ std::vector<typename Trie::key_type> keys_;
|
|
|
+ std::stack<iterator::end_aware_iterator<Iter>> iterators_;
|
|
|
+ bool done_{false};
|
|
|
|
|
|
public:
|
|
|
using reference = decltype(std::declval<Trie>().value());
|
|
|
@@ -46,16 +45,18 @@ namespace detail {
|
|
|
using iterator_category = std::forward_iterator_tag;
|
|
|
|
|
|
public:
|
|
|
- trie_iterator_base() : done{true} {}
|
|
|
- trie_iterator_base(Trie * tr) { stk.push(tr); }
|
|
|
+ trie_iterator_base() : done_{true} {}
|
|
|
+ trie_iterator_base(Trie * tr) { parent_trie_.push(tr); }
|
|
|
auto operator*() const -> reference { return root(); }
|
|
|
auto operator-> () const -> pointer { return std::addressof(operator*()); }
|
|
|
+
|
|
|
Trie & root() const {
|
|
|
- if (stk.empty()) {
|
|
|
+ if (parent_trie_.empty()) {
|
|
|
throw std::runtime_error("Dereferencing invalid iterator");
|
|
|
}
|
|
|
- return *stk.top();
|
|
|
+ return *parent_trie_.top();
|
|
|
}
|
|
|
+
|
|
|
trie_iterator_base parent() const {
|
|
|
trie_iterator_base tmp{*this};
|
|
|
tmp.pop();
|
|
|
@@ -63,42 +64,58 @@ namespace detail {
|
|
|
}
|
|
|
|
|
|
protected:
|
|
|
- void push(impl_t it) {
|
|
|
+ iterator::end_aware_iterator<Iter> & current() { return iterators_.top(); }
|
|
|
+ bool empty() const { return iterators_.empty(); }
|
|
|
+ void done(bool new_done) { done_ = new_done; }
|
|
|
+ bool done() const { return done_; }
|
|
|
+
|
|
|
+ void push(iterator::end_aware_iterator<Iter> it) {
|
|
|
if (it.done()) {
|
|
|
- done = true;
|
|
|
+ done_ = true;
|
|
|
return;
|
|
|
}
|
|
|
- iters.push(it);
|
|
|
- keys.push_back(it->first);
|
|
|
- stk.push(it->second.get());
|
|
|
+ iterators_.push(it);
|
|
|
+ keys_.push_back(it->first);
|
|
|
+ parent_trie_.push(it->second.get());
|
|
|
}
|
|
|
+
|
|
|
void pop() {
|
|
|
- stk.pop();
|
|
|
- iters.pop();
|
|
|
- keys.pop_back();
|
|
|
+ parent_trie_.pop();
|
|
|
+ iterators_.pop();
|
|
|
+ keys_.pop_back();
|
|
|
}
|
|
|
+
|
|
|
bool poping_empty() {
|
|
|
- if (!iters.top().done()) { return false; }
|
|
|
+ if (!current().done()) { return false; }
|
|
|
pop();
|
|
|
- return !iters.empty();
|
|
|
+ return !empty();
|
|
|
}
|
|
|
+
|
|
|
void assign() {
|
|
|
- if (iters.empty()) { return; }
|
|
|
- stk.top() = iters.top()->second.get();
|
|
|
- keys.back() = iters.top()->first;
|
|
|
+ if (empty()) { return; }
|
|
|
+ parent_trie_.top() = current()->second.get();
|
|
|
+ keys_.back() = current()->first;
|
|
|
}
|
|
|
+
|
|
|
bool can_recurse() { return !next().done(); }
|
|
|
+
|
|
|
void recurse() { push(next()); }
|
|
|
- impl_t next() { return helper()(root()); }
|
|
|
+
|
|
|
+ iterator::end_aware_iterator<Iter> next() {
|
|
|
+ return trie_iterator_next<Iter>()(root());
|
|
|
+ }
|
|
|
+
|
|
|
friend bool operator!=(trie_iterator_base const & lhs,
|
|
|
trie_iterator_base const & rhs) {
|
|
|
return !(lhs == rhs);
|
|
|
}
|
|
|
+
|
|
|
friend bool operator==(trie_iterator_base const & lhs,
|
|
|
trie_iterator_base const & rhs) {
|
|
|
- return (lhs.done && rhs.done) ||
|
|
|
- (lhs.keys == rhs.keys && lhs.done == rhs.done && *lhs == *rhs);
|
|
|
+ return (lhs.done_ && rhs.done_) ||
|
|
|
+ (lhs.keys_ == rhs.keys_ && lhs.done_ == rhs.done_ && *lhs == *rhs);
|
|
|
}
|
|
|
+
|
|
|
friend Trie;
|
|
|
template <typename Self, typename _Trie, typename KS>
|
|
|
friend Self find_impl(_Trie * tr, KS const & keys);
|
|
|
@@ -114,9 +131,10 @@ public:
|
|
|
trie_iterator() : super() {}
|
|
|
trie_iterator(Trie * tr) : super(tr) {}
|
|
|
trie_iterator(super && take) : super(std::move(take)) {}
|
|
|
+
|
|
|
trie_iterator & operator++() {
|
|
|
- if (super::done) return *this;
|
|
|
- if (super::iters.empty() || super::can_recurse()) {
|
|
|
+ if (super::done()) return *this;
|
|
|
+ if (super::empty() || super::can_recurse()) {
|
|
|
super::recurse();
|
|
|
} else {
|
|
|
advance();
|
|
|
@@ -126,14 +144,13 @@ public:
|
|
|
|
|
|
private:
|
|
|
void advance() {
|
|
|
- ++super::iters.top();
|
|
|
+ ++super::current();
|
|
|
while (super::poping_empty()) {
|
|
|
- ++super::iters.top();
|
|
|
+ ++super::current();
|
|
|
}
|
|
|
super::assign();
|
|
|
- super::done = super::iters.empty();
|
|
|
+ super::done(super::empty());
|
|
|
}
|
|
|
- friend Trie;
|
|
|
};
|
|
|
|
|
|
template <typename Trie, typename Iter>
|
|
|
@@ -146,9 +163,10 @@ public:
|
|
|
trie_reverse_iterator(Trie * tr) : super(tr) {
|
|
|
if (super::can_recurse()) recurse();
|
|
|
}
|
|
|
+
|
|
|
trie_reverse_iterator & operator++() {
|
|
|
- if (super::done || super::iters.empty()) {
|
|
|
- super::done = true;
|
|
|
+ if (super::done() || super::empty()) {
|
|
|
+ super::done(true);
|
|
|
} else {
|
|
|
advance();
|
|
|
}
|
|
|
@@ -161,9 +179,10 @@ private:
|
|
|
super::recurse();
|
|
|
} while (super::can_recurse());
|
|
|
}
|
|
|
+
|
|
|
void advance() {
|
|
|
- ++super::iters.top();
|
|
|
- if (super::iters.top().done()) {
|
|
|
+ ++super::current();
|
|
|
+ if (super::current().done()) {
|
|
|
while (super::poping_empty())
|
|
|
;
|
|
|
super::assign();
|
|
|
@@ -172,5 +191,4 @@ private:
|
|
|
if (super::can_recurse()) recurse();
|
|
|
}
|
|
|
}
|
|
|
- friend Trie;
|
|
|
};
|