File indexing completed on 2024-05-19 04:25:08
0001 /* 0002 * SPDX-FileCopyrightText: 2019 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 #ifndef KISFOREST_H 0007 #define KISFOREST_H 0008 0009 #include <utility> 0010 0011 #include <boost/iterator/iterator_facade.hpp> 0012 #include <boost/iterator/iterator_adaptor.hpp> 0013 0014 #include "KisCppQuirks.h" 0015 0016 #include "kis_assert.h" 0017 #include "kis_debug.h" 0018 0019 namespace KisForestDetail { 0020 0021 template <typename Base> 0022 struct RootNodeImpl 0023 { 0024 RootNodeImpl<Base> *parent = nullptr; 0025 Base *firstChild = nullptr; 0026 Base *lastChild = nullptr; 0027 0028 inline bool isRoot() const { 0029 return !parent; 0030 } 0031 }; 0032 0033 0034 template <typename Base> 0035 struct BaseNode : RootNodeImpl<Base> 0036 { 0037 Base *nextSibling = nullptr; 0038 Base *prevSibling = nullptr; 0039 }; 0040 0041 template <typename T> 0042 struct Node : public BaseNode<Node<T>> 0043 { 0044 template <typename X> 0045 explicit Node(X &&newValue) 0046 : value(std::forward<X>(newValue)) 0047 { 0048 } 0049 0050 T value; 0051 }; 0052 0053 template <typename T> 0054 using RootNode = RootNodeImpl<Node<T>>; 0055 0056 0057 /*************************************************************************/ 0058 /* BaseIterator */ 0059 /*************************************************************************/ 0060 0061 template <typename BaseClass, typename T, typename Tag, bool is_const> 0062 class BaseIterator : 0063 public boost::iterator_facade <BaseClass, 0064 T, 0065 Tag, 0066 std::add_lvalue_reference_t< 0067 std::add_const_if_t<is_const, T>>> 0068 { 0069 public: 0070 using value_type = T; 0071 using NodeType = std::add_const_if_t<is_const, Node<T>>; 0072 0073 BaseIterator(NodeType *node) 0074 : m_node(node) 0075 { 0076 } 0077 0078 NodeType* node() const { 0079 return m_node; 0080 } 0081 0082 private: 0083 friend class boost::iterator_core_access; 0084 0085 typename std::iterator_traits<BaseIterator>::reference dereference() const { 0086 KIS_ASSERT(m_node); 0087 return m_node->value; 0088 } 0089 0090 bool equal(const BaseClass &other) const { 0091 return m_node == other.m_node; 0092 } 0093 0094 protected: 0095 NodeType *m_node; 0096 }; 0097 0098 0099 /*************************************************************************/ 0100 /* ChildIterator */ 0101 /*************************************************************************/ 0102 0103 /** 0104 * Child iterator is used to traverse all the children of the current node. 0105 * It models \c BidirectionalIterator concept, so you can traverse with it in both 0106 * directions. 0107 * 0108 * \code{.cpp} 0109 * 0110 * // Forest: 0111 * // 0112 * // 0 1 0113 * // 2 0114 * // 3 5 6 0115 * // 7 0116 * // 4 0117 * // 8 9 0118 * // 10 0119 * 0120 * KisForest<int>::iterator it0 = findValue(forest, 0); 0121 * 0122 * // iterate through all the children of '0' 0123 * for (auto it = childBegin(it0); it != childEnd(it0); ++it) { 0124 * qDebug() << *it; 0125 * } 0126 * // prints: 1,2,3,4 0127 * 0128 * \endcode 0129 * 0130 * It is also possible to convert any iterator type into child iterator 0131 * via siblingCurrent() function. 0132 * 0133 * \code{.cpp} 0134 * 0135 * // Forest: 0136 * // 0137 * // 0 1 0138 * // 2 0139 * // 3 5 6 0140 * // 7 0141 * // 4 0142 * // 8 9 0143 * // 10 0144 * 0145 * KisForest<int>::iterator it2 = findValue(forest, 2); 0146 * 0147 * // iterate the children of '0' from '2' to '4' 0148 * for (auto it = siblingCurrent(it2); it != siblingEnd(it2); ++it) { 0149 * qDebug() << *it; 0150 * } 0151 * // prints: 2,3,4 0152 * 0153 * \endcode 0154 * 0155 * WARNING: converting end() iterator to other iterator types currently leads 0156 * to undefined behavior. 0157 */ 0158 0159 template <typename T, bool is_const> 0160 class ChildIterator : 0161 public BaseIterator <ChildIterator<T, is_const>, 0162 T, 0163 boost::bidirectional_traversal_tag, 0164 is_const> 0165 { 0166 using BaseClass = 0167 BaseIterator <ChildIterator<T, is_const>, 0168 T, 0169 boost::bidirectional_traversal_tag, 0170 is_const>; 0171 0172 public: 0173 using RootNodeType = std::add_const_if_t<is_const, RootNode<T>>; 0174 using NodeType = typename BaseClass::NodeType; 0175 0176 ChildIterator(NodeType *node, RootNodeType *parent, int offsetToParent) 0177 : BaseClass(node), 0178 m_parent(parent), 0179 m_offsetToParent(offsetToParent) 0180 { 0181 } 0182 0183 operator ChildIterator<T, true>() const { 0184 return ChildIterator<T, true>(this->m_node, m_parent, m_offsetToParent); 0185 } 0186 0187 private: 0188 friend class boost::iterator_core_access; 0189 template <typename X, bool c> 0190 friend ChildIterator<X, c> parent(const ChildIterator<X, c> &it); 0191 template <typename X, bool c> 0192 friend ChildIterator<X, c> siblingBegin(const ChildIterator<X, c> &it); 0193 template <typename X, bool c> 0194 friend ChildIterator<X, c> siblingEnd(const ChildIterator<X, c> &it); 0195 template <typename X, bool c> 0196 friend ChildIterator<X, c> childBegin(const ChildIterator<X, c> &it); 0197 template <typename X, bool c> 0198 friend ChildIterator<X, c> childEnd(const ChildIterator<X, c> &it); 0199 0200 template <typename X, bool c> 0201 friend QDebug operator<<(QDebug dbg, const ChildIterator<X, c> &it); 0202 template <typename X> friend class Forest; 0203 0204 void increment() { 0205 this->m_node = this->m_node->nextSibling; 0206 } 0207 0208 void decrement() { 0209 this->m_node = 0210 this->m_node ? 0211 this->m_node->prevSibling : 0212 (m_parent && m_offsetToParent == 0) ? m_parent->lastChild : nullptr; 0213 } 0214 0215 bool equal(const ChildIterator<T, is_const> &other) const { 0216 return this->m_node == other.m_node && 0217 (this->m_node || 0218 (this->m_parent == other.m_parent && 0219 this->m_offsetToParent == other.m_offsetToParent)); 0220 } 0221 0222 private: 0223 RootNodeType *m_parent; 0224 int m_offsetToParent; 0225 }; 0226 0227 template <typename value_type, bool is_const> 0228 QDebug operator<<(QDebug dbg, const ChildIterator<value_type, is_const> &it) 0229 { 0230 if (it.node()) { 0231 dbg.nospace() << "ChildIterator(" << it.node() << "(" << it.node()->value << ")" << ", parent:" << it.m_parent << ")"; 0232 } else { 0233 dbg.nospace() << "ChildIterator(" << "nullptr" << ", parent:" << it.m_parent << ", offset:" << it.m_offsetToParent << ")"; 0234 } 0235 return dbg; 0236 } 0237 0238 0239 template <typename value_type, bool is_const> 0240 ChildIterator<value_type, is_const> siblingCurrent(ChildIterator<value_type, is_const> it) 0241 { 0242 return it; 0243 } 0244 0245 template <typename value_type, bool is_const> 0246 ChildIterator<value_type, is_const> siblingBegin(const ChildIterator<value_type, is_const> &it) 0247 { 0248 using RootNodeType = typename ChildIterator<value_type, is_const>::RootNodeType; 0249 if (!it.node() && it.m_offsetToParent != 0) return it; 0250 RootNodeType *parent = it.m_parent; 0251 return ChildIterator<value_type, is_const>(parent ? parent->firstChild : nullptr, parent, 0); 0252 } 0253 0254 template <typename value_type, bool is_const> 0255 ChildIterator<value_type, is_const> siblingEnd(const ChildIterator<value_type, is_const> &it) 0256 { 0257 if (!it.node() && it.m_offsetToParent != 0) return it; 0258 return ChildIterator<value_type, is_const>(nullptr, it.m_parent, 0); 0259 } 0260 0261 template <typename Iterator, 0262 bool is_const = std::is_const_v<typename Iterator::NodeType>, 0263 typename ResultIterator = ChildIterator<typename Iterator::value_type, is_const>> 0264 ResultIterator siblingCurrent(Iterator it) 0265 { 0266 // TODO: conversion of an end-iterator into a child iterator is still not implemented 0267 // and considered as UB. We need to implement all special-cases for that. 0268 KIS_SAFE_ASSERT_RECOVER_NOOP(it.node()); 0269 0270 return ResultIterator(it.node(), it.node() ? it.node()->parent : nullptr, 0); 0271 } 0272 0273 template <typename Iterator, 0274 bool is_const = std::is_const_v<typename Iterator::NodeType>, 0275 typename ResultIterator = ChildIterator<typename Iterator::value_type, is_const>> 0276 ResultIterator siblingBegin(Iterator it) 0277 { 0278 return siblingBegin(siblingCurrent(it)); 0279 } 0280 0281 template <typename Iterator, 0282 bool is_const = std::is_const_v<typename Iterator::NodeType>, 0283 typename ResultIterator = ChildIterator<typename Iterator::value_type, is_const>> 0284 ResultIterator siblingEnd(Iterator it) 0285 { 0286 return siblingEnd(siblingCurrent(it)); 0287 } 0288 0289 template <typename value_type, bool is_const> 0290 ChildIterator<value_type, is_const> childBegin(const ChildIterator<value_type, is_const> &it) 0291 { 0292 if (it.node()) { 0293 return ChildIterator<value_type, is_const>(it.node()->firstChild, it.node(), 0); 0294 } else { 0295 return ChildIterator<value_type, is_const>(nullptr, it.m_parent, it.m_offsetToParent + 1); 0296 } 0297 } 0298 0299 template <typename value_type, bool is_const> 0300 ChildIterator<value_type, is_const> childEnd(const ChildIterator<value_type, is_const> &it) 0301 { 0302 if (it.node()) { 0303 return ChildIterator<value_type, is_const>(nullptr, it.node(), 0); 0304 } else { 0305 return ChildIterator<value_type, is_const>(nullptr, it.m_parent, it.m_offsetToParent + 1); 0306 } 0307 } 0308 0309 template <typename Iterator, 0310 bool is_const = std::is_const_v<typename Iterator::NodeType>, 0311 typename ResultIterator = ChildIterator<typename Iterator::value_type, is_const>> 0312 ResultIterator childBegin(Iterator it) 0313 { 0314 return childBegin(siblingCurrent(it)); 0315 } 0316 0317 template <typename Iterator, 0318 bool is_const = std::is_const_v<typename Iterator::NodeType>, 0319 typename ResultIterator = ChildIterator<typename Iterator::value_type, is_const>> 0320 ResultIterator childEnd(Iterator it) 0321 { 0322 return childEnd(siblingCurrent(it)); 0323 } 0324 0325 0326 template <typename value_type, bool is_const> 0327 ChildIterator<value_type, is_const> parent(const ChildIterator<value_type, is_const> &it) 0328 { 0329 if (it.m_parent->isRoot()) { 0330 return ChildIterator<value_type, is_const>(nullptr, it.m_parent, qMax(-1, it.m_offsetToParent - 1)); 0331 } else if (it.m_offsetToParent == 0) { 0332 using NodeType = typename ChildIterator<value_type, is_const>::NodeType; 0333 NodeType *parentNode = static_cast<NodeType*>(it.m_parent); 0334 return ChildIterator<value_type, is_const>(parentNode, parentNode->parent, 0); 0335 } else { 0336 return ChildIterator<value_type, is_const>(nullptr, it.m_parent, it.m_offsetToParent - 1); 0337 } 0338 } 0339 0340 template <typename T, bool is_const> 0341 inline bool isEnd(const ChildIterator<T, is_const> &it) { 0342 return !it.node(); 0343 } 0344 0345 0346 /*************************************************************************/ 0347 /* HierarchyIterator */ 0348 /*************************************************************************/ 0349 0350 /** 0351 * Hierarchy iterator is used to traverse from the current node to the root 0352 * of the current subtree of the forest. It models \c ForwardIterator concept. 0353 * 0354 * \code{.cpp} 0355 * 0356 * // Forest: 0357 * // 0358 * // 0 1 0359 * // 2 0360 * // 3 5 6 0361 * // 7 0362 * // 4 0363 * // 8 9 0364 * // 10 0365 * 0366 * KisForest<int>::iterator nodeIt = findValue(forest, 5); 0367 * 0368 * // print all the parent nodes for nodeIt, including nodeIt itself 0369 * for (auto it = hierarchyBegin(nodeIt); it != hierarchyEnd(nodeIt); ++it) { 0370 * qDebug() << *it; 0371 * } 0372 * // prints: 5,3,0 0373 * 0374 * \endcode 0375 * 0376 * WARNING: converting end() iterator to other iterator types currently leads 0377 * to undefined behavior. 0378 */ 0379 0380 template <typename T, bool is_const> 0381 class HierarchyIterator : 0382 public BaseIterator <HierarchyIterator<T, is_const>, 0383 T, 0384 boost::forward_traversal_tag, 0385 is_const> 0386 { 0387 using BaseClass = BaseIterator <HierarchyIterator<T, is_const>, 0388 T, 0389 boost::forward_traversal_tag, 0390 is_const>; 0391 public: 0392 using RootNodeType = std::add_const_if_t<is_const, RootNode<T>>; 0393 using NodeType = typename BaseClass::NodeType; 0394 0395 HierarchyIterator(NodeType *node) 0396 : BaseClass(node) 0397 { 0398 } 0399 0400 operator HierarchyIterator<T, true>() const { 0401 return HierarchyIterator<T, true>(this->m_node); 0402 } 0403 0404 private: 0405 friend class boost::iterator_core_access; 0406 0407 void increment() { 0408 RootNodeType *parent = this->m_node->parent; 0409 this->m_node = 0410 static_cast<NodeType*>( 0411 parent && !parent->isRoot() ? 0412 parent : nullptr); 0413 } 0414 }; 0415 0416 template <typename Iterator, 0417 bool is_const = std::is_const_v<typename Iterator::NodeType>, 0418 typename ResultIterator = HierarchyIterator<typename Iterator::value_type, is_const>> 0419 ResultIterator hierarchyBegin(Iterator it) 0420 { 0421 return ResultIterator(it.node()); 0422 } 0423 0424 template <typename Iterator, 0425 bool is_const = std::is_const_v<typename Iterator::NodeType>, 0426 typename ResultIterator = HierarchyIterator<typename Iterator::value_type, is_const>> 0427 ResultIterator hierarchyEnd(Iterator it) 0428 { 0429 Q_UNUSED(it); 0430 return ResultIterator(nullptr); 0431 } 0432 0433 0434 /*************************************************************************/ 0435 /* CompositionIterator */ 0436 /*************************************************************************/ 0437 0438 /** 0439 * Composition iterator is used to traverse entire child-subtree of the node 0440 * recursively in depth-first order. Every node it entered twice: first time, when 0441 * subtree is entered; second time, when subtree is left. To check the current 0442 * state of the iterator (Enter or Leave) use \c it.state() call. 0443 * 0444 * Iterator models \c ForwardIterator concept. 0445 * 0446 * \code{.cpp} 0447 * 0448 * // Forest: 0449 * // 0450 * // 0 1 0451 * // 2 0452 * // 3 5 6 0453 * // 7 0454 * // 4 0455 * // 8 9 0456 * // 10 0457 * 0458 * KisForest<int>::iterator it3 = findValue(forest, 3); 0459 * 0460 * // iterate through all the children of '3' recursively 0461 * for (auto it = compositionBegin(it3); it != compositionEnd(it3); ++it) { 0462 * qDebug() << *it << it.state(); 0463 * } 0464 * // prints: (3, Enter) 0465 * // (5, Enter) 0466 * // (6, Enter) 0467 * // (6, Leave) 0468 * // (7, Enter) 0469 * // (7, Leave) 0470 * // (5, Leave) 0471 * // (3, Leave) 0472 * 0473 * \endcode 0474 * 0475 * WARNING: converting end() iterator to other iterator types currently leads 0476 * to undefined behavior. 0477 */ 0478 0479 enum TraversalState { 0480 Enter, 0481 Leave 0482 }; 0483 0484 template <typename T, bool is_const> 0485 class CompositionIterator : 0486 public boost::iterator_adaptor< 0487 CompositionIterator<T, is_const>, 0488 ChildIterator<T, is_const>, 0489 boost::use_default, 0490 boost::forward_traversal_tag> 0491 { 0492 using BaseClass = boost::iterator_adaptor< 0493 CompositionIterator<T, is_const>, 0494 ChildIterator<T, is_const>, 0495 boost::use_default, 0496 boost::forward_traversal_tag>; 0497 0498 using BaseIteratorType = typename CompositionIterator::base_type; 0499 0500 public: 0501 using traversal_state = TraversalState; 0502 using RootNodeType = typename BaseIteratorType::RootNodeType; 0503 using NodeType = typename BaseIteratorType::NodeType; 0504 0505 NodeType* node() const { 0506 return this->base().node(); 0507 } 0508 0509 public: 0510 CompositionIterator(NodeType *node, traversal_state state = Enter) 0511 : BaseClass(BaseIteratorType(node, node ? node->parent : nullptr, 0)), 0512 m_state(state) 0513 { 0514 } 0515 0516 traversal_state state() const { 0517 return m_state; 0518 } 0519 0520 operator CompositionIterator<T, true>() const { 0521 return CompositionIterator<T, true>(this->m_node, this->m_state); 0522 } 0523 0524 private: 0525 friend class boost::iterator_core_access; 0526 0527 bool tryJumpToPos(typename CompositionIterator::base_type it, 0528 TraversalState newState) { 0529 bool result = false; 0530 0531 if (!isEnd(it)) { 0532 this->base_reference() = it; 0533 result = true; 0534 m_state = newState; 0535 } 0536 0537 return result; 0538 } 0539 0540 void increment() { 0541 switch (m_state) { 0542 case Enter: 0543 if (tryJumpToPos(childBegin(this->base()), Enter)) return; 0544 if (tryJumpToPos(this->base(), Leave)) return; 0545 break; 0546 case Leave: 0547 if (tryJumpToPos(std::next(this->base()), Enter)) return; 0548 if (tryJumpToPos(parent(this->base()), Leave)) return; 0549 break; 0550 } 0551 0552 this->base_reference() = BaseIteratorType(nullptr, nullptr, 0); 0553 } 0554 0555 private: 0556 traversal_state m_state = Enter; 0557 }; 0558 0559 template <typename Iterator, 0560 bool is_const = std::is_const_v<typename Iterator::NodeType>, 0561 typename ResultIterator = CompositionIterator<typename Iterator::value_type, is_const>> 0562 ResultIterator compositionBegin(Iterator it) 0563 { 0564 return ResultIterator(it.node(), Enter); 0565 } 0566 0567 template <typename Iterator, 0568 bool is_const = std::is_const_v<typename Iterator::NodeType>, 0569 typename ResultIterator = CompositionIterator<typename Iterator::value_type, is_const>> 0570 ResultIterator compositionEnd(Iterator it) 0571 { 0572 return it.node() ? 0573 std::next(ResultIterator(it.node(), Leave)) : 0574 ResultIterator(nullptr, Leave); 0575 } 0576 0577 0578 /*************************************************************************/ 0579 /* DepthFirstIterator */ 0580 /*************************************************************************/ 0581 0582 /** 0583 * Depth-first iterator is used to traverse entire child-subtree of the node 0584 * recursively in depth-first order. Every node is entered only once. It 0585 * implements standard recursion iteration: 0586 * 0587 * * \c DepthFirstIterator<T, Enter> implements head-recursion, that is, 0588 * the node is visited *before* its children 0589 * 0590 * * \c DepthFirstIterator<T, Leave> implements tail-recursion, that is, 0591 * the node is visited *after* its children 0592 * 0593 * Use \c subtreeBegin() and \c subtreeEnd() for head-recursion and \c tailSubtreeBegin() and 0594 * \c tailSubtreeEnd() for tail-recursion. 0595 * 0596 * Iterator models \c ForwardIterator concept. 0597 * 0598 * \code{.cpp} 0599 * 0600 * // Forest: 0601 * // 0602 * // 0 1 0603 * // 2 0604 * // 3 5 6 0605 * // 7 0606 * // 4 0607 * // 8 9 0608 * // 10 0609 * 0610 * KisForest<int>::iterator it3 = findValue(forest, 3); 0611 * 0612 * // iterate through all the children of '3' in head-recursive way 0613 * for (auto it = subtreeBegin(it3); it != subtreeEnd(it3); ++it) { 0614 * qDebug() << *it << it.state(); 0615 * } 0616 * // prints: 3, 5, 6, 7 0617 * 0618 * // iterate through all the children of '3' in tail-recursive way 0619 * for (auto it = tailSubtreeBegin(it3); it != tailSubtreeEnd(it3); ++it) { 0620 * qDebug() << *it << it.state(); 0621 * } 0622 * // prints: 6, 7, 5, 3 0623 * 0624 * \endcode 0625 * 0626 * WARNING: converting end() iterator to other iterator types currently leads 0627 * to undefined behavior. 0628 */ 0629 0630 template <typename T, TraversalState visit_on, bool is_const> 0631 class DepthFirstIterator : 0632 public boost::iterator_adaptor< 0633 DepthFirstIterator<T, visit_on, is_const>, 0634 CompositionIterator<T, is_const>, 0635 boost::use_default, 0636 boost::forward_traversal_tag> 0637 { 0638 using BaseClass = boost::iterator_adaptor< 0639 DepthFirstIterator<T, visit_on, is_const>, 0640 CompositionIterator<T, is_const>, 0641 boost::use_default, 0642 boost::forward_traversal_tag>; 0643 0644 using BaseIteratorType = typename DepthFirstIterator::base_type; 0645 0646 public: 0647 using traversal_state = TraversalState; 0648 using RootNodeType = typename BaseIteratorType::RootNodeType; 0649 using NodeType = typename BaseIteratorType::NodeType; 0650 0651 DepthFirstIterator(NodeType *node, 0652 traversal_state state = traversal_state::Enter, 0653 bool shouldSkipToBegin = false) 0654 : BaseClass(BaseIteratorType(node, state)) 0655 { 0656 if (shouldSkipToBegin) { 0657 skipToState(visit_on); 0658 } 0659 } 0660 0661 NodeType* node() const { 0662 return this->base().node(); 0663 } 0664 0665 operator DepthFirstIterator<T, visit_on, true>() const { 0666 return DepthFirstIterator<T, visit_on, true>(this->m_node, this->m_state); 0667 } 0668 0669 private: 0670 friend class boost::iterator_core_access; 0671 0672 void increment() { 0673 this->base_reference()++; 0674 skipToState(visit_on); 0675 } 0676 0677 void skipToState(TraversalState state) { 0678 while (this->base().node() && this->base().state() != state) { 0679 this->base_reference()++; 0680 } 0681 } 0682 0683 }; 0684 0685 template <typename Iterator, 0686 bool is_const = std::is_const_v<typename Iterator::NodeType>, 0687 typename ResultIterator = DepthFirstIterator<typename Iterator::value_type, Enter, is_const>> 0688 ResultIterator subtreeBegin(Iterator it) 0689 { 0690 return ResultIterator(it.node(), Enter); 0691 } 0692 0693 template <typename Iterator, 0694 bool is_const = std::is_const_v<typename Iterator::NodeType>, 0695 typename ResultIterator = DepthFirstIterator<typename Iterator::value_type, Enter, is_const>> 0696 ResultIterator subtreeEnd(Iterator it) 0697 { 0698 return it.node() ? 0699 std::next(ResultIterator(it.node(), Leave)) : 0700 ResultIterator(nullptr, Leave); 0701 } 0702 0703 template <typename Iterator, 0704 bool is_const = std::is_const_v<typename Iterator::NodeType>, 0705 typename ResultIterator = DepthFirstIterator<typename Iterator::value_type, Leave, is_const>> 0706 ResultIterator tailSubtreeBegin(Iterator it) 0707 { 0708 return ResultIterator(it.node(), Enter, true); 0709 } 0710 0711 template <typename Iterator, 0712 bool is_const = std::is_const_v<typename Iterator::NodeType>, 0713 typename ResultIterator = DepthFirstIterator<typename Iterator::value_type, Leave, is_const>> 0714 ResultIterator tailSubtreeEnd(Iterator it) 0715 { 0716 return it.node() ? 0717 std::next(ResultIterator(it.node(), Leave)) : 0718 ResultIterator(nullptr, Leave); 0719 } 0720 0721 0722 /*************************************************************************/ 0723 /* Forest */ 0724 /*************************************************************************/ 0725 0726 /** 0727 * Forest implements a container for composing tree-like structures from 0728 * arbitrary objects. 0729 * 0730 * All add/remove operations are implemented via child_iterator. You can 0731 * convert any iterator type into a child iterator via \c siblingCurrent() 0732 * function. 0733 * 0734 * * \code{.cpp} 0735 * 0736 * // Forest: 0737 * // 0738 * // 0 1 0739 * // 2 0740 * // 3 5 6 0741 * // 7 0742 * // 4 0743 * // 8 9 0744 * // 10 0745 * 0746 * KisForest<int> forest; 0747 * 0748 * auto it0 = forest.insert(childBegin(forest), 0); 0749 * auto it8 = forest.insert(childEnd(forest), 8); 0750 * 0751 * auto it1 = forest.insert(childEnd(it0), 1); 0752 * auto it2 = forest.insert(childEnd(it0), 2); 0753 * auto it3 = forest.insert(childEnd(it0), 3); 0754 * auto it4 = forest.insert(childEnd(it0), 4); 0755 * 0756 * auto it5 = forest.insert(childEnd(it3), 5); 0757 * 0758 * auto it6 = forest.insert(childEnd(it5), 6); 0759 * auto it7 = forest.insert(childEnd(it5), 7); 0760 * 0761 * auto it9 = forest.insert(childEnd(it8), 9); 0762 * auto it10 = forest.insert(childEnd(it8), 10); 0763 * 0764 * // iterate through all elements of the forest 0765 * for (auto it = subtreeBegin(forest); it != subtreeEnd(forest); ++it) { 0766 * qDebug() << *it << it.state(); 0767 * } 0768 * // prints: 0,1,2,3,5,6,7,4,8,9,10 0769 * 0770 * \endcode 0771 * 0772 * 0773 */ 0774 0775 template <typename T> 0776 class Forest 0777 { 0778 public: 0779 Forest() 0780 { 0781 } 0782 0783 ~Forest() { 0784 erase(childBegin(), childEnd()); 0785 } 0786 0787 Forest(const Forest<T> &rhs) { 0788 for (auto it = rhs.childBegin(); it != rhs.childEnd(); ++it) { 0789 auto cloneIt = this->insert(this->childEnd(), *it); 0790 cloneChildren(it, cloneIt); 0791 } 0792 } 0793 0794 using value_type = T; 0795 0796 using child_iterator = ChildIterator<T, false>; 0797 using const_child_iterator = ChildIterator<T, true>; 0798 0799 using composition_iterator = CompositionIterator<T, false>; 0800 using const_composition_iterator = CompositionIterator<T, true>; 0801 0802 using hierarchy_iterator = HierarchyIterator<T, false>; 0803 using const_hierarchy_iterator = HierarchyIterator<T, true>; 0804 0805 using iterator = DepthFirstIterator<T, Enter, false>; 0806 using const_iterator = DepthFirstIterator<T, Enter, true>; 0807 0808 using depth_first_tail_iterator = DepthFirstIterator<T, Leave, false>; 0809 using const_depth_first_tail_iterator = DepthFirstIterator<T, Leave, true>; 0810 0811 iterator begin() { 0812 return beginImpl(*this); 0813 } 0814 0815 iterator end() { 0816 return endImpl(*this); 0817 } 0818 0819 const_iterator begin() const { 0820 return beginImpl(*this); 0821 } 0822 0823 const_iterator end() const { 0824 return endImpl(*this); 0825 } 0826 0827 const_iterator constBegin() const { 0828 return beginImpl(*this); 0829 } 0830 0831 const_iterator constEnd() const { 0832 return endImpl(*this); 0833 } 0834 0835 depth_first_tail_iterator depthFirstTailBegin() { 0836 return tailSubtreeBegin(begin()); 0837 } 0838 0839 depth_first_tail_iterator depthFirstTailEnd() { 0840 return tailSubtreeEnd(end()); 0841 } 0842 0843 const_depth_first_tail_iterator depthFirstTailBegin() const { 0844 return tailSubtreeBegin(constBegin()); 0845 } 0846 0847 const_depth_first_tail_iterator depthFirstTailEnd() const { 0848 return tailSubtreeEnd(constEnd()); 0849 } 0850 0851 const_depth_first_tail_iterator constDepthFirstTailBegin() const { 0852 return tailSubtreeBegin(constBegin()); 0853 } 0854 0855 const_depth_first_tail_iterator constDepthFirstTailEnd() const { 0856 return tailSubtreeEnd(constEnd()); 0857 } 0858 0859 child_iterator childBegin() { 0860 return childBeginImpl(*this); 0861 } 0862 0863 child_iterator childEnd() { 0864 return childEndImpl(*this); 0865 } 0866 0867 child_iterator parentEnd() { 0868 return parentEndImpl(*this); 0869 } 0870 0871 const_child_iterator childBegin() const { 0872 return childBeginImpl(*this); 0873 } 0874 0875 const_child_iterator childEnd() const { 0876 return childEndImpl(*this); 0877 } 0878 0879 const_child_iterator parentEnd() const { 0880 return parentEndImpl(*this); 0881 } 0882 0883 const_child_iterator constChildBegin() const { 0884 return childBeginImpl(*this); 0885 } 0886 0887 const_child_iterator constChildEnd() const { 0888 return childEndImpl(*this); 0889 } 0890 0891 const_child_iterator constParentEnd() const { 0892 return parentEndImpl(*this); 0893 } 0894 0895 composition_iterator compositionBegin() { 0896 return compositionBeginImpl(*this); 0897 } 0898 0899 composition_iterator compositionEnd() { 0900 return compositionEndImpl(*this); 0901 } 0902 0903 const_composition_iterator compositionBegin() const { 0904 return compositionBeginImpl(*this); 0905 } 0906 0907 const_composition_iterator compositionEnd() const { 0908 return compositionEndImpl(*this); 0909 } 0910 0911 const_composition_iterator constCompositionBegin() const { 0912 return compositionBeginImpl(*this); 0913 } 0914 0915 const_composition_iterator constCompositionEnd() const { 0916 return compositionEndImpl(*this); 0917 } 0918 0919 /** 0920 * @brief Inserts element \p value into position \p pos. 0921 * \p value becomes the child of the same parent as \p pos 0922 * and is placed right before \p pos. 0923 * @return iterator pointing to the inserted element 0924 */ 0925 template <typename X> 0926 child_iterator insert(child_iterator pos, X &&value) { 0927 Node<T> *node = new Node<T>(std::forward<X>(value)); 0928 0929 linkNode(pos, node); 0930 0931 return child_iterator(node, node->parent, 0); 0932 } 0933 0934 /** 0935 * @brief Removes element at position \p pos. 0936 * If \p pos is 'end', then result is undefined. 0937 * @return the element following \p pos 0938 */ 0939 child_iterator erase(child_iterator pos) { 0940 child_iterator nextNode = std::next(pos); 0941 Node<T> *node = pos.node(); 0942 0943 Node<T> *lastNode = node; 0944 for (auto it = tailSubtreeBegin(pos); it != tailSubtreeEnd(pos); ++it) { 0945 0946 if (lastNode != node) { 0947 delete lastNode; 0948 } 0949 lastNode = it.node(); 0950 } 0951 0952 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(lastNode == node, pos); 0953 0954 unlinkNode(node); 0955 delete node; 0956 0957 return nextNode; 0958 } 0959 0960 /** 0961 * @brief erases all elements from \p pos to \p end (excluding \p end) 0962 * @return \p end 0963 */ 0964 child_iterator erase(child_iterator pos, child_iterator end) { 0965 while (pos != end) { 0966 pos = erase(pos); 0967 } 0968 return pos; 0969 } 0970 0971 /** 0972 * @brief move a subtree to new position 0973 * Moves \p subtree into a new position pointer by \p newPos. \p newPos 0974 * must not be inside the subtree, otherwise cycling links may appear. 0975 * @return iterator to a new position of \p subtree 0976 */ 0977 child_iterator move(child_iterator subtree, child_iterator newPos) { 0978 // sanity check for cycling move 0979 for (auto it = hierarchyBegin(newPos); it != hierarchyEnd(newPos); ++it) { 0980 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(it.node() != subtree.node(), subtree); 0981 } 0982 0983 Node<T> *node = subtree.node(); 0984 unlinkNode(node); 0985 0986 node->prevSibling = nullptr; 0987 node->nextSibling = nullptr; 0988 node->parent = nullptr; 0989 0990 linkNode(newPos, node); 0991 return child_iterator(node, node->parent, 0); 0992 } 0993 0994 private: 0995 0996 inline void linkBefore(Node<T> *node, Node<T> *beforeMe) { 0997 if (beforeMe) { 0998 node->nextSibling = beforeMe; 0999 beforeMe->prevSibling = node; 1000 } 1001 } 1002 1003 inline void linkAfter(Node<T> *node, Node<T> *afterMe) { 1004 if (afterMe) { 1005 node->prevSibling = afterMe; 1006 afterMe->nextSibling = node; 1007 } 1008 } 1009 1010 inline void linkNode(child_iterator pos, Node<T> *node) { 1011 Node<T> *nextNode = pos.node(); 1012 RootNode<T> *parentNode = pos.m_parent; 1013 1014 Node<T> *prevNode = nextNode ? 1015 nextNode->prevSibling : 1016 parentNode ? parentNode->lastChild : m_root.lastChild; 1017 1018 linkAfter(node, prevNode); 1019 linkBefore(node, nextNode); 1020 1021 KIS_SAFE_ASSERT_RECOVER_RETURN(parentNode); 1022 if (!nextNode) { 1023 parentNode->lastChild = node; 1024 } 1025 1026 if (nextNode == parentNode->firstChild) { 1027 parentNode->firstChild = node; 1028 } 1029 node->parent = parentNode; 1030 } 1031 1032 inline void unlinkNode(Node<T> *node) { 1033 RootNode<T> *parentNode = node->parent; 1034 1035 if (node->nextSibling) { 1036 node->nextSibling->prevSibling = node->prevSibling; 1037 } 1038 1039 if (node->prevSibling) { 1040 node->prevSibling->nextSibling = node->nextSibling; 1041 } 1042 1043 KIS_SAFE_ASSERT_RECOVER_RETURN(parentNode); 1044 if (parentNode->firstChild == node) { 1045 parentNode->firstChild = node->nextSibling; 1046 } 1047 1048 if (parentNode->lastChild == node) { 1049 parentNode->lastChild = node->prevSibling; 1050 } 1051 } 1052 1053 void cloneChildren(const_child_iterator oldParent, child_iterator parent) { 1054 auto it = KisForestDetail::childBegin(oldParent); 1055 auto end = KisForestDetail::childEnd(oldParent); 1056 for (;it != end; ++it) { 1057 auto itClone = this->insert(KisForestDetail::childEnd(parent), *it); 1058 cloneChildren(it, itClone); 1059 } 1060 } 1061 1062 private: 1063 template <class ForestType, 1064 class IteratorType = ChildIterator<typename ForestType::value_type, 1065 std::is_const_v<ForestType>>> 1066 static IteratorType childBeginImpl(ForestType &forest) { 1067 return IteratorType(forest.m_root.firstChild, &forest.m_root, 0); 1068 } 1069 1070 template <class ForestType, 1071 class IteratorType = ChildIterator<typename ForestType::value_type, 1072 std::is_const_v<ForestType>>> 1073 static IteratorType childEndImpl(ForestType &forest) { 1074 return IteratorType(nullptr, &forest.m_root, 0); 1075 } 1076 1077 template <class ForestType, 1078 class IteratorType = ChildIterator<typename ForestType::value_type, 1079 std::is_const_v<ForestType>>> 1080 static IteratorType parentEndImpl(ForestType &forest) { 1081 return IteratorType(nullptr, &forest.m_root, -1); 1082 } 1083 1084 template <class ForestType, 1085 class IteratorType = DepthFirstIterator<typename ForestType::value_type, 1086 Enter, 1087 std::is_const_v<ForestType>>> 1088 static IteratorType beginImpl(ForestType &forest) { 1089 return IteratorType(forest.m_root.firstChild); 1090 } 1091 1092 template <class ForestType, 1093 class IteratorType = DepthFirstIterator<typename ForestType::value_type, 1094 Enter, 1095 std::is_const_v<ForestType>>> 1096 static IteratorType endImpl(ForestType &forest) { 1097 Q_UNUSED(forest); 1098 return IteratorType(nullptr); 1099 } 1100 1101 template <class ForestType, 1102 class IteratorType = CompositionIterator<typename ForestType::value_type, 1103 std::is_const_v<ForestType>>> 1104 static IteratorType compositionBeginImpl(ForestType &forest) { 1105 return IteratorType(forest.m_root.firstChild); 1106 } 1107 1108 template <class ForestType, 1109 class IteratorType = CompositionIterator<typename ForestType::value_type, 1110 std::is_const_v<ForestType>>> 1111 static IteratorType compositionEndImpl(ForestType &forest) { 1112 Q_UNUSED(forest); 1113 return IteratorType(nullptr); 1114 } 1115 1116 private: 1117 RootNode<T> m_root; 1118 }; 1119 1120 template <typename T> 1121 typename Forest<T>::child_iterator childBegin(Forest<T> &forest) 1122 { 1123 return forest.childBegin(); 1124 } 1125 1126 template <typename T> 1127 typename Forest<T>::const_child_iterator childBegin(const Forest<T> &forest) 1128 { 1129 return forest.childBegin(); 1130 } 1131 1132 1133 template <typename T> 1134 typename Forest<T>::child_iterator childEnd(Forest<T> &forest) 1135 { 1136 return forest.childEnd(); 1137 } 1138 1139 template <typename T> 1140 typename Forest<T>::const_child_iterator childEnd(const Forest<T> &forest) 1141 { 1142 return forest.childEnd(); 1143 } 1144 1145 template <typename T> 1146 typename Forest<T>::composition_iterator compositionBegin(Forest<T> &forest) 1147 { 1148 return forest.compositionBegin(); 1149 } 1150 1151 template <typename T> 1152 typename Forest<T>::const_composition_iterator compositionBegin(const Forest<T> &forest) 1153 { 1154 return forest.compositionBegin(); 1155 } 1156 1157 1158 template <typename T> 1159 typename Forest<T>::composition_iterator compositionEnd(Forest<T> &forest) 1160 { 1161 return forest.compositionEnd(); 1162 } 1163 1164 template <typename T> 1165 typename Forest<T>::const_composition_iterator compositionEnd(const Forest<T> &forest) 1166 { 1167 return forest.compositionEnd(); 1168 } 1169 1170 1171 template <typename T> 1172 typename Forest<T>::depth_first_tail_iterator tailSubtreeBegin(Forest<T> &forest) 1173 { 1174 return forest.depthFirstTailBegin(); 1175 } 1176 1177 template <typename T> 1178 typename Forest<T>::const_depth_first_tail_iterator tailSubtreeBegin(const Forest<T> &forest) 1179 { 1180 return forest.depthFirstTailBegin(); 1181 } 1182 1183 template <typename T> 1184 typename Forest<T>::depth_first_tail_iterator tailSubtreeEnd(Forest<T> &forest) 1185 { 1186 return forest.depthFirstTailEnd(); 1187 } 1188 1189 template <typename T> 1190 typename Forest<T>::const_depth_first_tail_iterator tailSubtreeEnd(const Forest<T> &forest) 1191 { 1192 return forest.depthFirstTailEnd(); 1193 } 1194 1195 template <typename T> 1196 int depth(typename Forest<T>::const_child_iterator beginIt, 1197 typename Forest<T>::const_child_iterator endIt) 1198 { 1199 1200 int currentDepth = 0; 1201 1202 for (auto it = beginIt; it != endIt; ++it) { 1203 currentDepth = std::max(currentDepth, 1 + depth<T>(childBegin(it), childEnd(it))); 1204 } 1205 1206 return currentDepth; 1207 } 1208 1209 template <typename T> 1210 int depth(const Forest<T> &forest) { 1211 return depth<T>(childBegin(forest), childEnd(forest)); 1212 } 1213 1214 template <typename T> 1215 int size(const Forest<T> &forest) { 1216 return std::distance(begin(forest), end(forest)); 1217 } 1218 1219 using std::begin; 1220 using std::end; 1221 using std::make_reverse_iterator; 1222 1223 using std::find; 1224 using std::find_if; 1225 using std::find_if_not; 1226 } 1227 1228 template<typename T> 1229 using KisForest = KisForestDetail::Forest<T>; 1230 1231 1232 #endif // KISFOREST_H