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