1/* 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. 10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. 11 * Copyright (C) 2012, Google, Inc. All rights reserved. 12 * 13 * This library is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU Library General Public 15 * License as published by the Free Software Foundation; either 16 * version 2 of the License, or (at your option) any later version. 17 * 18 * This library is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 * Library General Public License for more details. 22 * 23 * You should have received a copy of the GNU Library General Public License 24 * along with this library; see the file COPYING.LIB. If not, write to 25 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 26 * Boston, MA 02110-1301, USA. 27 */ 28 29#ifndef SiblingTraversalStrategies_h 30#define SiblingTraversalStrategies_h 31 32#include "core/dom/Element.h" 33#include "core/dom/ElementTraversal.h" 34#include "core/rendering/style/RenderStyle.h" 35 36namespace blink { 37 38class DOMSiblingTraversalStrategy { 39public: 40 bool isFirstChild(Element&) const; 41 bool isLastChild(Element&) const; 42 bool isFirstOfType(Element&, const QualifiedName&) const; 43 bool isLastOfType(Element&, const QualifiedName&) const; 44 45 int countElementsBefore(Element&) const; 46 int countElementsAfter(Element&) const; 47 int countElementsOfTypeBefore(Element&, const QualifiedName&) const; 48 int countElementsOfTypeAfter(Element&, const QualifiedName&) const; 49 50private: 51 class HasTagName { 52 public: 53 explicit HasTagName(const QualifiedName& tagName) : m_tagName(tagName) { } 54 bool operator() (const Element& element) const { return element.hasTagName(m_tagName); } 55 private: 56 const QualifiedName& m_tagName; 57 }; 58}; 59 60inline bool DOMSiblingTraversalStrategy::isFirstChild(Element& element) const 61{ 62 return !ElementTraversal::previousSibling(element); 63} 64 65inline bool DOMSiblingTraversalStrategy::isLastChild(Element& element) const 66{ 67 return !ElementTraversal::nextSibling(element); 68} 69 70inline bool DOMSiblingTraversalStrategy::isFirstOfType(Element& element, const QualifiedName& type) const 71{ 72 return !ElementTraversal::previousSibling(element, HasTagName(type)); 73} 74 75inline bool DOMSiblingTraversalStrategy::isLastOfType(Element& element, const QualifiedName& type) const 76{ 77 return !ElementTraversal::nextSibling(element, HasTagName(type)); 78} 79 80inline int DOMSiblingTraversalStrategy::countElementsBefore(Element& element) const 81{ 82 int count = 0; 83 for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) 84 count++; 85 86 return count; 87} 88 89inline int DOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element& element, const QualifiedName& type) const 90{ 91 int count = 0; 92 for (const Element* sibling = ElementTraversal::previousSibling(element, HasTagName(type)); sibling; sibling = ElementTraversal::previousSibling(*sibling, HasTagName(type))) 93 ++count; 94 return count; 95} 96 97inline int DOMSiblingTraversalStrategy::countElementsAfter(Element& element) const 98{ 99 int count = 0; 100 for (const Element* sibling = ElementTraversal::nextSibling(element); sibling; sibling = ElementTraversal::nextSibling(*sibling)) 101 ++count; 102 return count; 103} 104 105inline int DOMSiblingTraversalStrategy::countElementsOfTypeAfter(Element& element, const QualifiedName& type) const 106{ 107 int count = 0; 108 for (const Element* sibling = ElementTraversal::nextSibling(element, HasTagName(type)); sibling; sibling = ElementTraversal::nextSibling(*sibling, HasTagName(type))) 109 ++count; 110 return count; 111} 112 113class ShadowDOMSiblingTraversalStrategy FINAL { 114 STACK_ALLOCATED(); 115public: 116 ShadowDOMSiblingTraversalStrategy(const WillBeHeapVector<RawPtrWillBeMember<Node>, 32>& siblings, int nth) 117 : m_siblings(siblings) 118 , m_nth(nth) 119 { 120 } 121 122 bool isFirstChild(Element&) const; 123 bool isLastChild(Element&) const; 124 bool isFirstOfType(Element&, const QualifiedName&) const; 125 bool isLastOfType(Element&, const QualifiedName&) const; 126 127 int countElementsBefore(Element&) const; 128 int countElementsAfter(Element&) const; 129 int countElementsOfTypeBefore(Element&, const QualifiedName&) const; 130 int countElementsOfTypeAfter(Element&, const QualifiedName&) const; 131 132private: 133 const WillBeHeapVector<RawPtrWillBeMember<Node>, 32>& m_siblings; 134 int m_nth; 135}; 136 137inline bool ShadowDOMSiblingTraversalStrategy::isFirstChild(Element& element) const 138{ 139 ASSERT(element == toElement(m_siblings[m_nth])); 140 141 for (int i = m_nth - 1; i >= 0; --i) { 142 if (m_siblings[i]->isElementNode()) 143 return false; 144 } 145 146 return true; 147} 148 149inline bool ShadowDOMSiblingTraversalStrategy::isLastChild(Element& element) const 150{ 151 ASSERT(element == toElement(m_siblings[m_nth])); 152 153 for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) { 154 if (m_siblings[i]->isElementNode()) 155 return false; 156 } 157 158 return true; 159} 160 161inline bool ShadowDOMSiblingTraversalStrategy::isFirstOfType(Element& element, const QualifiedName& type) const 162{ 163 ASSERT(element == toElement(m_siblings[m_nth])); 164 165 for (int i = m_nth - 1; i >= 0; --i) { 166 if (m_siblings[i]->isElementNode() && toElement(m_siblings[i])->hasTagName(type)) 167 return false; 168 } 169 170 return true; 171} 172 173inline bool ShadowDOMSiblingTraversalStrategy::isLastOfType(Element& element, const QualifiedName& type) const 174{ 175 ASSERT(element == toElement(m_siblings[m_nth])); 176 177 for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) { 178 if (m_siblings[i]->isElementNode() && toElement(m_siblings[i])->hasTagName(type)) 179 return false; 180 } 181 182 return true; 183} 184 185inline int ShadowDOMSiblingTraversalStrategy::countElementsBefore(Element& element) const 186{ 187 ASSERT(element == toElement(m_siblings[m_nth])); 188 189 int count = 0; 190 for (int i = m_nth - 1; i >= 0; --i) { 191 if (m_siblings[i]->isElementNode()) 192 ++count; 193 } 194 195 return count; 196} 197 198inline int ShadowDOMSiblingTraversalStrategy::countElementsAfter(Element& element) const 199{ 200 ASSERT(element == toElement(m_siblings[m_nth])); 201 202 int count = 0; 203 for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) { 204 if (m_siblings[i]->isElementNode()) 205 return ++count; 206 } 207 208 return count; 209} 210 211inline int ShadowDOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element& element, const QualifiedName& type) const 212{ 213 ASSERT(element == toElement(m_siblings[m_nth])); 214 215 int count = 0; 216 for (int i = m_nth - 1; i >= 0; --i) { 217 if (m_siblings[i]->isElementNode() && toElement(m_siblings[i])->hasTagName(type)) 218 ++count; 219 } 220 221 return count; 222} 223 224inline int ShadowDOMSiblingTraversalStrategy::countElementsOfTypeAfter(Element& element, const QualifiedName& type) const 225{ 226 ASSERT(element == toElement(m_siblings[m_nth])); 227 228 int count = 0; 229 for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) { 230 if (m_siblings[i]->isElementNode() && toElement(m_siblings[i])->hasTagName(type)) 231 return ++count; 232 } 233 234 return count; 235} 236 237} 238 239#endif 240