source: mainline/uspace/lib/cpp/include/internal/rbtree.hpp@ be9eb15

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since be9eb15 was be9eb15, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: added find, some contructors and assignment operators and reverse iterator support to rbtree

  • Property mode set to 100644
File size: 11.4 KB
RevLine 
[4d65515]1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_INTERNAL_RBTREE
30#define LIBCPP_INTERNAL_RBTREE
31
32#include <internal/key_extractors.hpp>
33#include <internal/rbtree_iterators.hpp>
34#include <internal/rbtree_node.hpp>
35#include <internal/rbtree_policies.hpp>
36
37namespace std::aux
38{
39 template<
40 class Value, class Key, class KeyExtractor,
41 class KeyComp, class Alloc, class Size,
42 class Iterator, class ConstIterator,
43 class Policy
44 >
45 class rbtree
46 {
47 public:
48 using value_type = Value;
49 using key_type = Key;
50 using size_type = Size;
51 using allocator_type = Alloc;
52 using key_compare = KeyComp;
53 using key_extract = KeyExtractor;
54
55 using iterator = Iterator;
56 using const_iterator = ConstIterator;
57
[be9eb15]58 using reverse_iterator = std::reverse_iterator<iterator>;
59 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
60
[4d65515]61 using node_type = rbtree_node<value_type>;
62
63 rbtree(const key_compare& kcmp = key_compare{})
64 : root_{nullptr}, size_{}, key_compare_{},
65 key_extractor_{}
66 { /* DUMMY BODY */ }
67
[be9eb15]68 rbtree(const rbtree& other); // TODO:
69
70 rbtree(rbtree&& other)
71 : root_{other.root_}, size_{other.size_},
72 key_compare_{move(other.key_compare_)},
73 key_extractor_{move(other.key_extractor_)}
74 {
75 other.root_ = nullptr;
76 other.size_ = size_type{};
77 }
78
79 rbtree& operator=(const rbtree& other)
80 {
81 auto tmp{other};
82 tmp.swap(*this);
[4d65515]83
[be9eb15]84 return *this;
85 }
[4d65515]86
[be9eb15]87 rbtree& operator=(rbtree&& other)
88 {
89 rbtree tmp{move(other)};
90 tmp.swap(*this);
[4d65515]91
[be9eb15]92 return *this;
93 }
[4d65515]94
95 bool empty() const noexcept
96 {
97 return size_;
98 }
99
100 size_type size() const noexcept
101 {
102 return size_;
103 }
104
105 size_type max_size(allocator_type& alloc)
106 {
107 return allocator_traits<allocator_type>::max_size(alloc);
108 }
109
110 iterator begin()
111 {
112 return iterator{find_smallest_(), false};
113 }
114
115 const_iterator begin() const
116 {
117 return cbegin();
118 }
119
120 iterator end()
121 {
122 return iterator{find_largest_(), true};
123 }
124
125 const_iterator end() const
126 {
127 return cend();
128 }
129
[be9eb15]130 reverse_iterator rbegin()
131 {
132 return make_reverse_iterator(end());
133 }
134
135 const_reverse_iterator rbegin() const
136 {
137 return make_reverse_iterator(cend());
138 }
139
140 reverse_iterator rend()
141 {
142 return make_reverse_iterator(begin());
143 }
144
145 const_reverse_iterator rend() const
146 {
147 return make_reverse_iterator(cbegin());
148 }
149
[4d65515]150 const_iterator cbegin() const
151 {
152 return const_iterator{find_smallest_(), false};
153 }
154
155 const_iterator cend() const
156 {
157 return const_iterator{find_largest_(), true};
158 }
159
[be9eb15]160 const_reverse_iterator crbegin() const
161 {
162 return make_reverse_iterator(cend());
163 }
164
165 const_reverse_iterator crend() const
166 {
167 return make_reverse_iterator(cbegin());
168 }
169
[4d65515]170 template<class... Args>
171 pair<iterator, bool> emplace(Args&&... args)
172 {
173 auto ret = Policy::emplace(*this, forward<Args>(args)...);
174
175 return ret;
176 }
177
178 pair<iterator, bool> insert(const value_type& val)
179 {
180 auto ret = Policy::insert(*this, val);
181 if (!ret.second)
182 return ret;
183
184 repair_after_insert_(ret.first.node());
185 update_root_(ret.first.node());
186
187 return ret;
188 }
189
190 pair<iterator, bool> insert(value_type&& val)
191 {
192 auto ret = Policy::insert(*this, forward<value_type>(val));
193 if (!ret.second)
194 return ret;
195
196 repair_after_insert_(ret.first.node());
197 update_root_(ret.first.node());
198
199 return ret;
200 }
201
202 size_type erase(const key_type& key)
203 {
204 auto ret = Policy::erase(*this, key);
205 if (ret == 0)
206 return ret;
207 // TODO: problem - we don't have a node ptr
208 // solution: return a pair<size_type, node_type*>
209
210 return ret;
211 }
212
213 iterator erase(const_iterator it)
214 {
215 // TODO: implement
216 }
217
218 void clear() noexcept
219 {
220 if (root_)
221 {
222 delete root_;
223 root_ = nullptr;
224 size_ = size_type{};
225 }
226 }
227
228 void swap(rbtree& other)
229 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
230 noexcept(swap(declval<KeyComp&>(), declval<KeyComp&>())))
231 {
232 std::swap(root_, other.root_);
233 std::swap(size_, other.size_);
234 std::swap(key_compare_, other.key_compare_);
235 std::swap(key_extractor_, other.key_extractor_);
236 }
237
238 key_compare key_comp() const
239 {
240 return key_compare_;
241 }
242
243 iterator find(const key_type& key)
244 {
[be9eb15]245 auto node = find_(key);
246 if (node)
247 return iterator{node, false};
248 else
249 return end();
[4d65515]250 }
251
[be9eb15]252 const_iterator find(const key_type& key) const
[4d65515]253 {
[be9eb15]254 auto node = find_(key);
255 if (node)
256 return const_iterator{node, false};
257 else
258 return end();
[4d65515]259 }
260
261 size_type count(const key_type& key) const
262 {
263 return Policy::count(*this, key);
264 }
265
266 iterator upper_bound(const key_type& key)
267 {
268 return Policy::upper_bound(*this, key);
269 }
270
271 const_iterator upper_bound(const key_type& key) const
272 {
273 return Policy::upper_bound_const(*this, key);
274 }
275
276 iterator lower_bound(const key_type& key)
277 {
278 return Policy::lower_bound(*this, key);
279 }
280
281 const_iterator lower_bound(const key_type& key) const
282 {
283 return Policy::lower_bound_const(*this, key);
284 }
285
286 pair<iterator, iterator> equal_range(const key_type& key)
287 {
288 return Policy::equal_range(*this, key);
289 }
290
291 pair<const_iterator, const_iterator> equal_range(const key_type& key) const
292 {
293 return Policy::equal_range_const(*this, key);
294 }
295
296 bool is_eq_to(const rbtree& other) const
297 {
298 // TODO: implement
299 return false;
300 }
301
302 const key_type& get_key(const value_type& val) const
303 {
304 return key_extractor_(val);
305 }
306
307 bool keys_comp(const key_type& key, const value_type& val) const
308 {
309 return key_compare_(key, key_extractor_(val));
310 }
311
312 node_type* find_parent_for_insertion(const value_type& val) const
313 {
314 auto current = root_;
315 auto parent = current;
316
317 while (current)
318 {
319 parent = current;
320 if (key_compare_(key_extractor_(val), key_extractor_(current->value)))
321 current = current->left;
322 else
323 current = current->right;
324 }
325
326 return parent;
327 }
328
329 private:
330 node_type* root_;
331 size_type size_;
332 key_compare key_compare_;
333 key_extract key_extractor_;
334
[be9eb15]335 node_type* find_(const key_type& key) const
336 {
337 auto current = root_;
338 while (current != nullptr)
339 {
340 if (key_compare_(key, key_extractor_(current->value)))
341 current = current->left;
342 else if (key == key_extractor_(current->value))
343 return current;
344 else
345 current = current->right;
346 }
347
348 return nullptr;
349 }
350
[4d65515]351 node_type* find_smallest_() const
352 {
353 if (root_)
354 return root_->find_smallest();
355 else
356 return nullptr;
357 }
358
359 node_type* find_largest_() const
360 {
361 if (root_)
362 return root_->find_largest();
363 else
364 return nullptr;
365 }
366
367 void update_root_(node_type* node)
368 {
369 if (!node)
370 return;
371
372 root_ = node;
373 while (root_->parent)
374 root_ = root_->parent;
375 }
376
377 void repair_after_insert_(node_type* node)
378 {
379 // TODO: implement
380 }
381
[be9eb15]382 void repair_after_erase_(node_type* node)
383 {
384 // TODO: implement
385 }
386
[4d65515]387 friend Policy;
388 };
389}
390
391#endif
Note: See TracBrowser for help on using the repository browser.