1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde (at) carewolf.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit (at) nickshanks.com) 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 6 * Copyright (C) 2007 Alexey Proskuryakov <ap (at) webkit.org> 7 * Copyright (C) 2007, 2008 Eric Seidel <eric (at) 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 36 namespace blink { 37 38 class DOMSiblingTraversalStrategy { 39 public: 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 50 private: 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 60 inline bool DOMSiblingTraversalStrategy::isFirstChild(Element& element) const 61 { 62 return !ElementTraversal::previousSibling(element); 63 } 64 65 inline bool DOMSiblingTraversalStrategy::isLastChild(Element& element) const 66 { 67 return !ElementTraversal::nextSibling(element); 68 } 69 70 inline bool DOMSiblingTraversalStrategy::isFirstOfType(Element& element, const QualifiedName& type) const 71 { 72 return !ElementTraversal::previousSibling(element, HasTagName(type)); 73 } 74 75 inline bool DOMSiblingTraversalStrategy::isLastOfType(Element& element, const QualifiedName& type) const 76 { 77 return !ElementTraversal::nextSibling(element, HasTagName(type)); 78 } 79 80 inline 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 89 inline 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 97 inline 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 105 inline 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 113 class ShadowDOMSiblingTraversalStrategy FINAL { 114 STACK_ALLOCATED(); 115 public: 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 132 private: 133 const WillBeHeapVector<RawPtrWillBeMember<Node>, 32>& m_siblings; 134 int m_nth; 135 }; 136 137 inline 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 149 inline 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 161 inline 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 173 inline 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 185 inline 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 198 inline 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 211 inline 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 224 inline 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