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

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

cpp: added a WIP version of a generic red black tree, well, currently a BST

  • Property mode set to 100644
File size: 9.0 KB
Line 
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
58 using node_type = rbtree_node<value_type>;
59
60 rbtree(const key_compare& kcmp = key_compare{})
61 : root_{nullptr}, size_{}, key_compare_{},
62 key_extractor_{}
63 { /* DUMMY BODY */ }
64
65 rbtree(const rbtree& other);
66
67 rbtree(rbtree&& other);
68
69 rbtree& operator=(const rbtree& other);
70
71 rbtree& operator=(rbtree&& other);
72
73 bool empty() const noexcept
74 {
75 return size_;
76 }
77
78 size_type size() const noexcept
79 {
80 return size_;
81 }
82
83 size_type max_size(allocator_type& alloc)
84 {
85 return allocator_traits<allocator_type>::max_size(alloc);
86 }
87
88 iterator begin()
89 {
90 return iterator{find_smallest_(), false};
91 }
92
93 const_iterator begin() const
94 {
95 return cbegin();
96 }
97
98 iterator end()
99 {
100 return iterator{find_largest_(), true};
101 }
102
103 const_iterator end() const
104 {
105 return cend();
106 }
107
108 const_iterator cbegin() const
109 {
110 return const_iterator{find_smallest_(), false};
111 }
112
113 const_iterator cend() const
114 {
115 return const_iterator{find_largest_(), true};
116 }
117
118 template<class... Args>
119 pair<iterator, bool> emplace(Args&&... args)
120 {
121 auto ret = Policy::emplace(*this, forward<Args>(args)...);
122
123 return ret;
124 }
125
126 pair<iterator, bool> insert(const value_type& val)
127 {
128 auto ret = Policy::insert(*this, val);
129 if (!ret.second)
130 return ret;
131
132 repair_after_insert_(ret.first.node());
133 update_root_(ret.first.node());
134
135 return ret;
136 }
137
138 pair<iterator, bool> insert(value_type&& val)
139 {
140 auto ret = Policy::insert(*this, forward<value_type>(val));
141 if (!ret.second)
142 return ret;
143
144 repair_after_insert_(ret.first.node());
145 update_root_(ret.first.node());
146
147 return ret;
148 }
149
150 size_type erase(const key_type& key)
151 {
152 auto ret = Policy::erase(*this, key);
153 if (ret == 0)
154 return ret;
155 // TODO: problem - we don't have a node ptr
156 // solution: return a pair<size_type, node_type*>
157
158 return ret;
159 }
160
161 iterator erase(const_iterator it)
162 {
163 // TODO: implement
164 }
165
166 void clear() noexcept
167 {
168 if (root_)
169 {
170 delete root_;
171 root_ = nullptr;
172 size_ = size_type{};
173 }
174 }
175
176 void swap(rbtree& other)
177 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
178 noexcept(swap(declval<KeyComp&>(), declval<KeyComp&>())))
179 {
180 std::swap(root_, other.root_);
181 std::swap(size_, other.size_);
182 std::swap(key_compare_, other.key_compare_);
183 std::swap(key_extractor_, other.key_extractor_);
184 }
185
186 key_compare key_comp() const
187 {
188 return key_compare_;
189 }
190
191 iterator find(const key_type& key)
192 {
193 // TODO: implement
194 }
195
196 const_iterator find(const key_type&& key) const
197 {
198 // TODO: implement
199 }
200
201 size_type count(const key_type& key) const
202 {
203 return Policy::count(*this, key);
204 }
205
206 iterator upper_bound(const key_type& key)
207 {
208 return Policy::upper_bound(*this, key);
209 }
210
211 const_iterator upper_bound(const key_type& key) const
212 {
213 return Policy::upper_bound_const(*this, key);
214 }
215
216 iterator lower_bound(const key_type& key)
217 {
218 return Policy::lower_bound(*this, key);
219 }
220
221 const_iterator lower_bound(const key_type& key) const
222 {
223 return Policy::lower_bound_const(*this, key);
224 }
225
226 pair<iterator, iterator> equal_range(const key_type& key)
227 {
228 return Policy::equal_range(*this, key);
229 }
230
231 pair<const_iterator, const_iterator> equal_range(const key_type& key) const
232 {
233 return Policy::equal_range_const(*this, key);
234 }
235
236 bool is_eq_to(const rbtree& other) const
237 {
238 // TODO: implement
239 return false;
240 }
241
242 const key_type& get_key(const value_type& val) const
243 {
244 return key_extractor_(val);
245 }
246
247 bool keys_comp(const key_type& key, const value_type& val) const
248 {
249 return key_compare_(key, key_extractor_(val));
250 }
251
252 node_type* find_parent_for_insertion(const value_type& val) const
253 {
254 auto current = root_;
255 auto parent = current;
256
257 while (current)
258 {
259 parent = current;
260 if (key_compare_(key_extractor_(val), key_extractor_(current->value)))
261 current = current->left;
262 else
263 current = current->right;
264 }
265
266 return parent;
267 }
268
269 private:
270 node_type* root_;
271 size_type size_;
272 key_compare key_compare_;
273 key_extract key_extractor_;
274
275 node_type* find_smallest_() const
276 {
277 if (root_)
278 return root_->find_smallest();
279 else
280 return nullptr;
281 }
282
283 node_type* find_largest_() const
284 {
285 if (root_)
286 return root_->find_largest();
287 else
288 return nullptr;
289 }
290
291 void update_root_(node_type* node)
292 {
293 if (!node)
294 return;
295
296 root_ = node;
297 while (root_->parent)
298 root_ = root_->parent;
299 }
300
301 void repair_after_insert_(node_type* node)
302 {
303 // TODO: implement
304 }
305
306 friend Policy;
307 };
308}
309
310#endif
Note: See TracBrowser for help on using the repository browser.