/* * Copyright (C) 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef ElementIterator_h #define ElementIterator_h #include "ElementTraversal.h" #if !ASSERT_DISABLED #include "ElementIteratorAssertions.h" #endif namespace WebCore { template class ElementIterator { public: ElementIterator(const ContainerNode* root); ElementIterator(const ContainerNode* root, ElementType* current); ElementType& operator*() const; ElementType* operator->() const; bool operator==(const ElementIterator& other) const; bool operator!=(const ElementIterator& other) const; ElementIterator& traverseNext(); ElementIterator& traversePrevious(); ElementIterator& traverseNextSibling(); ElementIterator& traversePreviousSibling(); ElementIterator& traverseNextSkippingChildren(); ElementIterator& traverseAncestor(); void dropAssertions(); private: const ContainerNode* m_root; ElementType* m_current; #if !ASSERT_DISABLED ElementIteratorAssertions m_assertions; #endif }; template class ElementConstIterator { public: ElementConstIterator(const ContainerNode* root); ElementConstIterator(const ContainerNode* root, const ElementType* current); const ElementType& operator*() const; const ElementType* operator->() const; bool operator==(const ElementConstIterator& other) const; bool operator!=(const ElementConstIterator& other) const; ElementConstIterator& traverseNext(); ElementConstIterator& traversePrevious(); ElementConstIterator& traverseNextSibling(); ElementConstIterator& traversePreviousSibling(); ElementConstIterator& traverseNextSkippingChildren(); ElementConstIterator& traverseAncestor(); void dropAssertions(); private: const ContainerNode* m_root; const ElementType* m_current; #if !ASSERT_DISABLED ElementIteratorAssertions m_assertions; #endif }; // ElementIterator template inline ElementIterator::ElementIterator(const ContainerNode* root) : m_root(root) , m_current(nullptr) { } template inline ElementIterator::ElementIterator(const ContainerNode* root, ElementType* current) : m_root(root) , m_current(current) #if !ASSERT_DISABLED , m_assertions(current) #endif { } template inline ElementIterator& ElementIterator::traverseNext() { ASSERT(m_current); ASSERT(!m_assertions.domTreeHasMutated()); m_current = Traversal::next(*m_current, m_root); #if !ASSERT_DISABLED // Drop the assertion when the iterator reaches the end. if (!m_current) m_assertions.dropEventDispatchAssertion(); #endif return *this; } template inline ElementIterator& ElementIterator::traversePrevious() { ASSERT(m_current); ASSERT(!m_assertions.domTreeHasMutated()); m_current = Traversal::previous(*m_current, m_root); #if !ASSERT_DISABLED // Drop the assertion when the iterator reaches the end. if (!m_current) m_assertions.dropEventDispatchAssertion(); #endif return *this; } template inline ElementIterator& ElementIterator::traverseNextSibling() { ASSERT(m_current); ASSERT(!m_assertions.domTreeHasMutated()); m_current = Traversal::nextSibling(*m_current); #if !ASSERT_DISABLED // Drop the assertion when the iterator reaches the end. if (!m_current) m_assertions.dropEventDispatchAssertion(); #endif return *this; } template inline ElementIterator& ElementIterator::traversePreviousSibling() { ASSERT(m_current); ASSERT(!m_assertions.domTreeHasMutated()); m_current = Traversal::previousSibling(*m_current); #if !ASSERT_DISABLED // Drop the assertion when the iterator reaches the end. if (!m_current) m_assertions.dropEventDispatchAssertion(); #endif return *this; } template inline ElementIterator& ElementIterator::traverseNextSkippingChildren() { ASSERT(m_current); ASSERT(!m_assertions.domTreeHasMutated()); m_current = Traversal::nextSkippingChildren(*m_current, m_root); #if !ASSERT_DISABLED // Drop the assertion when the iterator reaches the end. if (!m_current) m_assertions.dropEventDispatchAssertion(); #endif return *this; } template inline void ElementIterator::dropAssertions() { #if !ASSERT_DISABLED m_assertions.clear(); #endif } template inline ElementType* findElementAncestorOfType(const Element& current) { for (Element* ancestor = current.parentElement(); ancestor; ancestor = ancestor->parentElement()) { if (is(*ancestor)) return downcast(ancestor); } return nullptr; } template <> inline Element* findElementAncestorOfType(const Element& current) { return current.parentElement(); } template inline ElementIterator& ElementIterator::traverseAncestor() { ASSERT(m_current); ASSERT(m_current != m_root); ASSERT(!m_assertions.domTreeHasMutated()); m_current = findElementAncestorOfType(*m_current); #if !ASSERT_DISABLED // Drop the assertion when the iterator reaches the end. if (!m_current) m_assertions.dropEventDispatchAssertion(); #endif return *this; } template inline ElementType& ElementIterator::operator*() const { ASSERT(m_current); ASSERT(!m_assertions.domTreeHasMutated()); return *m_current; } template inline ElementType* ElementIterator::operator->() const { ASSERT(m_current); ASSERT(!m_assertions.domTreeHasMutated()); return m_current; } template inline bool ElementIterator::operator==(const ElementIterator& other) const { ASSERT(m_root == other.m_root); ASSERT(!m_assertions.domTreeHasMutated()); return m_current == other.m_current; } template inline bool ElementIterator::operator!=(const ElementIterator& other) const { return !(*this == other); } // ElementConstIterator template inline ElementConstIterator::ElementConstIterator(const ContainerNode* root) : m_root(root) , m_current(nullptr) { } template inline ElementConstIterator::ElementConstIterator(const ContainerNode* root, const ElementType* current) : m_root(root) , m_current(current) #if !ASSERT_DISABLED , m_assertions(current) #endif { } template inline ElementConstIterator& ElementConstIterator::traverseNext() { ASSERT(m_current); ASSERT(!m_assertions.domTreeHasMutated()); m_current = Traversal::next(*m_current, m_root); #if !ASSERT_DISABLED // Drop the assertion when the iterator reaches the end. if (!m_current) m_assertions.dropEventDispatchAssertion(); #endif return *this; } template inline ElementConstIterator& ElementConstIterator::traversePrevious() { ASSERT(m_current); ASSERT(!m_assertions.domTreeHasMutated()); m_current = Traversal::previous(*m_current, m_root); #if !ASSERT_DISABLED // Drop the assertion when the iterator reaches the end. if (!m_current) m_assertions.dropEventDispatchAssertion(); #endif return *this; } template inline ElementConstIterator& ElementConstIterator::traverseNextSibling() { ASSERT(m_current); ASSERT(!m_assertions.domTreeHasMutated()); m_current = Traversal::nextSibling(*m_current); #if !ASSERT_DISABLED // Drop the assertion when the iterator reaches the end. if (!m_current) m_assertions.dropEventDispatchAssertion(); #endif return *this; } template inline ElementConstIterator& ElementConstIterator::traversePreviousSibling() { ASSERT(m_current); ASSERT(!m_assertions.domTreeHasMutated()); m_current = Traversal::previousSibling(*m_current); #if !ASSERT_DISABLED // Drop the assertion when the iterator reaches the end. if (!m_current) m_assertions.dropEventDispatchAssertion(); #endif return *this; } template inline ElementConstIterator& ElementConstIterator::traverseNextSkippingChildren() { ASSERT(m_current); ASSERT(!m_assertions.domTreeHasMutated()); m_current = Traversal::nextSkippingChildren(*m_current, m_root); #if !ASSERT_DISABLED // Drop the assertion when the iterator reaches the end. if (!m_current) m_assertions.dropEventDispatchAssertion(); #endif return *this; } template inline ElementConstIterator& ElementConstIterator::traverseAncestor() { ASSERT(m_current); ASSERT(m_current != m_root); ASSERT(!m_assertions.domTreeHasMutated()); m_current = findElementAncestorOfType(*m_current); #if !ASSERT_DISABLED // Drop the assertion when the iterator reaches the end. if (!m_current) m_assertions.dropEventDispatchAssertion(); #endif return *this; } template inline void ElementConstIterator::dropAssertions() { #if !ASSERT_DISABLED m_assertions.clear(); #endif } template inline const ElementType& ElementConstIterator::operator*() const { ASSERT(m_current); ASSERT(!m_assertions.domTreeHasMutated()); return *m_current; } template inline const ElementType* ElementConstIterator::operator->() const { ASSERT(m_current); ASSERT(!m_assertions.domTreeHasMutated()); return m_current; } template inline bool ElementConstIterator::operator==(const ElementConstIterator& other) const { ASSERT(m_root == other.m_root); ASSERT(!m_assertions.domTreeHasMutated()); return m_current == other.m_current; } template inline bool ElementConstIterator::operator!=(const ElementConstIterator& other) const { return !(*this == other); } } #include "ElementAncestorIterator.h" #include "ElementChildIterator.h" #include "TypedElementDescendantIterator.h" #endif