/* * 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 RenderIterator_h #define RenderIterator_h #include "RenderElement.h" namespace WebCore { template class RenderIterator { public: RenderIterator(const RenderElement* root); RenderIterator(const RenderElement* root, T* current); T& operator*(); T* operator->(); bool operator==(const RenderIterator& other) const; bool operator!=(const RenderIterator& other) const; RenderIterator& traverseNextSibling(); RenderIterator& traversePreviousSibling(); RenderIterator& traverseAncestor(); private: const RenderElement* m_root; T* m_current; }; template class RenderConstIterator { public: RenderConstIterator(const RenderElement* root); RenderConstIterator(const RenderElement* root, const T* current); const T& operator*() const; const T* operator->() const; bool operator==(const RenderConstIterator& other) const; bool operator!=(const RenderConstIterator& other) const; RenderConstIterator& traverseNextSibling(); RenderConstIterator& traversePreviousSibling(); RenderConstIterator& traverseAncestor(); private: const RenderElement* m_root; const T* m_current; }; // Similar to WTF::is<>() but without the static_assert() making sure the check is necessary. template inline bool isRendererOfType(const U& renderer) { return TypeCastTraits::isOfType(renderer); } // Traversal helpers namespace RenderTraversal { template inline T* firstChild(U& current) { RenderObject* object = current.firstChild(); while (object && !isRendererOfType(*object)) object = object->nextSibling(); return static_cast(object); } template inline T* lastChild(U& current) { RenderObject* object = current.lastChild(); while (object && !isRendererOfType(*object)) object = object->previousSibling(); return static_cast(object); } template inline T* nextSibling(U& current) { RenderObject* object = current.nextSibling(); while (object && !isRendererOfType(*object)) object = object->nextSibling(); return static_cast(object); } template inline T* previousSibling(U& current) { RenderObject* object = current.previousSibling(); while (object && !isRendererOfType(*object)) object = object->previousSibling(); return static_cast(object); } template inline T* findAncestorOfType(const RenderObject& current) { for (auto* ancestor = current.parent(); ancestor; ancestor = ancestor->parent()) { if (isRendererOfType(*ancestor)) return static_cast(ancestor); } return nullptr; } } // namespace WebCore::RenderTraversal // RenderIterator template inline RenderIterator::RenderIterator(const RenderElement* root) : m_root(root) , m_current(nullptr) { } template inline RenderIterator::RenderIterator(const RenderElement* root, T* current) : m_root(root) , m_current(current) { } template inline RenderIterator& RenderIterator::traverseNextSibling() { ASSERT(m_current); m_current = RenderTraversal::nextSibling(*m_current); return *this; } template inline RenderIterator& RenderIterator::traversePreviousSibling() { ASSERT(m_current); m_current = RenderTraversal::previousSibling(*m_current); return *this; } template inline RenderIterator& RenderIterator::traverseAncestor() { ASSERT(m_current); ASSERT(m_current != m_root); m_current = RenderTraversal::findAncestorOfType(*m_current); return *this; } template inline T& RenderIterator::operator*() { ASSERT(m_current); return *m_current; } template inline T* RenderIterator::operator->() { ASSERT(m_current); return m_current; } template inline bool RenderIterator::operator==(const RenderIterator& other) const { ASSERT(m_root == other.m_root); return m_current == other.m_current; } template inline bool RenderIterator::operator!=(const RenderIterator& other) const { return !(*this == other); } // RenderConstIterator template inline RenderConstIterator::RenderConstIterator(const RenderElement* root) : m_root(root) , m_current(nullptr) { } template inline RenderConstIterator::RenderConstIterator(const RenderElement* root, const T* current) : m_root(root) , m_current(current) { } template inline RenderConstIterator& RenderConstIterator::traverseNextSibling() { ASSERT(m_current); m_current = RenderTraversal::nextSibling(*m_current); return *this; } template inline RenderConstIterator& RenderConstIterator::traversePreviousSibling() { ASSERT(m_current); m_current = RenderTraversal::previousSibling(m_current); return *this; } template inline RenderConstIterator& RenderConstIterator::traverseAncestor() { ASSERT(m_current); ASSERT(m_current != m_root); m_current = RenderTraversal::findAncestorOfType(*m_current); return *this; } template inline const T& RenderConstIterator::operator*() const { ASSERT(m_current); return *m_current; } template inline const T* RenderConstIterator::operator->() const { ASSERT(m_current); return m_current; } template inline bool RenderConstIterator::operator==(const RenderConstIterator& other) const { ASSERT(m_root == other.m_root); return m_current == other.m_current; } template inline bool RenderConstIterator::operator!=(const RenderConstIterator& other) const { return !(*this == other); } } #include "RenderAncestorIterator.h" #include "RenderChildIterator.h" #endif