|
|
@@ -28,12 +28,61 @@ namespace detail {
|
|
|
return { tr.local_rbegin(), tr.local_rend() };
|
|
|
}
|
|
|
};
|
|
|
+
|
|
|
+ template <typename Trie, typename V, typename Iter>
|
|
|
+ class trie_iterator_base {
|
|
|
+ protected:
|
|
|
+ using impl_t = ::iterator::end_aware_iterator<Iter>;
|
|
|
+ public:
|
|
|
+ trie_iterator_base() : done{true} {}
|
|
|
+ trie_iterator_base(Trie * tr) { stk.push(tr); }
|
|
|
+ V & operator*() const { return *stk.top(); }
|
|
|
+ protected:
|
|
|
+ bool poping_empty() {
|
|
|
+ if (iters.top().done()) {
|
|
|
+ stk.pop();
|
|
|
+ iters.pop();
|
|
|
+ keys.pop_back();
|
|
|
+ return !iters.empty();
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ void assign() {
|
|
|
+ if (!iters.empty()) {
|
|
|
+ stk.top() = iters.top()->second.get();
|
|
|
+ keys.back() = iters.top()->first;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ bool can_recurse() { return !next().done(); }
|
|
|
+ void recurse() {
|
|
|
+ auto it = next();
|
|
|
+ iters.push(it);
|
|
|
+ keys.push_back(it->first);
|
|
|
+ stk.push(it->second.get());
|
|
|
+ }
|
|
|
+ impl_t next() { return detail::trie_iterator_next<Iter>()(*stk.top()); }
|
|
|
+ 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) {
|
|
|
+ if ( lhs.done && rhs.done ) return true;
|
|
|
+ else if (lhs.keys != rhs.keys) return false;
|
|
|
+ else if ( lhs.done != rhs.done ) return false;
|
|
|
+ else return *lhs == *rhs;
|
|
|
+ }
|
|
|
+ protected:
|
|
|
+ friend Trie;
|
|
|
+ std::stack<Trie *> stk;
|
|
|
+ std::list<typename Trie::key_type> keys;
|
|
|
+ std::stack<impl_t> iters;
|
|
|
+ bool done{false};
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
template <typename Trie, typename V, typename Iter>
|
|
|
-class trie_iterator {
|
|
|
+class trie_iterator : public detail::trie_iterator_base<Trie, V, Iter> {
|
|
|
private:
|
|
|
- using impl_t = ::iterator::end_aware_iterator<Iter>;
|
|
|
+ using super = detail::trie_iterator_base<Trie, V, Iter>;
|
|
|
public:
|
|
|
using value_type = V;
|
|
|
using reference = value_type &;
|
|
|
@@ -41,60 +90,30 @@ public:
|
|
|
using difference_type = std::ptrdiff_t;
|
|
|
using iterator_category = std::forward_iterator_tag;
|
|
|
public:
|
|
|
- trie_iterator() : done{true} {}
|
|
|
- trie_iterator(Trie * tr) { stk.push(tr); }
|
|
|
- reference operator*() const { return *stk.top(); }
|
|
|
+ trie_iterator() : super() {}
|
|
|
+ trie_iterator(Trie * tr) : super(tr) { }
|
|
|
trie_iterator & operator++() {
|
|
|
- if (done) return *this;
|
|
|
- if ( iters.empty() || can_recurse() ) { recurse(); }
|
|
|
+ if (super::done) return *this;
|
|
|
+ if ( super::iters.empty() || super::can_recurse() ) { super::recurse(); }
|
|
|
else { advance(); }
|
|
|
return *this;
|
|
|
}
|
|
|
private:
|
|
|
- bool can_recurse() { return !next().done(); }
|
|
|
- void recurse() {
|
|
|
- auto it = next();
|
|
|
- iters.push(it);
|
|
|
- keys.push_back(it->first);
|
|
|
- stk.push(it->second.get());
|
|
|
- }
|
|
|
- impl_t next() { return detail::trie_iterator_next<Iter>()(*stk.top()); }
|
|
|
void advance() {
|
|
|
- ++iters.top();
|
|
|
- while (iters.top().done()) {
|
|
|
- stk.pop();
|
|
|
- iters.pop();
|
|
|
- keys.pop_back();
|
|
|
- if ( iters.empty() ) break;
|
|
|
- ++iters.top();
|
|
|
+ ++super::iters.top();
|
|
|
+ while (super::poping_empty()) {
|
|
|
+ ++super::iters.top();
|
|
|
}
|
|
|
- if (!iters.empty()) {
|
|
|
- stk.top() = iters.top()->second.get();
|
|
|
- keys.back() = iters.top()->first;
|
|
|
- } else {
|
|
|
- done = true;
|
|
|
- }
|
|
|
- }
|
|
|
- friend bool operator!=(trie_iterator const & lhs, trie_iterator const & rhs) {
|
|
|
- return !(lhs == rhs);
|
|
|
- }
|
|
|
- friend bool operator==(trie_iterator const & lhs, trie_iterator const & rhs) {
|
|
|
- if ( lhs.done && rhs.done ) return true;
|
|
|
- else if (lhs.keys != rhs.keys) return false;
|
|
|
- else if ( lhs.done != rhs.done ) return false;
|
|
|
- else return *lhs == *rhs;
|
|
|
+ super::assign();
|
|
|
+ super::done = super::iters.empty();
|
|
|
}
|
|
|
friend Trie;
|
|
|
- std::stack<Trie *> stk;
|
|
|
- std::list<typename Trie::key_type> keys;
|
|
|
- std::stack<impl_t> iters;
|
|
|
- bool done{false};
|
|
|
};
|
|
|
|
|
|
template <typename Trie, typename V, typename Iter>
|
|
|
-class trie_reverse_iterator {
|
|
|
+class trie_reverse_iterator : public detail::trie_iterator_base<Trie, V, Iter> {
|
|
|
private:
|
|
|
- using impl_t = ::iterator::end_aware_iterator<Iter>;
|
|
|
+ using super = detail::trie_iterator_base<Trie, V, Iter>;
|
|
|
public:
|
|
|
using value_type = V;
|
|
|
using reference = value_type &;
|
|
|
@@ -102,59 +121,28 @@ public:
|
|
|
using difference_type = std::ptrdiff_t;
|
|
|
using iterator_category = std::forward_iterator_tag;
|
|
|
public:
|
|
|
- trie_reverse_iterator() : done{true} {}
|
|
|
- trie_reverse_iterator(Trie * tr) {
|
|
|
- stk.push(tr);
|
|
|
- if (can_recurse()) recurse();
|
|
|
+ trie_reverse_iterator() : super() {}
|
|
|
+ trie_reverse_iterator(Trie * tr) : super(tr) {
|
|
|
+ if (super::can_recurse()) recurse();
|
|
|
}
|
|
|
- reference operator*() const { return *stk.top(); }
|
|
|
trie_reverse_iterator & operator++() {
|
|
|
- if (done || iters.empty()) { done = true; return *this; }
|
|
|
- advance();
|
|
|
+ if (super::done || super::iters.empty()) { super::done = true; }
|
|
|
+ else { advance(); }
|
|
|
return *this;
|
|
|
}
|
|
|
private:
|
|
|
- bool can_recurse() { return !next().done(); }
|
|
|
void recurse() {
|
|
|
- do {
|
|
|
- auto it = next();
|
|
|
- iters.push(it);
|
|
|
- keys.push_back(it->first);
|
|
|
- stk.push(it->second.get());
|
|
|
- } while ( can_recurse() );
|
|
|
+ do { super::recurse(); } while ( super::can_recurse() );
|
|
|
}
|
|
|
- impl_t next() { return detail::trie_iterator_next<Iter>()(*stk.top()); }
|
|
|
void advance() {
|
|
|
- ++iters.top();
|
|
|
- if (iters.top().done()) {
|
|
|
- while (iters.top().done()) {
|
|
|
- stk.pop();
|
|
|
- iters.pop();
|
|
|
- keys.pop_back();
|
|
|
- if ( iters.empty() ) break;
|
|
|
- }
|
|
|
- if (!iters.empty()) {
|
|
|
- stk.top() = iters.top()->second.get();
|
|
|
- keys.back() = iters.top()->first;
|
|
|
- }
|
|
|
+ ++super::iters.top();
|
|
|
+ if (super::iters.top().done()) {
|
|
|
+ while (super::poping_empty());
|
|
|
+ super::assign();
|
|
|
} else {
|
|
|
- stk.top() = iters.top()->second.get();
|
|
|
- keys.back() = iters.top()->first;
|
|
|
- if (can_recurse()) recurse();
|
|
|
+ super::assign();
|
|
|
+ if (super::can_recurse()) recurse();
|
|
|
}
|
|
|
}
|
|
|
- friend bool operator!=(trie_reverse_iterator const & lhs, trie_reverse_iterator const & rhs) {
|
|
|
- return !(lhs == rhs);
|
|
|
- }
|
|
|
- friend bool operator==(trie_reverse_iterator const & lhs, trie_reverse_iterator const & rhs) {
|
|
|
- if ( lhs.done && rhs.done ) return true;
|
|
|
- else if (lhs.keys != rhs.keys) return false;
|
|
|
- else if ( lhs.done != rhs.done ) return false;
|
|
|
- else return *lhs == *rhs;
|
|
|
- }
|
|
|
friend Trie;
|
|
|
- std::stack<Trie *> stk;
|
|
|
- std::list<typename Trie::key_type> keys;
|
|
|
- std::stack<impl_t> iters;
|
|
|
- bool done{false};
|
|
|
};
|