Loading...
Searching...
No Matches
tnchain.inl
1#pragma once
2
4#include "core/builtin/container/native/tnmap.inl"
5
6namespace by {
7
8#define TEMPL template <typename K, typename V, typename defaultContainer>
9#define ME tnchain<K, V, defaultContainer>
10#define SUPER typename ME::super
11
12 TEMPL
13 ME::tnchain(): _map(new defaultContainer()) {}
14
15 TEMPL
16 ME::tnchain(const super& arr): _map(arr) {}
17
18 TEMPL
19 ME::tnchain(const super& org, const me& next): _map(org) { link(next); }
20
21 TEMPL
22 ME::tnchain(std::initializer_list<std::pair<K, V*>> elems) {
23 for(const auto& e: elems)
24 _map->add(e.first, *e.second);
25 }
26
27 TEMPL
28 nbool ME::in(const K& key) const {
29 nbool ret = false;
30 this->each([&](const K& elemKey, const V&) { return ret = elemKey != key; });
31 return !ret;
32 }
33
34 TEMPL
35 ncnt ME::len() const {
36 ncnt len = 0;
37 this->each([&](const K&, const V&) { return len++, true; });
38 return len;
39 }
40
41 TEMPL
42 ncnt ME::chainLen() const {
43 ncnt len = 0;
44 for(const me* e = this; e; e = e->getNext())
45 len++;
46 return len;
47 }
48
49 TEMPL
50 V* ME::get(const K& key) {
51 V* ret = nullptr;
52 this->each([&](const K& elemKey, V& val) {
53 WHEN(elemKey != key) .ret(true);
54 ret = &val;
55 return false;
56 });
57 return ret;
58 }
59
60 TEMPL
61 void ME::_getAll(const K& key, narr& tray) const {
62 this->each([&](const K& elemKey, const V& val) {
63 if(elemKey == key) tray.add(val);
64 return true;
65 });
66 }
67
68 TEMPL
69 nbool ME::add(const K& key, const V& new1) { return getContainer().add(key, new1); }
70
71 TEMPL
72 nbool ME::del(const K& key) {
73 nbool ret = true;
74 for(me* e = this; e; e = e->getNext())
75 if(!e->getContainer().del(key)) ret = false;
76 return ret;
77 }
78
79 TEMPL
80 nbool ME::del(const iter& at) {
81 const me* owner = (const me*) at.getContainer();
82 for(me* e = this; e; e = e->getNext()) {
83 if(e != owner) continue;
84 return e->getContainer().del(_getInnerIter(at));
85 }
86 return false;
87 }
88
89 TEMPL
90 nbool ME::del(const iter& from, const iter& last) {
91 WHEN(from.isReversed() != last.isReversed()) .exErr(ITERATORS_ARENT_SAME_DIRECTION).ret(false);
92 const me* fromChain = (const me*) from.getContainer();
93 const me& lastChain =
94 (const me*) last.getContainer() OR.warn("iterator 'end' owned by null chain instance.").ret(false);
95 const me* endChain = lastChain.getNext(); // now, endChain can be null but it's okay.
96
97 me* e = (me*) fromChain;
98 nbool ret = true;
99 do {
100 super& eArr = e->getContainer();
101 iter innerBegin = _getInnerBeginOfChain(*e, *fromChain, from),
102 innerLast = _getInnerEndOfChain(*e, lastChain, last);
103 ret = eArr.del(innerBegin, innerLast) ? ret : false;
104 e = e->getNext();
105 } while(e != endChain);
106
107 return ret;
108 }
109
110 TEMPL
111 nbool ME::link(const iter& portion) {
112 ME& next = (ME*) (portion TO(getContainer())) OR.ret(false);
113 WHEN(&next == this) .warn("recursive link detected for portion(%s).", (void*) &next).ret(false);
114
115 _next = portion;
116 // this's not reversed to portion iterator:
117 // the direction of the `chain iter` is determined by the perspective from which the chain
118 // is viewed.
119 // if you are looking at a chain from a reversed viewpoint and you link a new
120 // chain to that chain from a normal viewpoint, the viewpoint from which the new chain looks
121 // at the reversed chain must be reversed.
122 //
123 // e.g.
124 // A ----reversed--> B ----normal--> C
125 // <--normal----- <--reversed--
126 //
127 // therefore, the value of `next._prev.isReversed()` must be the same as the value of
128 // `prev._next.isReversed()`. This ensures that advancing iters on both ends will produce
129 // the same result.
130 me* prev = getPrev();
131 next._prev = _rendOfThisChain(prev ? prev->_next.isReversed() : false);
132 return true;
133 }
134
135 TEMPL
136 nbool ME::link(const ME& new1) { return link(new1.begin()); }
137
138 TEMPL
139 nbool ME::unlink() {
140 ME* next = (ME*) (_next TO(getContainer()));
141 if(next) next->_prev.rel();
142 _next.rel();
143 return true;
144 }
145
146 TEMPL
147 ME* ME::getTail() {
148 me* ret = this;
149 while(ret && ret->_next.getContainer())
150 ret = (me*) ret->_next.getContainer();
151 return ret;
152 }
153
154 TEMPL
155 void ME::onCloneDeep(const clonable& from) {
156 const me& rhs = (const me&) from;
157 _map.bind(*(super*) rhs._map->cloneDeep());
158
159 me* e = this;
160 const me* next = rhs.getNext();
161 while(next) {
162 e->link(*new me(*(super*) next->getContainer().cloneDeep()));
163 e = e->getNext();
164 next = next->getNext();
165 }
166 }
167
168 TEMPL
169 ME* ME::wrap(const super& toShallowWrap) { return wrap<ME>(toShallowWrap); }
170
171 TEMPL
172 ME* ME::cloneChain(const super* until) const {
173 tstr<me> e(getNext());
174 ME* ret = new ME(this->getContainer());
175 ME* retElem = ret;
176 while(e) {
177 tstr<me> new1(new ME(e->getContainer()));
178 retElem->link(*new1);
179 retElem = new1.get();
180
181 if(&e->getContainer() == until) break;
182 e.bind((me*) e->_next.getContainer());
183 }
184
185 return ret;
186 }
187
188 TEMPL
189 ME* ME::cloneChain(const me* until) const {
190 return cloneChain(until ? &until->getContainer() : (const super*) nullptr);
191 }
192
193 TEMPL
194 ME* ME::cloneChain() const { return cloneChain((const super*) nullptr); }
195
196 TEMPL
197 void ME::rel() {
198 for(tstr<me> e(this); e; e.bind(e->getNext()))
199 e->getContainer().rel();
200 }
201
202 TEMPL
203 tnbicontainer<K, V>& ME::getContainer() { return *_map; }
204
205 TEMPL
206 const SUPER& ME::getContainer() const { return *_map; }
207
208 TEMPL
209 ME* ME::getNext() { return (ME*) _next.getContainer(); }
210
211 TEMPL
212 ME* ME::getPrev() { return (ME*) _prev.getContainer(); }
213
214 TEMPL
215 typename ME::iteration* ME::_onMakeIteration(const K* key, nbool isReversed, ncnt step, nbool isBoundary) const {
216 me* unconst = const_cast<me*>(this);
217 auto* ret = new nchainIteration(isReversed ? unconst->getTail() : unconst, key, isReversed, isBoundary, true);
218 ret->next(step);
219 ret->_setBoundary(isBoundary);
220 return ret;
221 }
222
223 TEMPL
224 typename ME::iter* ME::_getInnerIter(const iter& outer) {
225 nchainIteration& cast = (nchainIteration*) outer._iteration.get() OR.ret(nullptr);
226 return &cast._iter;
227 }
228
229 TEMPL
230 typename ME::iter ME::_getInnerBeginOfChain(me& it, const me& fromChain, const iter& from) {
231 me* prev = it.getPrev();
232 nbool isReversed = prev ? prev->_next.isReversed() : false;
233 WHEN(&it != &fromChain) .ret(it.getContainer().begin());
234 WHEN(isReversed) .ret(it.getContainer().begin());
235
236 auto ret = _getInnerIter(from) OR.ret(this->end());
237 return ret;
238 }
239
240 TEMPL
241 typename ME::iter ME::_getInnerEndOfChain(me& it, const me& lastChain, const iter& last) {
242 me* prev = it.getPrev();
243 nbool isReversed = !prev ? false : prev->_next.isReversed();
244 WHEN(&it != &lastChain) .ret(it.getContainer().end());
245 WHEN(isReversed) .ret(it.getContainer().end());
246
247 auto ret = _getInnerIter(last) OR.ret(this->end());
248 return ret;
249 }
250
251 TEMPL
252 typename ME::iter ME::_rendOfThisChain(nbool isReversed) {
253 return iter(new nchainIteration(this, nullptr, isReversed, true, false));
254 }
255
256#undef ME
257#undef TEMPL
258#undef SUPER
259} // namespace by
Bidirectional iterator for key-value containers.
Definition biter.hpp:10
Chain iteration implementation.
Definition nchainIteration.hpp:8
ncnt next(ncnt step) override
Definition nchainIteration.hpp:41
to Top