Serenity Operating System
at portability 295 lines 9.7 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 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 are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#pragma once 28 29#include <AK/Assertions.h> 30#include <AK/NonnullRefPtr.h> 31#include <AK/Weakable.h> 32 33// FIXME: I wish I didn't have to forward declare these, but I can't seem to avoid 34// it if I still want to have for_each_in_subtree_of_type<U> inline here. 35class Node; 36class LayoutNode; 37template<typename T> 38bool is(const Node&); 39template<typename T> 40bool is(const LayoutNode&); 41 42template<typename T> 43class TreeNode : public Weakable<T> { 44public: 45 void ref() 46 { 47 ASSERT(m_ref_count); 48 ++m_ref_count; 49 } 50 51 void unref() 52 { 53 ASSERT(m_ref_count); 54 if (!--m_ref_count) { 55 if (m_next_sibling) 56 m_next_sibling->m_previous_sibling = m_previous_sibling; 57 if (m_previous_sibling) 58 m_previous_sibling->m_next_sibling = m_next_sibling; 59 T* next_child; 60 for (auto* child = m_first_child; child; child = next_child) { 61 next_child = child->m_next_sibling; 62 child->m_parent = nullptr; 63 child->unref(); 64 } 65 delete static_cast<T*>(this); 66 } 67 } 68 int ref_count() const { return m_ref_count; } 69 70 T* parent() { return m_parent; } 71 const T* parent() const { return m_parent; } 72 73 bool has_children() const { return m_first_child; } 74 T* next_sibling() { return m_next_sibling; } 75 T* previous_sibling() { return m_previous_sibling; } 76 T* first_child() { return m_first_child; } 77 T* last_child() { return m_last_child; } 78 const T* next_sibling() const { return m_next_sibling; } 79 const T* previous_sibling() const { return m_previous_sibling; } 80 const T* first_child() const { return m_first_child; } 81 const T* last_child() const { return m_last_child; } 82 83 int child_count() const 84 { 85 int count = 0; 86 for (auto* child = first_child(); child; child = child->next_sibling()) 87 ++count; 88 return count; 89 } 90 91 T* child_at_index(int index) 92 { 93 int count = 0; 94 for (auto* child = first_child(); child; child = child->next_sibling()) { 95 if (count == index) 96 return child; 97 ++count; 98 } 99 return nullptr; 100 } 101 102 const T* child_at_index(int index) const 103 { 104 return const_cast<TreeNode*>(this)->child_at_index(index); 105 } 106 107 bool is_ancestor_of(const TreeNode&) const; 108 109 void prepend_child(NonnullRefPtr<T> node, bool call_inserted_into = true); 110 void append_child(NonnullRefPtr<T> node, bool call_inserted_into = true); 111 NonnullRefPtr<T> remove_child(NonnullRefPtr<T> node, bool call_removed_from = true); 112 void donate_all_children_to(T& node); 113 114 bool is_child_allowed(const T&) const { return true; } 115 116 T* next_in_pre_order() 117 { 118 if (first_child()) 119 return first_child(); 120 T* node; 121 if (!(node = next_sibling())) { 122 node = parent(); 123 while (node && !node->next_sibling()) 124 node = node->parent(); 125 if (node) 126 node = node->next_sibling(); 127 } 128 return node; 129 } 130 131 const T* next_in_pre_order() const 132 { 133 return const_cast<TreeNode*>(this)->next_in_pre_order(); 134 } 135 136 template<typename Callback> 137 IterationDecision for_each_in_subtree(Callback callback) const 138 { 139 if (callback(static_cast<const T&>(*this)) == IterationDecision::Break) 140 return IterationDecision::Break; 141 for (auto* child = first_child(); child; child = child->next_sibling()) { 142 if (child->for_each_in_subtree(callback) == IterationDecision::Break) 143 return IterationDecision::Break; 144 } 145 return IterationDecision::Continue; 146 } 147 148 template<typename Callback> 149 IterationDecision for_each_in_subtree(Callback callback) 150 { 151 if (callback(static_cast<T&>(*this)) == IterationDecision::Break) 152 return IterationDecision::Break; 153 for (auto* child = first_child(); child; child = child->next_sibling()) { 154 if (child->for_each_in_subtree(callback) == IterationDecision::Break) 155 return IterationDecision::Break; 156 } 157 return IterationDecision::Continue; 158 } 159 160 template<typename U, typename Callback> 161 IterationDecision for_each_in_subtree_of_type(Callback callback) 162 { 163 if (is<U>(static_cast<const T&>(*this))) { 164 if (callback(static_cast<U&>(*this)) == IterationDecision::Break) 165 return IterationDecision::Break; 166 } 167 for (auto* child = first_child(); child; child = child->next_sibling()) { 168 if (child->template for_each_in_subtree_of_type<U>(callback) == IterationDecision::Break) 169 return IterationDecision::Break; 170 } 171 return IterationDecision::Continue; 172 } 173 174 template<typename U, typename Callback> 175 IterationDecision for_each_in_subtree_of_type(Callback callback) const 176 { 177 if (is<U>(static_cast<const T&>(*this))) { 178 if (callback(static_cast<const U&>(*this)) == IterationDecision::Break) 179 return IterationDecision::Break; 180 } 181 for (auto* child = first_child(); child; child = child->next_sibling()) { 182 if (child->template for_each_in_subtree_of_type<U>(callback) == IterationDecision::Break) 183 return IterationDecision::Break; 184 } 185 return IterationDecision::Continue; 186 } 187 188protected: 189 TreeNode() {} 190 191private: 192 int m_ref_count { 1 }; 193 T* m_parent { nullptr }; 194 T* m_first_child { nullptr }; 195 T* m_last_child { nullptr }; 196 T* m_next_sibling { nullptr }; 197 T* m_previous_sibling { nullptr }; 198}; 199 200template<typename T> 201inline NonnullRefPtr<T> TreeNode<T>::remove_child(NonnullRefPtr<T> node, bool call_removed_from) 202{ 203 ASSERT(node->m_parent == this); 204 205 if (m_first_child == node) 206 m_first_child = node->m_next_sibling; 207 208 if (m_last_child == node) 209 m_last_child = node->m_previous_sibling; 210 211 if (node->m_next_sibling) 212 node->m_next_sibling->m_previous_sibling = node->m_previous_sibling; 213 214 if (node->m_previous_sibling) 215 node->m_previous_sibling->m_next_sibling = node->m_next_sibling; 216 217 node->m_next_sibling = nullptr; 218 node->m_previous_sibling = nullptr; 219 node->m_parent = nullptr; 220 221 if (call_removed_from) 222 node->removed_from(static_cast<T&>(*this)); 223 224 node->unref(); 225 226 return node; 227} 228 229template<typename T> 230inline void TreeNode<T>::append_child(NonnullRefPtr<T> node, bool call_inserted_into) 231{ 232 ASSERT(!node->m_parent); 233 234 if (!static_cast<T*>(this)->is_child_allowed(*node)) 235 return; 236 237 if (m_last_child) 238 m_last_child->m_next_sibling = node.ptr(); 239 node->m_previous_sibling = m_last_child; 240 node->m_parent = static_cast<T*>(this); 241 m_last_child = node.ptr(); 242 if (!m_first_child) 243 m_first_child = m_last_child; 244 if (call_inserted_into) 245 node->inserted_into(static_cast<T&>(*this)); 246 (void)node.leak_ref(); 247} 248 249template<typename T> 250inline void TreeNode<T>::prepend_child(NonnullRefPtr<T> node, bool call_inserted_into) 251{ 252 ASSERT(!node->m_parent); 253 254 if (!static_cast<T*>(this)->is_child_allowed(*node)) 255 return; 256 257 if (m_first_child) 258 m_first_child->m_previous_sibling = node.ptr(); 259 node->m_next_sibling = m_first_child; 260 node->m_parent = static_cast<T*>(this); 261 m_first_child = node.ptr(); 262 if (!m_last_child) 263 m_last_child = m_first_child; 264 if (call_inserted_into) 265 node->inserted_into(static_cast<T&>(*this)); 266 (void)node.leak_ref(); 267} 268 269template<typename T> 270inline void TreeNode<T>::donate_all_children_to(T& node) 271{ 272 for (T* child = m_first_child; child != nullptr;) { 273 T* next_child = child->m_next_sibling; 274 275 child->m_parent = nullptr; 276 child->m_next_sibling = nullptr; 277 child->m_previous_sibling = nullptr; 278 279 node.append_child(adopt(*child)); 280 child = next_child; 281 } 282 283 m_first_child = nullptr; 284 m_last_child = nullptr; 285} 286 287template<typename T> 288inline bool TreeNode<T>::is_ancestor_of(const TreeNode<T>& other) const 289{ 290 for (auto* ancestor = other.parent(); ancestor; ancestor = ancestor->parent()) { 291 if (ancestor == this) 292 return true; 293 } 294 return false; 295}