nchainIteration.hpp
Go to the documentation of this file.
1
8 BY(CLASS(nchainIteration, iteration))
9 friend class tnchain;
10
11public:
12 nchainIteration(tnchain* iteratingChain, const K* key, nbool isReversed):
13 me(iteratingChain, key, isReversed, false, true) {}
14
15 nchainIteration(tnchain* iteratingChain, const K* key, nbool isReversed, nbool isBoundary, nbool isAutoAdvance):
16 super(isReversed),
17 _chainIter(iteratingChain),
18 _key(key ? *key : _getDummyKey()),
19 _isDummyKey(!key),
20 _iter(_makeContainerIter(false)),
21 _isBoundary(isBoundary) {
22 if(isAutoAdvance && !_iter) {
23 next(1);
24 _setBoundary(isBoundary);
25 }
26 }
27
28 nbool isEnd() const override {
29 WHEN(_getNextContainer()) .ret(false);
30 return !_iter;
31 }
32
33 void rel() override {
34 _iter.rel();
35 _chainIter.rel();
36 }
37
38 nbool isBoundary() const { return _isBoundary; }
39
40 ncnt next(ncnt step) override { return _step(super::NEXT, step); }
41
42 ncnt prev(ncnt step) override { return _step(super::PREV, step); }
43
44 ncnt stepForward(ncnt step) override { return _step(super::FORWARD, step); }
45
46 ncnt stepBackward(ncnt step) override { return _step(super::BACKWARD, step); }
47
48 using super::getContainer;
49
50 tbicontainable<K, V>* getContainer() override {
51 WHEN(!_chainIter) .ret(nullptr);
52 return _chainIter.get();
53 }
54
55 const K* getKey() const override { return _iter.getKey(); }
56
57 using super::getVal;
58
59 V* getVal() override { return _iter.getVal(); }
60
61 using super::setVal;
62
63 void setVal(const V& new1) override { _iter.setVal(new1); }
64
65protected:
66 nbool _onSame(const typeProvidable& rhs) const override {
67 const me& cast = (const me&) rhs;
68 return (isEnd() && cast.isEnd()) || _iter == cast._iter;
69 }
70
71private:
72 ncnt _step(typename super::iterationType type, ncnt step) {
73 ncnt remain = step;
74
75 // if _chainIter was invalidated then _iter too.
76 while(remain > 0) {
77 if(!_isSubIterEndAtMiddle()) remain -= _iterate(type, remain);
78 if(remain <= 0) break;
79
80 // _iter moved to 'End' state now.
81 if(isEnd()) break;
82 _updateIter();
83 if(_iter) remain--;
84 }
85
86 return step - remain;
87 }
88
89 ncnt _iterate(typename super::iterationType type, ncnt step) {
90 _isBoundary = false;
91 switch(type) {
92 case super::FORWARD: return _iter.stepForward(step);
93 case super::BACKWARD: return _iter.stepBackward(step);
94 case super::PREV: return _iter.prev(step);
95 default:
96 case super::NEXT: return _iter.next(step);
97 }
98 }
99
100 const iter* _getNextIter() const {
101 WHEN(!_chainIter) .ret(nullptr);
102 return this->isReversed() ? &_chainIter->_prev : &_chainIter->_next;
103 }
104
105 const tnchain* _getNextContainer() const {
106 WHEN(!_chainIter) .ret(nullptr);
107 return this->isReversed() ? _chainIter->getPrev() : _chainIter->getNext();
108 }
109
110 void _updateIter() {
111 const iter& nextIter = _getNextIter() OR_DO {
112 _chainIter.rel();
113 _iter.rel();
114 return;
115 };
116
117 // proceed to next chain:
118 _chainIter.bind(_castChain(nextIter));
119 // init container iter:
120 me& nextIteration = _castIteration(nextIter) OR.ret();
121 _iter = nextIteration._isBoundary ? _makeContainerIter(nextIteration.isReversed()) : nextIteration._iter;
122 if(!_isDummyKey && (!_iter.getKey() || _key != *_iter.getKey())) _iter.next(1);
123 }
124
131 iter _makeContainerIter(nbool isReversed) const {
132 return isReversed ? (this->isReversed() ? _chainIter->_map->begin(_getFindingKey()) :
133 _chainIter->_map->rbegin(_getFindingKey())) :
134 (this->isReversed() ? _chainIter->_map->rbegin(_getFindingKey()) :
135 _chainIter->_map->begin(_getFindingKey()));
136 }
137
138 void _setBoundary(nbool new1) { _isBoundary = new1; }
139
140 me* _castIteration(const iter& e) { return (me*) (e._iteration.get()); }
141 const me* _castIteration(const iter& e) const BY_CONST_FUNC(_castIteration(e))
142
143 tnchain* _castChain(const iter& e) { return (tnchain*) e.getContainer(); }
144
145 tnchain* _castChain(const iter* it) BY_SIDE_FUNC(_castChain);
146
147 const tnchain* _castChain(const iter& e) const BY_CONST_FUNC(_castChain(e));
148 const tnchain* _castChain(const iter* e) const BY_CONST_FUNC(_castChain(e));
149
150 // check whether sub iter has been reached to reversed non-boundary end iter.
151 // e.g.
152 // chain A has {1, 2, 3} elements.
153 // chain B has {4, 5, 6} elements.
154 // when A linked B from the 2nd element, chains will be follow:
155 // {1, 2, 3, 5, 6}
156 // in this case, what if user wants to iterate in reversed?
157 // then elements to be out should be:
158 // {6, 5, 3, 2, 1}
159 // our sub iterate can detect end of the sub container inside of its logic when
160 // you call `next()` in `_iterate()`.
161 // however, in above example, after sub iter reached to `5`, it's not possible for it
162 // to detect the end of iteration of the sub container. because actually there is one
163 // more element to iterate, `4`.
164 // so only who is capable of knowing that reversed iteration reached to the end for
165 // reversed iterator is need to be done by `nchainIteration` class.
166 // and this func is for that.
167 nbool _isSubIterEndAtMiddle()
168 const { // if this iter is not reversed, there is no case you have the `end at middle`.
169 WHEN(!this->isReversed()) .ret(false);
170
171 // if there is no prev chain, I'll just regard it as `end()` soon.
172 const tnchain& prev = _castChain(_getNextIter()) OR.ret(false);
173 const me& prevNext = _castIteration(prev._next) OR.ret(false);
174 WHEN(prevNext.isBoundary()) .ret(false);
175 return _iter == prevNext._iter;
176 }
177
178 static const K& _getDummyKey() {
179 static K inner;
180 return inner;
181 }
182
183 const K* _getFindingKey() const { return _isDummyKey ? nullptr : &_key; }
184
185private:
188 tstr<tnchain> _chainIter;
189 K _key;
190 nbool _isDummyKey;
192 iter _iter;
193
214 nbool _isBoundary;
215};
Bidirectional iterator for key-value containers.
Definition: biter.hpp:9
ncnt next(ncnt step) override
void rel() override
once rel(), an iterator enters a state where it can never be reused again.
Definition: biteration.hpp:5
Definition: nchainIteration.hpp:7
ncnt next(ncnt step) override
Definition: nchainIteration.hpp:40