Chromium Code Reviews| Index: Source/core/dom/NodeTraversal.h |
| diff --git a/Source/core/dom/NodeTraversal.h b/Source/core/dom/NodeTraversal.h |
| index fafabc8e2de7d3fc1872b805ef837d167c8916eb..860f861d821ed5039836e1bddc5df17bc291249f 100644 |
| --- a/Source/core/dom/NodeTraversal.h |
| +++ b/Source/core/dom/NodeTraversal.h |
| @@ -31,8 +31,15 @@ |
| namespace blink { |
| +template <class Iterator> class TraversalRange; |
| +template <class TraversalNext> class TraversalChildrenIterator; |
| +template <class TraversalNext> class TraversalDescendantIterator; |
| +template <class TraversalNext> class TraversalInclusiveDescendantIterator; |
| +template <class TraversalNext> class TraversalNextIterator; |
| + |
| class NodeTraversal { |
| public: |
| + using TraversalNodeType = Node; |
| // Does a pre-order traversal of the tree to find the next node after this one. |
| // This uses the same order that tags appear in the source file. If the stayWithin |
| // argument is non-null, the traversal will stop once the specified node is reached. |
| @@ -46,6 +53,8 @@ public: |
| static Node* nextSkippingChildren(const Node&); |
| static Node* nextSkippingChildren(const Node&, const Node* stayWithin); |
| + static Node* firstWithin(const Node& current) { return current.firstChild(); } |
| + |
| static Node* lastWithin(const ContainerNode&); |
| static Node& lastWithinOrSelf(Node&); |
| @@ -74,6 +83,13 @@ public: |
| static Node* childAt(const Node& parent, unsigned index) { return childAtTemplate(parent, index); } |
| static Node* childAt(const ContainerNode& parent, unsigned index) { return childAtTemplate(parent, index); } |
| + static Node* nextSibling(const Node& node) { return node.nextSibling(); } |
| + |
| + static TraversalRange<TraversalChildrenIterator<NodeTraversal>> childrenOf(const Node&); |
| + static TraversalRange<TraversalDescendantIterator<NodeTraversal>> descendantsOf(const Node&); |
| + static TraversalRange<TraversalInclusiveDescendantIterator<NodeTraversal>> inclusiveDescendantsOf(const Node&); |
| + static TraversalRange<TraversalNextIterator<NodeTraversal>> from(Node&); |
| + |
| private: |
| template <class NodeType> |
| static Node* traverseNextTemplate(NodeType&); |
| @@ -83,6 +99,94 @@ private: |
| static Node* childAtTemplate(NodeType&, unsigned); |
| }; |
| +template <class Iterator> |
| +class TraversalRange { |
| +public: |
| + TraversalRange(const Node& start) : m_start(start) { } |
| + Iterator begin() { return Iterator(m_start); } |
| + Iterator end() { return Iterator::end(); } |
| +private: |
| + const Node& m_start; |
| +}; |
| + |
| +template <class TraversalNext> |
| +class TraversalIteratorBase { |
| +public: |
| + using NodeType = typename TraversalNext::TraversalNodeType; |
| + NodeType& operator*() { return *m_current; } |
| + bool operator!=(const TraversalIteratorBase& rval) const { return m_current != rval.m_current ; } |
| +protected: |
| + TraversalIteratorBase(NodeType* current) : m_current(current) { }; |
| + NodeType* m_current; |
| +}; |
| + |
| +template <class TraversalNext> |
| +class TraversalChildrenIterator : public TraversalIteratorBase<TraversalNext> { |
| +public: |
| + using TraversalIteratorBase<TraversalNext>::m_current; |
| + TraversalChildrenIterator(const Node& start) : TraversalIteratorBase<TraversalNext>(TraversalNext::firstWithin(start)) { }; |
| + void operator++() { m_current = TraversalNext::nextSibling(*m_current); }; |
| + static TraversalChildrenIterator end() { return TraversalChildrenIterator(); }; |
| +private: |
| + TraversalChildrenIterator() : TraversalIteratorBase<TraversalNext>(nullptr) { }; |
| +}; |
| + |
| +template <class TraversalNext> |
| +class TraversalNextIterator : public TraversalIteratorBase<TraversalNext> { |
| +public: |
| + using TraversalIteratorBase<TraversalNext>::m_current; |
| + TraversalNextIterator(const Node& start) : TraversalIteratorBase<TraversalNext>(TraversalNext::next(start)) { }; |
| + void operator++() { m_current = TraversalNext::next(*m_current); } |
| + static TraversalNextIterator end() { return TraversalNextIterator(); }; |
| +private: |
| + TraversalNextIterator() : TraversalIteratorBase<TraversalNext>(nullptr) { }; |
| +}; |
| + |
| +template <class TraversalNext> |
| +class TraversalDescendantIterator : public TraversalIteratorBase<TraversalNext> { |
| +public: |
| + using TraversalIteratorBase<TraversalNext>::m_current; |
| + TraversalDescendantIterator(const Node& start) : TraversalIteratorBase<TraversalNext>(TraversalNext::firstWithin(start)), m_root(&start) { }; |
|
esprehn
2014/10/16 17:43:25
need explicit on these classes
|
| + void operator++() { m_current = TraversalNext::next(*m_current, m_root); } |
| + static TraversalDescendantIterator end() { return TraversalDescendantIterator(); }; |
| +private: |
| + TraversalDescendantIterator() : TraversalIteratorBase<TraversalNext>(nullptr), m_root(nullptr) { }; |
| + const Node* m_root; |
| +}; |
| + |
| +template <class TraversalNext> |
| +class TraversalInclusiveDescendantIterator : public TraversalIteratorBase<TraversalNext> { |
| +public: |
| + using NodeType = typename TraversalNext::TraversalNodeType; |
| + using TraversalIteratorBase<TraversalNext>::m_current; |
| + TraversalInclusiveDescendantIterator(const NodeType& start) : TraversalIteratorBase<TraversalNext>(const_cast<NodeType*>(&start)), m_root(&start) { }; |
| + void operator++() { m_current = TraversalNext::next(*m_current, m_root); } |
| + static TraversalInclusiveDescendantIterator end() { return TraversalInclusiveDescendantIterator(); }; |
| +private: |
| + TraversalInclusiveDescendantIterator() : TraversalIteratorBase<TraversalNext>(nullptr), m_root(nullptr) { }; |
| + const Node* m_root; |
| +}; |
| + |
| +inline TraversalRange<TraversalChildrenIterator<NodeTraversal>> NodeTraversal::childrenOf(const Node& parent) |
| +{ |
| + return TraversalRange<TraversalChildrenIterator<NodeTraversal>>(parent); |
| +} |
| + |
| +inline TraversalRange<TraversalDescendantIterator<NodeTraversal>> NodeTraversal::descendantsOf(const Node& root) |
| +{ |
| + return TraversalRange<TraversalDescendantIterator<NodeTraversal>>(root); |
| +} |
| + |
| +inline TraversalRange<TraversalInclusiveDescendantIterator<NodeTraversal>> NodeTraversal::inclusiveDescendantsOf(const Node& root) |
| +{ |
| + return TraversalRange<TraversalInclusiveDescendantIterator<NodeTraversal>>(root); |
| +} |
| + |
| +inline TraversalRange<TraversalNextIterator<NodeTraversal>> NodeTraversal::from(Node& start) |
| +{ |
| + return TraversalRange<TraversalNextIterator<NodeTraversal>>(start); |
| +}; |
| + |
| template <class NodeType> |
| inline Node* NodeTraversal::traverseNextTemplate(NodeType& current) |
| { |