11 #include <Sawyer/Assert.h>
12 #include <Sawyer/Optional.h>
18 #if 1 // DEBUGGING [Robb Matzke 2019-02-18]
139 : std::runtime_error(mesg) {}
159 const std::string &mesg =
"attempt to attach child that already has a different parent")
237 ASSERT_not_null(
shared());
242 explicit operator bool()
const {
243 return shared() !=
nullptr;
247 std::shared_ptr<T>
shared()
const;
250 operator std::shared_ptr<T>()
const {
256 void assign(
const NodePtr &child);
274 : parent_(
nullptr) {}
283 ASSERT_not_null(parent_);
291 explicit operator bool()
const {
292 return parent_ !=
nullptr;
295 #if 0 // [Robb Matzke 2019-02-18]: Node is not declared yet?
297 operator std::shared_ptr<Node>
const {
317 void set(
Node *parent) {
340 std::vector<NodePtr > children_;
353 return children_.size();
358 return children_.max_size();
363 return children_.capacity();
368 return children_.empty();
373 children_.reserve(n);
378 children_.shrink_to_fit();
383 ASSERT_require(idx < children_.size());
384 return children_.at(idx);
389 ASSERT_require(idx < children_.size());
390 return children_[idx];
395 ASSERT_forbid(
empty());
396 return children_.front();
401 ASSERT_forbid(
empty());
402 return children_.back();
406 const std::vector<NodePtr >&
elmts()
const {
425 template<
class T>
friend class ListNode;
426 template<
class T>
friend class ChildEdge;
433 void setAt(
size_t idx,
const NodePtr &newChild);
434 void setAt(
size_t idx, std::nullptr_t) {
440 void checkInsertionConsistency(
const NodePtr &newChild,
const NodePtr &oldChild, Node *parent);
444 void insertAt(
size_t idx,
const NodePtr &child);
447 void eraseAt(
size_t idx);
453 size_t appendEdge(
const NodePtr &child);
479 class Node:
public std::enable_shared_from_this<Node> {
481 enum TraversalDirection { TRAVERSE_UPWARD, TRAVERSE_DOWNWARD };
498 Node& operator=(
const Node&) =
delete;
515 template<
class Functor>
517 return traverseImpl<Functor>(TRAVERSE_DOWNWARD, functor);
519 template<
class Functor>
521 return traverseImpl<Functor>(TRAVERSE_DOWNWARD, functor);
530 template<
class T,
class Functor>
532 template<
class T,
class Functor>
542 template<
class Functor>
544 return traverseImpl<Functor>(TRAVERSE_UPWARD, functor);
546 template<
class Functor>
548 return traverseImpl<Functor>(TRAVERSE_UPWARD, functor);
555 template<
class Predicate>
557 return findImpl<Node, Predicate>(TRAVERSE_DOWNWARD, predicate);
559 template<
class Predicate>
561 return findImpl<Node, Predicate>(TRAVERSE_DOWNWARD, predicate);
570 return findImpl<T>(TRAVERSE_DOWNWARD, [](
const std::shared_ptr<T>&) {
return true; });
574 return findImpl<T>(TRAVERSE_DOWNWARD, [](
const std::shared_ptr<T>&) {
return true; });
581 template<
class T,
class Predicate>
583 return findImpl<T, Predicate>(TRAVERSE_DOWNWARD, predicate);
585 template<
class T,
class Predicate>
586 std::shared_ptr<T>
findType(Predicate predicate)
const {
587 return findImpl<T, Predicate>(TRAVERSE_DOWNWARD, predicate);
594 template<
class Predicate>
596 return findImpl<Node, Predicate>(TRAVERSE_UPWARD, predicate);
598 template<
class Predicate>
600 return findImpl<Node, Predicate>(TRAVERSE_UPWARD, predicate);
609 return findImpl<T>(TRAVERSE_UPWARD, [](
const std::shared_ptr<T>&) {
return true; });
613 return findImpl<T>(TRAVERSE_UPWARD, [](
const std::shared_ptr<T>&) {
return true; });
620 template<
class T,
class Predicate>
622 return findImpl<T, Predicate>(TRAVERSE_UPWARD, predicate);
624 template<
class T,
class Predicate>
626 return findImpl<T, Predicate>(TRAVERSE_UPWARD, predicate);
632 template<
class Functor>
634 template<
class Functor>
638 template<
class T,
class Predicate>
639 std::shared_ptr<T> findImpl(TraversalDirection, Predicate);
640 template<
class T,
class Predicate>
641 std::shared_ptr<T> findImpl(TraversalDirection, Predicate)
const;
736 const std::shared_ptr<T>
at(
size_t i)
const {
737 return std::dynamic_pointer_cast<T>(
children.
at(i));
742 return std::dynamic_pointer_cast<T>(
children[i]);
746 const std::shared_ptr<T>
front()
const {
751 const std::shared_ptr<T>
back()
const {
756 std::vector<std::shared_ptr<T> >
elmts()
const;
781 void setAt(
size_t i,
const std::shared_ptr<T> &child) {
784 void setAt(
size_t i, std::nullptr_t) {
794 void insertAt(
size_t i,
const std::shared_ptr<T> &newChild) {
823 template<
class T,
class U>
bool operator==(
const ChildEdge<T> &lhs,
const ChildEdge<U> &rhs) noexcept {
return lhs.shared() == rhs.shared(); }
824 template<
class T,
class U>
bool operator!=(
const ChildEdge<T> &lhs,
const ChildEdge<U> &rhs) noexcept {
return lhs.shared() != rhs.shared(); }
825 template<
class T,
class U>
bool operator< (
const ChildEdge<T> &lhs,
const ChildEdge<U> &rhs) noexcept {
return lhs.shared() < rhs.shared(); }
826 template<
class T,
class U>
bool operator<=(
const ChildEdge<T> &lhs,
const ChildEdge<U> &rhs) noexcept {
return lhs.shared() <= rhs.shared(); }
827 template<
class T,
class U>
bool operator> (
const ChildEdge<T> &lhs,
const ChildEdge<U> &rhs) noexcept {
return lhs.shared() > rhs.shared(); }
828 template<
class T,
class U>
bool operator>=(
const ChildEdge<T> &lhs,
const ChildEdge<U> &rhs) noexcept {
return lhs.shared() >= rhs.shared(); }
831 template<
class T>
bool operator==(
const ChildEdge<T> &lhs, std::nullptr_t) noexcept {
return lhs.shared() ==
nullptr; }
832 template<
class T>
bool operator!=(
const ChildEdge<T> &lhs, std::nullptr_t) noexcept {
return lhs.shared() !=
nullptr; }
833 template<
class T>
bool operator< (
const ChildEdge<T> &lhs, std::nullptr_t) noexcept {
return lhs.shared() <
nullptr; }
834 template<
class T>
bool operator<=(
const ChildEdge<T> &lhs, std::nullptr_t) noexcept {
return lhs.shared() <=
nullptr; }
835 template<
class T>
bool operator> (
const ChildEdge<T> &lhs, std::nullptr_t) noexcept {
return lhs.shared() >
nullptr; }
836 template<
class T>
bool operator>=(
const ChildEdge<T> &lhs, std::nullptr_t) noexcept {
return lhs.shared() >=
nullptr; }
839 template<
class T>
bool operator==(std::nullptr_t,
const ChildEdge<T> &rhs) noexcept {
return nullptr == rhs.shared(); }
840 template<
class T>
bool operator!=(std::nullptr_t,
const ChildEdge<T> &rhs) noexcept {
return nullptr != rhs.shared(); }
841 template<
class T>
bool operator< (std::nullptr_t,
const ChildEdge<T> &rhs) noexcept {
return nullptr < rhs.shared(); }
842 template<
class T>
bool operator<=(std::nullptr_t,
const ChildEdge<T> &rhs) noexcept {
return nullptr <= rhs.shared(); }
843 template<
class T>
bool operator> (std::nullptr_t,
const ChildEdge<T> &rhs) noexcept {
return nullptr > rhs.shared(); }
844 template<
class T>
bool operator>=(std::nullptr_t,
const ChildEdge<T> &rhs) noexcept {
return nullptr >= rhs.shared(); }
847 template<
class T,
class U>
bool operator==(
const ChildEdge<T> &lhs,
const std::shared_ptr<U> &rhs) noexcept {
return lhs.shared() == rhs; }
848 template<
class T,
class U>
bool operator!=(
const ChildEdge<T> &lhs,
const std::shared_ptr<U> &rhs) noexcept {
return lhs.shared() != rhs; }
849 template<
class T,
class U>
bool operator< (
const ChildEdge<T> &lhs,
const std::shared_ptr<U> &rhs) noexcept {
return lhs.shared() < rhs; }
850 template<
class T,
class U>
bool operator<=(
const ChildEdge<T> &lhs,
const std::shared_ptr<U> &rhs) noexcept {
return lhs.shared() <= rhs; }
851 template<
class T,
class U>
bool operator> (
const ChildEdge<T> &lhs,
const std::shared_ptr<U> &rhs) noexcept {
return lhs.shared() > rhs; }
852 template<
class T,
class U>
bool operator>=(
const ChildEdge<T> &lhs,
const std::shared_ptr<U> &rhs) noexcept {
return lhs.shared() >= rhs; }
855 template<
class T,
class U>
bool operator==(
const std::shared_ptr<T> &lhs,
const ChildEdge<U> &rhs) noexcept {
return lhs == rhs.shared(); }
856 template<
class T,
class U>
bool operator!=(
const std::shared_ptr<T> &lhs,
const ChildEdge<U> &rhs) noexcept {
return lhs != rhs.shared(); }
857 template<
class T,
class U>
bool operator< (
const std::shared_ptr<T> &lhs,
const ChildEdge<U> &rhs) noexcept {
return lhs < rhs.shared(); }
858 template<
class T,
class U>
bool operator<=(
const std::shared_ptr<T> &lhs,
const ChildEdge<U> &rhs) noexcept {
return lhs <= rhs.shared(); }
859 template<
class T,
class U>
bool operator> (
const std::shared_ptr<T> &lhs,
const ChildEdge<U> &rhs) noexcept {
return lhs > rhs.shared(); }
860 template<
class T,
class U>
bool operator>=(
const std::shared_ptr<T> &lhs,
const ChildEdge<U> &rhs) noexcept {
return lhs >= rhs.shared(); }
863 inline bool operator==(
const ParentEdge &lhs, std::nullptr_t) noexcept {
return lhs.shared() ==
nullptr; }
864 inline bool operator!=(
const ParentEdge &lhs, std::nullptr_t) noexcept {
return lhs.shared() !=
nullptr; }
865 inline bool operator< (
const ParentEdge &lhs, std::nullptr_t) noexcept {
return lhs.shared() <
nullptr; }
866 inline bool operator<=(
const ParentEdge &lhs, std::nullptr_t) noexcept {
return lhs.shared() <=
nullptr; }
867 inline bool operator> (
const ParentEdge &lhs, std::nullptr_t) noexcept {
return lhs.shared() >
nullptr; }
868 inline bool operator>=(
const ParentEdge &lhs, std::nullptr_t) noexcept {
return lhs.shared() >=
nullptr; }
871 inline bool operator==(std::nullptr_t,
const ParentEdge &rhs) noexcept {
return nullptr == rhs.shared(); }
872 inline bool operator!=(std::nullptr_t,
const ParentEdge &rhs) noexcept {
return nullptr != rhs.shared(); }
873 inline bool operator< (std::nullptr_t,
const ParentEdge &rhs) noexcept {
return nullptr < rhs.shared(); }
874 inline bool operator<=(std::nullptr_t,
const ParentEdge &rhs) noexcept {
return nullptr <= rhs.shared(); }
875 inline bool operator> (std::nullptr_t,
const ParentEdge &rhs) noexcept {
return nullptr > rhs.shared(); }
876 inline bool operator>=(std::nullptr_t,
const ParentEdge &rhs) noexcept {
return nullptr >= rhs.shared(); }
879 template<
class T>
bool operator==(
const ParentEdge &lhs,
const std::shared_ptr<T> &rhs) noexcept {
return lhs.shared() == rhs; }
880 template<
class T>
bool operator!=(
const ParentEdge &lhs,
const std::shared_ptr<T> &rhs) noexcept {
return lhs.shared() != rhs; }
881 template<
class T>
bool operator< (
const ParentEdge &lhs,
const std::shared_ptr<T> &rhs) noexcept {
return lhs.shared() < rhs; }
882 template<
class T>
bool operator<=(
const ParentEdge &lhs,
const std::shared_ptr<T> &rhs) noexcept {
return lhs.shared() <= rhs; }
883 template<
class T>
bool operator> (
const ParentEdge &lhs,
const std::shared_ptr<T> &rhs) noexcept {
return lhs.shared() > rhs; }
884 template<
class T>
bool operator>=(
const ParentEdge &lhs,
const std::shared_ptr<T> &rhs) noexcept {
return lhs.shared() >= rhs; }
887 template<
class T>
bool operator==(
const std::shared_ptr<T> &lhs,
const ParentEdge &rhs) noexcept {
return lhs == rhs.shared(); }
888 template<
class T>
bool operator!=(
const std::shared_ptr<T> &lhs,
const ParentEdge &rhs) noexcept {
return lhs != rhs.shared(); }
889 template<
class T>
bool operator< (
const std::shared_ptr<T> &lhs,
const ParentEdge &rhs) noexcept {
return lhs < rhs.shared(); }
890 template<
class T>
bool operator<=(
const std::shared_ptr<T> &lhs,
const ParentEdge &rhs) noexcept {
return lhs <= rhs.shared(); }
891 template<
class T>
bool operator> (
const std::shared_ptr<T> &lhs,
const ParentEdge &rhs) noexcept {
return lhs > rhs.shared(); }
892 template<
class T>
bool operator>=(
const std::shared_ptr<T> &lhs,
const ParentEdge &rhs) noexcept {
return lhs >= rhs.shared(); }
895 template<
class T>
bool operator==(
const ParentEdge &lhs,
const ChildEdge<T> &rhs) noexcept {
return lhs.shared() == rhs.shared(); }
896 template<
class T>
bool operator!=(
const ParentEdge &lhs,
const ChildEdge<T> &rhs) noexcept {
return lhs.shared() != rhs.shared(); }
897 template<
class T>
bool operator< (
const ParentEdge &lhs,
const ChildEdge<T> &rhs) noexcept {
return lhs.shared() < rhs.shared(); }
898 template<
class T>
bool operator<=(
const ParentEdge &lhs,
const ChildEdge<T> &rhs) noexcept {
return lhs.shared() <= rhs.shared(); }
899 template<
class T>
bool operator> (
const ParentEdge &lhs,
const ChildEdge<T> &rhs) noexcept {
return lhs.shared() > rhs.shared(); }
900 template<
class T>
bool operator>=(
const ParentEdge &lhs,
const ChildEdge<T> &rhs) noexcept {
return lhs.shared() >= rhs.shared(); }
903 template<
class T>
bool operator==(
const ChildEdge<T> &lhs,
const ParentEdge &rhs) noexcept {
return lhs.shared() == rhs.shared(); }
904 template<
class T>
bool operator!=(
const ChildEdge<T> &lhs,
const ParentEdge &rhs) noexcept {
return lhs.shared() != rhs.shared(); }
905 template<
class T>
bool operator< (
const ChildEdge<T> &lhs,
const ParentEdge &rhs) noexcept {
return lhs.shared() < rhs.shared(); }
906 template<
class T>
bool operator<=(
const ChildEdge<T> &lhs,
const ParentEdge &rhs) noexcept {
return lhs.shared() <= rhs.shared(); }
907 template<
class T>
bool operator> (
const ChildEdge<T> &lhs,
const ParentEdge &rhs) noexcept {
return lhs.shared() > rhs.shared(); }
908 template<
class T>
bool operator>=(
const ChildEdge<T> &lhs,
const ParentEdge &rhs) noexcept {
return lhs.shared() >= rhs.shared(); }
926 : container_(container), idx_(container->children.appendEdge(nullptr)) {
927 ASSERT_not_null(container_);
932 : container_(container), idx_(container->children.appendEdge(child)) {
933 ASSERT_not_null(container_);
939 return std::dynamic_pointer_cast<T>(container_->
children[this->idx_]);
945 container_->
children.setAt(idx_, newChild);
954 return parent_ ? parent_->shared_from_this() :
NodePtr();
961 Children::Children(
Node *container)
962 : container_(container) {
963 ASSERT_not_null(container);
967 Children::appendEdge(
const NodePtr &child) {
968 size_t idx = children_.size();
969 children_.push_back(
nullptr);
975 Children::checkInsertionConsistency(
const NodePtr &newChild,
const NodePtr &oldChild, Node *parent) {
976 ASSERT_not_null(parent);
978 if (newChild && newChild != oldChild) {
979 if (newChild->parent !=
nullptr) {
980 if (newChild->parent.shared().get() == parent) {
981 throw ConsistencyException(newChild,
"node is already a child of the parent");
983 throw ConsistencyException(newChild,
"node is already attached to a tree");
989 throw ConsistencyException(newChild,
"node insertion would introduce a cycle");
995 Children::setAt(
size_t idx,
const NodePtr &newChild) {
996 ASSERT_require(idx < children_.size());
997 NodePtr oldChild = children_[idx];
998 checkInsertionConsistency(newChild, oldChild, container_);
1000 oldChild->parent.reset();
1001 children_[idx] = newChild;
1003 newChild->parent.set(container_);
1007 Children::insertAt(
size_t idx,
const NodePtr &child) {
1008 ASSERT_require(idx <= children_.size());
1009 checkInsertionConsistency(child,
nullptr, container_);
1010 children_.insert(children_.begin() + idx, child);
1012 child->parent.set(container_);
1016 Children::eraseAt(
size_t idx) {
1017 ASSERT_require(idx < children_.size());
1019 children_[idx]->parent.reset();
1020 children_.erase(children_.begin() + idx);
1025 while (!children_.empty()) {
1026 if (children_.back())
1027 children_.back()->parent.reset();
1028 children_.pop_back();
1039 template<
class Functor>
1041 Node::traverseImpl(TraversalDirection direction, Functor functor) {
1044 if (TRAVERSE_DOWNWARD == direction) {
1062 template<
class Functor>
1064 Node::traverseImpl(TraversalDirection direction, Functor functor)
const {
1067 if (TRAVERSE_DOWNWARD == direction) {
1089 template<
class T,
class Functor>
1094 : functor(functor) {}
1097 if (std::shared_ptr<T> typed = std::dynamic_pointer_cast<T>(node)) {
1098 return functor(typed, event);
1105 template<
class T,
class Functor>
1111 template<
class T,
class Functor>
1120 template<
class T,
class Predicate>
1122 Node::findImpl(TraversalDirection direction, Predicate predicate) {
1123 std::shared_ptr<T> found;
1124 traverseImpl(direction,
1126 if (
ENTER == event) {
1127 std::shared_ptr<T> typedNode = std::dynamic_pointer_cast<T>(node);
1128 if (typedNode && predicate(typedNode)) {
1138 template<
class T,
class Predicate>
1140 Node::findImpl(TraversalDirection direction, Predicate predicate)
const {
1141 std::shared_ptr<T> found;
1142 traverseImpl(direction,
1144 if (
ENTER == event) {
1145 std::shared_ptr<const T> typedNode = std::dynamic_pointer_cast<const T>(node);
1146 if (typedNode && predicate(typedNode)) {
1161 std::vector<std::shared_ptr<T> >
1163 std::vector<std::shared_ptr<T> > retval;
1164 retval.reserve(children.size());
1165 for (
size_t i = 0; i < children.size(); ++i)
1166 retval.push_back(std::dynamic_pointer_cast<T>(children[i]));
1173 for (
size_t i = startAt; i < children.size(); ++i) {
1174 if (children[i] == node)
1185 children.eraseAt(*where);