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/module.hpp"
8#include <map>
9
10namespace hi::inline v1 {
11
18template<typename Key, typename T, typename Compare = std::less<Key>>
19class tree {
20public:
21 using key_type = Key;
22 using value_type = T;
23
24 constexpr ~tree() = default;
25 constexpr tree(tree const&) noexcept = default;
26 constexpr tree(tree&&) noexcept = default;
27 constexpr tree& operator=(tree const&) noexcept = default;
28 constexpr tree& operator=(tree&&) noexcept = default;
29 constexpr tree() noexcept = default;
30
38 value_type& operator()(auto path_first, auto path_last) noexcept
39 {
40 auto *ptr = find_or_create(path_first, path_last);
42 return ptr->value;
43 }
44
53 value_type const& operator()(auto path_first, auto path_last) const noexcept
54 {
55 auto *ptr = find(path_first, path_last, [](value_type const&) -> void {});
57 return ptr->value;
58 }
59
65 value_type& operator[](auto const& key) noexcept
66 {
67 using std::cbegin;
68 using std::cend;
69 return this->operator()(cbegin(key), cend(key));
70 }
71
78 value_type const& operator[](auto const& path) const noexcept
79 {
80 using std::cbegin;
81 using std::cend;
82 return this->operator()(cbegin(path), cend(path));
83 }
84
85 /* Walk the tree from the node pointed to by the path.
86 *
87 * @param path_first The first element of the path to the start node.
88 * @param path_last On beyond the last element of the path to the start node.
89 * @param func The function `(value_type &) -> void` to execute on the
90 */
91 void walk(auto path_first, auto path_last, auto&& func) noexcept
92 {
93 if (auto element = find(path_first, path_last, [](value_type&) -> void {})) {
94 _walk(element, hi_forward(func));
95 }
96 }
97
98 /* Walk the tree from the node pointed to by the path.
99 *
100 * @param path_first The first element of the path to the start node.
101 * @param path_last On beyond the last element of the path to the start node.
102 * @param func The function `(value_type const &) -> void` to execute on the
103 */
104 void walk(auto path_first, auto path_last, auto&& func) const noexcept
105 {
106 if (auto element = find(path_first, path_last, [](value_type const&) -> void {})) {
107 _walk(element, hi_forward(func));
108 }
109 }
110
111 /* Walk the tree from the node pointed to by the path.
112 *
113 * @param path The path (range) to the start node.
114 * @param func The function `(value_type &) -> void` to execute on the
115 */
116 void walk(auto const& key, auto&& func) noexcept
117 {
118 using std::cbegin;
119 using std::cend;
120 return walk(cbegin(key), cend(key), hi_forward(func));
121 }
122
123 /* Walk the tree from the node pointed to by the path.
124 *
125 * @param path The path (range) to the start node.
126 * @param func The function `(value_type const &) -> void` to execute on the
127 */
128 void walk(auto const& key, auto&& func) const noexcept
129 {
130 using std::cbegin;
131 using std::cend;
132 return walk(cbegin(key), cend(key), hi_forward(func));
133 }
134
142 void walk_including_path(auto path_first, auto path_last, auto const& func) noexcept
143 {
144 if (auto element = find(path_first, path_last, func)) {
145 _walk(element, func);
146 }
147 }
148
156 void walk_including_path(auto path_first, auto path_last, auto const& func) const noexcept
157 {
158 if (auto element = find(path_first, path_last, func)) {
159 _walk(element, func);
160 }
161 }
162
169 void walk_including_path(auto const& path, auto&& func) noexcept
170 {
171 using std::cbegin;
172 using std::cend;
173 return walk_including_path(cbegin(path), cend(path), hi_forward(func));
174 }
175
182 void walk_including_path(auto const& path, auto&& func) const noexcept
183 {
184 using std::cbegin;
185 using std::cend;
186 return walk_including_path(cbegin(path), cend(path), hi_forward(func));
187 }
188
193 void walk(auto&& func) noexcept
194 {
195 _walk(std::addressof(_root), hi_forward(func));
196 }
197
202 void walk(auto&& func) const noexcept
203 {
204 _walk(std::addressof(_root), hi_forward(func));
205 }
206
207private:
208 struct node_type {
209 value_type value;
211 };
212
213 node_type _root;
214
222 [[nodiscard]] constexpr node_type *find(auto path_first, auto path_last, auto const& func) noexcept
223 {
224 auto *node = &_root;
225 for (auto path_it = path_first; path_it != path_last; ++path_it) {
226 func(node->value);
227
228 if (auto node_it = node->children.find(*path_it); node_it != node->children.end()) {
229 node = &node_it->second;
230 } else {
231 return nullptr;
232 }
233 }
234 return node;
235 }
236
244 [[nodiscard]] constexpr node_type const *find(auto path_first, auto path_last, auto const& func) const noexcept
245 {
246 node_type const *node = std::addressof(_root);
247 for (auto path_it = path_first; path_it != path_last; ++path_it) {
248 func(node->value);
249
250 if (auto node_it = node->children.find(*path_it); node_it != node->children.end()) {
251 node = std::addressof(node_it->second);
252 } else {
253 return nullptr;
254 }
255 }
256 return node;
257 }
258
259 [[nodiscard]] constexpr node_type *find_or_create(auto path_first, auto path_last) noexcept
260 {
261 auto *node = &_root;
262 for (auto path_it = path_first; path_it != path_last; ++path_it) {
263 node = &node->children[*path_it];
264 }
265 return node;
266 }
267
273 constexpr void _walk(node_type *node, auto const& func) noexcept
274 {
275 func(node->value);
276 for (auto& child : node->children) {
277 _walk(&child.second, func);
278 }
279 }
280
286 constexpr void _walk(node_type const *node, auto const& func) const noexcept
287 {
288 func(node->value);
289 for (auto& child : node->children) {
290 _walk(&child.second, func);
291 }
292 }
293};
294
295} // namespace hi::inline v1
#define hi_assert_not_null(x,...)
Assert if an expression is not nullptr.
Definition assert.hpp:223
#define hi_forward(x)
Forward a value, based on the decltype of the value.
Definition utility.hpp:29
DOXYGEN BUG.
Definition algorithm.hpp:13
A tree container.
Definition tree.hpp:19
void walk(auto &&func) const noexcept
Walk the full tree.
Definition tree.hpp:202
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:53
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:182
value_type & operator[](auto const &key) noexcept
Find or create the node and return the value of the node.
Definition tree.hpp:65
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:156
value_type const & operator[](auto const &path) const noexcept
Find the node and return the value of the node.
Definition tree.hpp:78
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:169
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:142
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:38
void walk(auto &&func) noexcept
Walk the full tree.
Definition tree.hpp:193
T addressof(T... args)
T find(T... args)