ComposedTreeIterator.h [plain text]
#include "ElementAndTextDescendantIterator.h"
#include "ShadowRoot.h"
#ifndef ComposedTreeIterator_h
#define ComposedTreeIterator_h
namespace WebCore {
class HTMLSlotElement;
class ComposedTreeIterator {
public:
ComposedTreeIterator();
enum FirstChildTag { FirstChild };
ComposedTreeIterator(ContainerNode& root, FirstChildTag);
ComposedTreeIterator(ContainerNode& root, Node& current);
Node& operator*() { return current(); }
Node* operator->() { return ¤t(); }
bool operator==(const ComposedTreeIterator& other) const { return context().iterator == other.context().iterator; }
bool operator!=(const ComposedTreeIterator& other) const { return context().iterator != other.context().iterator; }
ComposedTreeIterator& operator++() { return traverseNext(); }
ComposedTreeIterator& traverseNext();
ComposedTreeIterator& traverseNextSkippingChildren();
ComposedTreeIterator& traverseNextSibling();
ComposedTreeIterator& traversePreviousSibling();
unsigned depth() const;
void dropAssertions();
private:
void initializeContextStack(ContainerNode& root, Node& current);
void traverseNextInShadowTree();
void traverseNextLeavingContext();
void traverseShadowRoot(ShadowRoot&);
bool advanceInSlot(int direction);
void traverseSiblingInSlot(int direction);
struct Context {
Context();
Context(ContainerNode& root, FirstChildTag);
Context(ContainerNode& root, Node& node);
enum SlottedTag { Slotted };
Context(ContainerNode& root, Node& node, SlottedTag);
ElementAndTextDescendantIterator iterator;
ElementAndTextDescendantIterator end;
size_t slotNodeIndex { notFound };
};
Context& context() { return m_contextStack.last(); }
const Context& context() const { return m_contextStack.last(); }
Node& current() { return *context().iterator; }
bool m_didDropAssertions { false };
Vector<Context, 8> m_contextStack;
};
inline ComposedTreeIterator::ComposedTreeIterator()
{
m_contextStack.uncheckedAppend({ });
}
inline ComposedTreeIterator& ComposedTreeIterator::traverseNext()
{
if (auto* shadowRoot = context().iterator->shadowRoot()) {
traverseShadowRoot(*shadowRoot);
return *this;
}
if (m_contextStack.size() > 1) {
traverseNextInShadowTree();
return *this;
}
context().iterator.traverseNext();
return *this;
}
inline ComposedTreeIterator& ComposedTreeIterator::traverseNextSkippingChildren()
{
context().iterator.traverseNextSkippingChildren();
if (context().iterator == context().end && m_contextStack.size() > 1)
traverseNextLeavingContext();
return *this;
}
inline ComposedTreeIterator& ComposedTreeIterator::traverseNextSibling()
{
if (current().parentNode()->shadowRoot()) {
traverseSiblingInSlot(1);
return *this;
}
context().iterator.traverseNextSibling();
return *this;
}
inline ComposedTreeIterator& ComposedTreeIterator::traversePreviousSibling()
{
if (current().parentNode()->shadowRoot()) {
traverseSiblingInSlot(-1);
return *this;
}
context().iterator.traversePreviousSibling();
return *this;
}
inline unsigned ComposedTreeIterator::depth() const
{
unsigned depth = 0;
for (auto& context : m_contextStack)
depth += context.iterator.depth();
return depth;
}
class ComposedTreeDescendantAdapter {
public:
ComposedTreeDescendantAdapter(ContainerNode& parent)
: m_parent(parent)
{ }
ComposedTreeIterator begin() { return ComposedTreeIterator(m_parent, ComposedTreeIterator::FirstChild); }
ComposedTreeIterator end() { return { }; }
ComposedTreeIterator at(const Node& child) { return ComposedTreeIterator(m_parent, const_cast<Node&>(child)); }
private:
ContainerNode& m_parent;
};
class ComposedTreeChildAdapter {
public:
class Iterator : public ComposedTreeIterator {
public:
Iterator() = default;
explicit Iterator(ContainerNode& root)
: ComposedTreeIterator(root, ComposedTreeIterator::FirstChild)
{ }
Iterator(ContainerNode& root, Node& current)
: ComposedTreeIterator(root, current)
{ }
Iterator& operator++() { return static_cast<Iterator&>(traverseNextSibling()); }
Iterator& operator--() { return static_cast<Iterator&>(traversePreviousSibling()); }
};
ComposedTreeChildAdapter(ContainerNode& parent)
: m_parent(parent)
{ }
Iterator begin() { return Iterator(m_parent); }
Iterator end() { return { }; }
Iterator at(const Node& child) { return Iterator(m_parent, const_cast<Node&>(child)); }
private:
ContainerNode& m_parent;
};
inline ComposedTreeDescendantAdapter composedTreeDescendants(ContainerNode& parent)
{
return ComposedTreeDescendantAdapter(parent);
}
inline ComposedTreeChildAdapter composedTreeChildren(ContainerNode& parent)
{
return ComposedTreeChildAdapter(parent);
}
enum class ComposedTreeAsTextMode { Normal, WithPointers };
WEBCORE_EXPORT String composedTreeAsText(ContainerNode& root, ComposedTreeAsTextMode = ComposedTreeAsTextMode::Normal);
}
#endif