ElementDescendantIterator.h [plain text]
#ifndef ElementDescendantIterator_h
#define ElementDescendantIterator_h
#include "Element.h"
#include "ElementIteratorAssertions.h"
#include "ElementTraversal.h"
#include <wtf/Vector.h>
namespace WebCore {
class ElementDescendantIterator {
public:
ElementDescendantIterator();
explicit ElementDescendantIterator(Element* current);
ElementDescendantIterator& operator++();
ElementDescendantIterator& operator--();
Element& operator*();
Element* operator->();
bool operator==(const ElementDescendantIterator& other) const;
bool operator!=(const ElementDescendantIterator& other) const;
private:
Element* m_current;
Vector<Element*, 16, UnsafeVectorOverflow> m_ancestorSiblingStack;
#if !ASSERT_DISABLED
ElementIteratorAssertions m_assertions;
#endif
};
class ElementDescendantConstIterator {
public:
ElementDescendantConstIterator();
explicit ElementDescendantConstIterator(const Element*);
ElementDescendantConstIterator& operator++();
const Element& operator*() const;
const Element* operator->() const;
bool operator==(const ElementDescendantConstIterator& other) const;
bool operator!=(const ElementDescendantConstIterator& other) const;
private:
const Element* m_current;
Vector<Element*, 16, UnsafeVectorOverflow> m_ancestorSiblingStack;
#if !ASSERT_DISABLED
ElementIteratorAssertions m_assertions;
#endif
};
class ElementDescendantIteratorAdapter {
public:
ElementDescendantIteratorAdapter(ContainerNode& root);
ElementDescendantIterator begin();
ElementDescendantIterator end();
ElementDescendantIterator last();
private:
ContainerNode& m_root;
};
class ElementDescendantConstIteratorAdapter {
public:
ElementDescendantConstIteratorAdapter(const ContainerNode& root);
ElementDescendantConstIterator begin() const;
ElementDescendantConstIterator end() const;
ElementDescendantConstIterator last() const;
private:
const ContainerNode& m_root;
};
ElementDescendantIteratorAdapter elementDescendants(ContainerNode&);
ElementDescendantConstIteratorAdapter elementDescendants(const ContainerNode&);
inline ElementDescendantIterator::ElementDescendantIterator()
: m_current(nullptr)
{
}
inline ElementDescendantIterator::ElementDescendantIterator(Element* current)
: m_current(current)
{
m_ancestorSiblingStack.uncheckedAppend(nullptr);
}
ALWAYS_INLINE ElementDescendantIterator& ElementDescendantIterator::operator++()
{
ASSERT(m_current);
ASSERT(!m_assertions.domTreeHasMutated());
Element* firstChild = ElementTraversal::firstChild(m_current);
Element* nextSibling = ElementTraversal::nextSibling(m_current);
if (firstChild) {
if (nextSibling)
m_ancestorSiblingStack.append(nextSibling);
m_current = firstChild;
return *this;
}
if (nextSibling) {
m_current = nextSibling;
return *this;
}
m_current = m_ancestorSiblingStack.takeLast();
#if !ASSERT_DISABLED
if (!m_current)
m_assertions.dropEventDispatchAssertion();
#endif
return *this;
}
ALWAYS_INLINE ElementDescendantIterator& ElementDescendantIterator::operator--()
{
ASSERT(m_current);
ASSERT(!m_assertions.domTreeHasMutated());
Element* previousSibling = ElementTraversal::previousSibling(m_current);
if (!previousSibling) {
m_current = m_current->parentElement();
if (m_current->nextSibling() == m_ancestorSiblingStack.last())
m_ancestorSiblingStack.removeLast();
return *this;
}
Element* deepestSibling = previousSibling;
while (Element* lastChild = ElementTraversal::lastChild(deepestSibling))
deepestSibling = lastChild;
ASSERT(deepestSibling);
if (deepestSibling != previousSibling)
m_ancestorSiblingStack.append(m_current);
m_current = deepestSibling;
#if !ASSERT_DISABLED
if (!m_current)
m_assertions.dropEventDispatchAssertion();
#endif
return *this;
}
inline Element& ElementDescendantIterator::operator*()
{
ASSERT(m_current);
ASSERT(!m_assertions.domTreeHasMutated());
return *m_current;
}
inline Element* ElementDescendantIterator::operator->()
{
ASSERT(m_current);
ASSERT(!m_assertions.domTreeHasMutated());
return m_current;
}
inline bool ElementDescendantIterator::operator==(const ElementDescendantIterator& other) const
{
ASSERT(!m_assertions.domTreeHasMutated());
return m_current == other.m_current;
}
inline bool ElementDescendantIterator::operator!=(const ElementDescendantIterator& other) const
{
return !(*this == other);
}
inline ElementDescendantConstIterator::ElementDescendantConstIterator()
: m_current(nullptr)
{
}
inline ElementDescendantConstIterator::ElementDescendantConstIterator(const Element* current)
: m_current(current)
{
m_ancestorSiblingStack.uncheckedAppend(nullptr);
}
ALWAYS_INLINE ElementDescendantConstIterator& ElementDescendantConstIterator::operator++()
{
ASSERT(m_current);
ASSERT(!m_assertions.domTreeHasMutated());
Element* firstChild = ElementTraversal::firstChild(m_current);
Element* nextSibling = ElementTraversal::nextSibling(m_current);
if (firstChild) {
if (nextSibling)
m_ancestorSiblingStack.append(nextSibling);
m_current = firstChild;
return *this;
}
if (nextSibling) {
m_current = nextSibling;
return *this;
}
m_current = m_ancestorSiblingStack.takeLast();
#if !ASSERT_DISABLED
if (!m_current)
m_assertions.dropEventDispatchAssertion();
#endif
return *this;
}
inline const Element& ElementDescendantConstIterator::operator*() const
{
ASSERT(m_current);
ASSERT(!m_assertions.domTreeHasMutated());
return *m_current;
}
inline const Element* ElementDescendantConstIterator::operator->() const
{
ASSERT(m_current);
ASSERT(!m_assertions.domTreeHasMutated());
return m_current;
}
inline bool ElementDescendantConstIterator::operator==(const ElementDescendantConstIterator& other) const
{
ASSERT(!m_assertions.domTreeHasMutated());
return m_current == other.m_current;
}
inline bool ElementDescendantConstIterator::operator!=(const ElementDescendantConstIterator& other) const
{
return !(*this == other);
}
inline ElementDescendantIteratorAdapter::ElementDescendantIteratorAdapter(ContainerNode& root)
: m_root(root)
{
}
inline ElementDescendantIterator ElementDescendantIteratorAdapter::begin()
{
return ElementDescendantIterator(ElementTraversal::firstChild(&m_root));
}
inline ElementDescendantIterator ElementDescendantIteratorAdapter::end()
{
return ElementDescendantIterator();
}
inline ElementDescendantIterator ElementDescendantIteratorAdapter::last()
{
return ElementDescendantIterator(ElementTraversal::lastWithin(&m_root));
}
inline ElementDescendantConstIteratorAdapter::ElementDescendantConstIteratorAdapter(const ContainerNode& root)
: m_root(root)
{
}
inline ElementDescendantConstIterator ElementDescendantConstIteratorAdapter::begin() const
{
return ElementDescendantConstIterator(ElementTraversal::firstChild(&m_root));
}
inline ElementDescendantConstIterator ElementDescendantConstIteratorAdapter::end() const
{
return ElementDescendantConstIterator();
}
inline ElementDescendantConstIterator ElementDescendantConstIteratorAdapter::last() const
{
return ElementDescendantConstIterator(ElementTraversal::lastWithin(&m_root));
}
inline ElementDescendantIteratorAdapter elementDescendants(ContainerNode& root)
{
return ElementDescendantIteratorAdapter(root);
}
inline ElementDescendantConstIteratorAdapter elementDescendants(const ContainerNode& root)
{
return ElementDescendantConstIteratorAdapter(root);
}
}
namespace std {
template <> struct iterator_traits<WebCore::ElementDescendantIterator> {
typedef WebCore::Element value_type;
};
template <> struct iterator_traits<WebCore::ElementDescendantConstIterator> {
typedef const WebCore::Element value_type;
};
}
#endif