CollectionTraversal.h [plain text]
#pragma once
#include "CollectionType.h"
#include "ElementChildIterator.h"
#include "ElementDescendantIterator.h"
namespace WebCore {
template <CollectionTraversalType traversalType>
struct CollectionTraversal { };
template <>
struct CollectionTraversal<CollectionTraversalType::Descendants> {
using Iterator = ElementDescendantIterator;
static ElementDescendantIterator end(ContainerNode&) { return ElementDescendantIterator(); }
template <typename CollectionClass>
static ElementDescendantIterator begin(const CollectionClass&, ContainerNode& rootNode);
template <typename CollectionClass>
static ElementDescendantIterator last(const CollectionClass&, ContainerNode& rootNode);
template <typename CollectionClass>
static void traverseForward(const CollectionClass&, ElementDescendantIterator& current, unsigned count, unsigned& traversedCount);
template <typename CollectionClass>
static void traverseBackward(const CollectionClass&, ElementDescendantIterator& current, unsigned count);
};
template <typename CollectionClass>
inline ElementDescendantIterator CollectionTraversal<CollectionTraversalType::Descendants>::begin(const CollectionClass& collection, ContainerNode& rootNode)
{
auto descendants = elementDescendants(rootNode);
auto end = descendants.end();
for (auto it = descendants.begin(); it != end; ++it) {
if (collection.elementMatches(*it)) {
it.dropAssertions();
return it;
}
}
return end;
}
template <typename CollectionClass>
inline ElementDescendantIterator CollectionTraversal<CollectionTraversalType::Descendants>::last(const CollectionClass& collection, ContainerNode& rootNode)
{
auto descendants = elementDescendants(rootNode);
ElementDescendantIterator invalid;
for (auto it = descendants.last(); it != invalid; --it) {
if (collection.elementMatches(*it)) {
it.dropAssertions();
return it;
}
}
return invalid;
}
template <typename CollectionClass>
inline void CollectionTraversal<CollectionTraversalType::Descendants>::traverseForward(const CollectionClass& collection, ElementDescendantIterator& current, unsigned count, unsigned& traversedCount)
{
ASSERT(collection.elementMatches(*current));
ElementDescendantIterator invalid;
for (traversedCount = 0; traversedCount < count; ++traversedCount) {
do {
++current;
if (current == invalid)
return;
} while (!collection.elementMatches(*current));
}
}
template <typename CollectionClass>
inline void CollectionTraversal<CollectionTraversalType::Descendants>::traverseBackward(const CollectionClass& collection, ElementDescendantIterator& current, unsigned count)
{
ASSERT(collection.elementMatches(*current));
ElementDescendantIterator invalid;
for (; count; --count) {
do {
--current;
if (current == invalid)
return;
} while (!collection.elementMatches(*current));
}
}
template <>
struct CollectionTraversal<CollectionTraversalType::ChildrenOnly> {
using Iterator = ElementChildIterator<Element>;
static ElementChildIterator<Element> end(ContainerNode& rootNode) { return ElementChildIterator<Element>(rootNode); }
template <typename CollectionClass>
static ElementChildIterator<Element> begin(const CollectionClass&, ContainerNode& rootNode);
template <typename CollectionClass>
static ElementChildIterator<Element> last(const CollectionClass&, ContainerNode& rootNode);
template <typename CollectionClass>
static void traverseForward(const CollectionClass&, ElementChildIterator<Element>& current, unsigned count, unsigned& traversedCount);
template <typename CollectionClass>
static void traverseBackward(const CollectionClass&, ElementChildIterator<Element>& current, unsigned count);
};
template <typename CollectionClass>
inline ElementChildIterator<Element> CollectionTraversal<CollectionTraversalType::ChildrenOnly>::begin(const CollectionClass& collection, ContainerNode& rootNode)
{
auto children = childrenOfType<Element>(rootNode);
auto end = children.end();
for (auto it = children.begin(); it != end; ++it) {
if (collection.elementMatches(*it)) {
it.dropAssertions();
return it;
}
}
return end;
}
template <typename CollectionClass>
inline ElementChildIterator<Element> CollectionTraversal<CollectionTraversalType::ChildrenOnly>::last(const CollectionClass& collection, ContainerNode& rootNode)
{
auto children = childrenOfType<Element>(rootNode);
ElementChildIterator<Element> invalid(collection.rootNode());
ElementChildIterator<Element> last(rootNode, children.last());
for (auto it = last; it != invalid; --it) {
if (collection.elementMatches(*it)) {
it.dropAssertions();
return it;
}
}
return invalid;
}
template <typename CollectionClass>
inline void CollectionTraversal<CollectionTraversalType::ChildrenOnly>::traverseForward(const CollectionClass& collection, ElementChildIterator<Element>& current, unsigned count, unsigned& traversedCount)
{
ASSERT(collection.elementMatches(*current));
ElementChildIterator<Element> invalid(collection.rootNode());
for (traversedCount = 0; traversedCount < count; ++traversedCount) {
do {
++current;
if (current == invalid)
return;
} while (!collection.elementMatches(*current));
}
}
template <typename CollectionClass>
inline void CollectionTraversal<CollectionTraversalType::ChildrenOnly>::traverseBackward(const CollectionClass& collection, ElementChildIterator<Element>& current, unsigned count)
{
ASSERT(collection.elementMatches(*current));
ElementChildIterator<Element> invalid(collection.rootNode());
for (; count; --count) {
do {
--current;
if (current == invalid)
return;
} while (!collection.elementMatches(*current));
}
}
template <>
struct CollectionTraversal<CollectionTraversalType::CustomForwardOnly> {
using Iterator = Element*;
static Element* end(ContainerNode&) { return nullptr; }
template <typename CollectionClass>
static Element* begin(const CollectionClass&, ContainerNode&);
template <typename CollectionClass>
static Element* last(const CollectionClass&, ContainerNode&);
template <typename CollectionClass>
static void traverseForward(const CollectionClass&, Element*& current, unsigned count, unsigned& traversedCount);
template <typename CollectionClass>
static void traverseBackward(const CollectionClass&, Element*&, unsigned count);
};
template <typename CollectionClass>
inline Element* CollectionTraversal<CollectionTraversalType::CustomForwardOnly>::begin(const CollectionClass& collection, ContainerNode&)
{
return collection.customElementAfter(nullptr);
}
template <typename CollectionClass>
inline Element* CollectionTraversal<CollectionTraversalType::CustomForwardOnly>::last(const CollectionClass&, ContainerNode&)
{
ASSERT_NOT_REACHED();
return nullptr;
}
template <typename CollectionClass>
inline void CollectionTraversal<CollectionTraversalType::CustomForwardOnly>::traverseForward(const CollectionClass& collection, Element*& current, unsigned count, unsigned& traversedCount)
{
Element* element = current;
for (traversedCount = 0; traversedCount < count; ++traversedCount) {
element = collection.customElementAfter(element);
if (!element) {
current = nullptr;
return;
}
}
current = element;
}
template <typename CollectionClass>
inline void CollectionTraversal<CollectionTraversalType::CustomForwardOnly>::traverseBackward(const CollectionClass&, Element*&, unsigned count)
{
UNUSED_PARAM(count);
ASSERT_NOT_REACHED();
}
}