AncestorIterator.h (4903B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /** 8 * Implementation of some generic iterators over ancestor nodes. 9 * 10 * Note that these keep raw pointers to the nodes they iterate from, and as 11 * such the DOM should not be mutated while they're in use. There are debug 12 * assertions (via nsMutationGuard) that check this in debug builds. 13 */ 14 15 #ifndef mozilla_dom_AncestorIterator_h 16 #define mozilla_dom_AncestorIterator_h 17 18 #include "FilteredNodeIterator.h" 19 #include "nsIContentInlines.h" 20 #include "nsINode.h" 21 22 namespace mozilla::dom { 23 24 #ifdef DEBUG 25 # define MUTATION_GUARD(class_name_) \ 26 nsMutationGuard mMutationGuard; \ 27 ~class_name_() { MOZ_ASSERT(!mMutationGuard.Mutated(0)); } 28 #else 29 # define MUTATION_GUARD(class_name_) 30 #endif 31 32 #define DEFINE_ANCESTOR_ITERATOR(name_, method_) \ 33 class Inclusive##name_ { \ 34 using Self = Inclusive##name_; \ 35 \ 36 public: \ 37 explicit Inclusive##name_(const nsINode& aNode) \ 38 : mCurrent(const_cast<nsINode*>(&aNode)) {} \ 39 Self& begin() { return *this; } \ 40 std::nullptr_t end() const { return nullptr; } \ 41 bool operator!=(std::nullptr_t) const { return !!mCurrent; } \ 42 void operator++() { mCurrent = mCurrent->method_(); } \ 43 nsINode* operator*() { return mCurrent; } \ 44 \ 45 MUTATION_GUARD(Inclusive##name_) \ 46 \ 47 protected: \ 48 explicit Inclusive##name_(nsINode* aCurrent) : mCurrent(aCurrent) {} \ 49 nsINode* mCurrent; \ 50 }; \ 51 class name_ : public Inclusive##name_ { \ 52 public: \ 53 using Super = Inclusive##name_; \ 54 explicit name_(const nsINode& aNode) \ 55 : Inclusive##name_(aNode.method_()) {} \ 56 }; \ 57 template <typename T> \ 58 class name_##OfTypeIterator : public FilteredNodeIterator<T, name_> { \ 59 public: \ 60 explicit name_##OfTypeIterator(const nsINode& aNode) \ 61 : FilteredNodeIterator<T, name_>(aNode) {} \ 62 }; \ 63 template <typename T> \ 64 class Inclusive##name_##OfTypeIterator \ 65 : public FilteredNodeIterator<T, Inclusive##name_> { \ 66 public: \ 67 explicit Inclusive##name_##OfTypeIterator(const nsINode& aNode) \ 68 : FilteredNodeIterator<T, Inclusive##name_>(aNode) {} \ 69 }; 70 71 DEFINE_ANCESTOR_ITERATOR(Ancestors, GetParentNode) 72 DEFINE_ANCESTOR_ITERATOR(FlatTreeAncestors, GetFlattenedTreeParentNode) 73 74 #undef MUTATION_GUARD 75 76 } // namespace mozilla::dom 77 78 template <typename T> 79 inline mozilla::dom::AncestorsOfTypeIterator<T> nsINode::AncestorsOfType() 80 const { 81 return mozilla::dom::AncestorsOfTypeIterator<T>(*this); 82 } 83 84 template <typename T> 85 inline mozilla::dom::InclusiveAncestorsOfTypeIterator<T> 86 nsINode::InclusiveAncestorsOfType() const { 87 return mozilla::dom::InclusiveAncestorsOfTypeIterator<T>(*this); 88 } 89 90 template <typename T> 91 inline mozilla::dom::FlatTreeAncestorsOfTypeIterator<T> 92 nsINode::FlatTreeAncestorsOfType() const { 93 return mozilla::dom::FlatTreeAncestorsOfTypeIterator<T>(*this); 94 } 95 96 template <typename T> 97 inline mozilla::dom::InclusiveFlatTreeAncestorsOfTypeIterator<T> 98 nsINode::InclusiveFlatTreeAncestorsOfType() const { 99 return mozilla::dom::InclusiveFlatTreeAncestorsOfTypeIterator<T>(*this); 100 } 101 102 template <typename T> 103 inline T* nsINode::FirstAncestorOfType() const { 104 return *(AncestorsOfType<T>()); 105 } 106 107 #endif // mozilla_dom_AncestorIterator.h