HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
tree.hpp
1// Copyright Take Vos 2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "../utility/utility.hpp"
8#include "../macros.hpp"
9#include <map>
10
11
12
13namespace hi::inline v1 {
14
21template<typename Key, typename T, typename Compare = std::less<Key>>
22class tree {
23public:
24 using key_type = Key;
25 using value_type = T;
26
27 constexpr ~tree() = default;
28 constexpr tree(tree const&) noexcept = default;
29 constexpr tree(tree&&) noexcept = default;
30 constexpr tree& operator=(tree const&) noexcept = default;
31 constexpr tree& operator=(tree&&) noexcept = default;
32 constexpr tree() noexcept = default;
33
41 value_type& operator()(auto path_first, auto path_last) noexcept
42 {
43 auto *ptr = find_or_create(path_first, path_last);
44 hi_assert_not_null(ptr);
45 return ptr->value;
46 }
47
56 value_type const& operator()(auto path_first, auto path_last) const noexcept
57 {
58 auto *ptr = find(path_first, path_last, [](value_type const&) -> void {});
59 hi_assert_not_null(ptr);
60 return ptr->value;
61 }
62
68 value_type& operator[](auto const& key) noexcept
69 {
70 using std::cbegin;
71 using std::cend;
72 return this->operator()(cbegin(key), cend(key));
73 }
74
81 value_type const& operator[](auto const& path) const noexcept
82 {
83 using std::cbegin;
84 using std::cend;
85 return this->operator()(cbegin(path), cend(path));
86 }
87
88 /* Walk the tree from the node pointed to by the path.
89 *
90 * @param path_first The first element of the path to the start node.
91 * @param path_last On beyond the last element of the path to the start node.
92 * @param func The function `(value_type &) -> void` to execute on the
93 */
94 void walk(auto path_first, auto path_last, auto&& func) noexcept
95 {
96 if (auto element = find(path_first, path_last, [](value_type&) -> void {})) {
97 _walk(element, hi_forward(func));
98 }
99 }
100
101 /* Walk the tree from the node pointed to by the path.
102 *
103 * @param path_first The first element of the path to the start node.
104 * @param path_last On beyond the last element of the path to the start node.
105 * @param func The function `(value_type const &) -> void` to execute on the
106 */
107 void walk(auto path_first, auto path_last, auto&& func) const noexcept
108 {
109 if (auto element = find(path_first, path_last, [](value_type const&) -> void {})) {
110 _walk(element, hi_forward(func));
111 }
112 }
113
114 /* Walk the tree from the node pointed to by the path.
115 *
116 * @param path The path (range) to the start node.
117 * @param func The function `(value_type &) -> void` to execute on the
118 */
119 void walk(auto const& key, auto&& func) noexcept
120 {
121 using std::cbegin;
122 using std::cend;
123 return walk(cbegin(key), cend(key), hi_forward(func));
124 }
125
126 /* Walk the tree from the node pointed to by the path.
127 *
128 * @param path The path (range) to the start node.
129 * @param func The function `(value_type const &) -> void` to execute on the
130 */
131 void walk(auto const& key, auto&& func) const noexcept
132 {
133 using std::cbegin;
134 using std::cend;
135 return walk(cbegin(key), cend(key), hi_forward(func));
136 }
137
145 void walk_including_path(auto path_first, auto path_last, auto const& func) noexcept
146 {
147 if (auto element = find(path_first, path_last, func)) {
148 _walk(element, func);
149 }
150 }
151
159 void walk_including_path(auto path_first, auto path_last, auto const& func) const noexcept
160 {
161 if (auto element = find(path_first, path_last, func)) {
162 _walk(element, func);
163 }
164 }
165
172 void walk_including_path(auto const& path, auto&& func) noexcept
173 {
174 using std::cbegin;
175 using std::cend;
176 return walk_including_path(cbegin(path), cend(path), hi_forward(func));
177 }
178
185 void walk_including_path(auto const& path, auto&& func) const noexcept
186 {
187 using std::cbegin;
188 using std::cend;
189 return walk_including_path(cbegin(path), cend(path), hi_forward(func));
190 }
191
196 void walk(auto&& func) noexcept
197 {
198 _walk(std::addressof(_root), hi_forward(func));
199 }
200
205 void walk(auto&& func) const noexcept
206 {
207 _walk(std::addressof(_root), hi_forward(func));
208 }
209
210private:
211 struct node_type {
212 value_type value;
214 };
215
216 node_type _root;
217
225 [[nodiscard]] constexpr node_type *find(auto path_first, auto path_last, auto const& func) noexcept
226 {
227 auto *node = &_root;
228 for (auto path_it = path_first; path_it != path_last; ++path_it) {
229 func(node->value);
230
231 if (auto node_it = node->children.find(*path_it); node_it != node->children.end()) {
232 node = &node_it->second;
233 } else {
234 return nullptr;
235 }
236 }
237 return node;
238 }
239
247 [[nodiscard]] constexpr node_type const *find(auto path_first, auto path_last, auto const& func) const noexcept
248 {
249 node_type const *node = std::addressof(_root);
250 for (auto path_it = path_first; path_it != path_last; ++path_it) {
251 func(node->value);
252
253 if (auto node_it = node->children.find(*path_it); node_it != node->children.end()) {
254 node = std::addressof(node_it->second);
255 } else {
256 return nullptr;
257 }
258 }
259 return node;
260 }
261
262 [[nodiscard]] constexpr node_type *find_or_create(auto path_first, auto path_last) noexcept
263 {
264 auto *node = &_root;
265 for (auto path_it = path_first; path_it != path_last; ++path_it) {
266 node = &node->children[*path_it];
267 }
268 return node;
269 }
270
276 constexpr void _walk(node_type *node, auto const& func) noexcept
277 {
278 func(node->value);
279 for (auto& child : node->children) {
280 _walk(&child.second, func);
281 }
282 }
283
289 constexpr void _walk(node_type const *node, auto const& func) const noexcept
290 {
291 func(node->value);
292 for (auto& child : node->children) {
293 _walk(&child.second, func);
294 }
295 }
296};
297
298} // namespace hi::inline v1
DOXYGEN BUG.
Definition algorithm.hpp:16
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
A tree container.
Definition tree.hpp:22
void walk(auto &&func) const noexcept
Walk the full tree.
Definition tree.hpp:205
value_type const & operator()(auto path_first, auto path_last) const noexcept
Find the node and return the value of the node.
Definition tree.hpp:56
void walk_including_path(auto const &path, auto &&func) const noexcept
Walk the tree starting at path, and also for each node along the path.
Definition tree.hpp:185
value_type & operator[](auto const &key) noexcept
Find or create the node and return the value of the node.
Definition tree.hpp:68
void walk_including_path(auto path_first, auto path_last, auto const &func) const noexcept
Walk the tree starting at path, and also for each node along the path.
Definition tree.hpp:159
value_type const & operator[](auto const &path) const noexcept
Find the node and return the value of the node.
Definition tree.hpp:81
void walk_including_path(auto const &path, auto &&func) noexcept
Walk the tree starting at path, and also for each node along the path.
Definition tree.hpp:172
void walk_including_path(auto path_first, auto path_last, auto const &func) noexcept
Walk the tree starting at path, and also for each node along the path.
Definition tree.hpp:145
value_type & operator()(auto path_first, auto path_last) noexcept
Find or create the node and return the value of the node.
Definition tree.hpp:41
void walk(auto &&func) noexcept
Walk the full tree.
Definition tree.hpp:196
T addressof(T... args)
T find(T... args)