summaryrefslogtreecommitdiff
path: root/Source/WebCore/html/CollectionTraversal.h
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/html/CollectionTraversal.h
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/html/CollectionTraversal.h')
-rw-r--r--Source/WebCore/html/CollectionTraversal.h245
1 files changed, 245 insertions, 0 deletions
diff --git a/Source/WebCore/html/CollectionTraversal.h b/Source/WebCore/html/CollectionTraversal.h
new file mode 100644
index 000000000..66829338d
--- /dev/null
+++ b/Source/WebCore/html/CollectionTraversal.h
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2015 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#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)) {
+ // Drop iterator assertions because HTMLCollections / NodeList use a fine-grained invalidation scheme.
+ 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)) {
+ // Drop iterator assertions because HTMLCollections / NodeList use a fine-grained invalidation scheme.
+ 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)) {
+ // Drop iterator assertions because HTMLCollections / NodeList use a fine-grained invalidation scheme.
+ 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)) {
+ // Drop iterator assertions because HTMLCollections / NodeList use a fine-grained invalidation scheme.
+ 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();
+}
+
+} // namespace WebCore