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/rendering/style/RenderStyle.h" 34 #include "wtf/UnusedParam.h" 35 36 namespace WebCore { 37 38 struct DOMSiblingTraversalStrategy { 39 bool isFirstChild(Element*) const; 40 bool isLastChild(Element*) const; 41 bool isFirstOfType(Element*, const QualifiedName&) const; 42 bool isLastOfType(Element*, const QualifiedName&) const; 43 44 int countElementsBefore(Element*) const; 45 int countElementsAfter(Element*) const; 46 int countElementsOfTypeBefore(Element*, const QualifiedName&) const; 47 int countElementsOfTypeAfter(Element*, const QualifiedName&) const; 48 }; 49 50 inline bool DOMSiblingTraversalStrategy::isFirstChild(Element* element) const 51 { 52 return !element->previousElementSibling(); 53 } 54 55 inline bool DOMSiblingTraversalStrategy::isLastChild(Element* element) const 56 { 57 return !element->nextElementSibling(); 58 } 59 60 inline bool DOMSiblingTraversalStrategy::isFirstOfType(Element* element, const QualifiedName& type) const 61 { 62 for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) { 63 if (sibling->hasTagName(type)) 64 return false; 65 } 66 return true; 67 } 68 69 inline bool DOMSiblingTraversalStrategy::isLastOfType(Element* element, const QualifiedName& type) const 70 { 71 for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) { 72 if (sibling->hasTagName(type)) 73 return false; 74 } 75 return true; 76 } 77 78 inline int DOMSiblingTraversalStrategy::countElementsBefore(Element* element) const 79 { 80 int count = 0; 81 for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) { 82 unsigned index = sibling->childIndex(); 83 if (index) { 84 count += index; 85 break; 86 } 87 count++; 88 } 89 90 return count; 91 } 92 93 inline int DOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element* element, const QualifiedName& type) const 94 { 95 int count = 0; 96 for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) { 97 if (sibling->hasTagName(type)) 98 ++count; 99 } 100 101 return count; 102 } 103 104 inline int DOMSiblingTraversalStrategy::countElementsAfter(Element* element) const 105 { 106 int count = 0; 107 for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) 108 ++count; 109 110 return count; 111 } 112 113 inline int DOMSiblingTraversalStrategy::countElementsOfTypeAfter(Element* element, const QualifiedName& type) const 114 { 115 int count = 0; 116 for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) { 117 if (sibling->hasTagName(type)) 118 ++count; 119 } 120 121 return count; 122 } 123 124 struct ShadowDOMSiblingTraversalStrategy { 125 ShadowDOMSiblingTraversalStrategy(const Vector<Node*>& siblings, int nth) 126 : m_siblings(siblings) 127 , m_nth(nth) 128 { 129 } 130 131 bool isFirstChild(Element*) const; 132 bool isLastChild(Element*) const; 133 bool isFirstOfType(Element*, const QualifiedName&) const; 134 bool isLastOfType(Element*, const QualifiedName&) const; 135 136 int countElementsBefore(Element*) const; 137 int countElementsAfter(Element*) const; 138 int countElementsOfTypeBefore(Element*, const QualifiedName&) const; 139 int countElementsOfTypeAfter(Element*, const QualifiedName&) const; 140 141 private: 142 Vector<Node*> m_siblings; 143 int m_nth; 144 }; 145 146 inline bool ShadowDOMSiblingTraversalStrategy::isFirstChild(Element* element) const 147 { 148 UNUSED_PARAM(element); 149 150 ASSERT(element == toElement(m_siblings[m_nth])); 151 152 for (int i = m_nth - 1; i >= 0; --i) { 153 if (m_siblings[i]->isElementNode()) 154 return false; 155 } 156 157 return true; 158 } 159 160 inline bool ShadowDOMSiblingTraversalStrategy::isLastChild(Element* element) const 161 { 162 UNUSED_PARAM(element); 163 164 ASSERT(element == toElement(m_siblings[m_nth])); 165 166 for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) { 167 if (m_siblings[i]->isElementNode()) 168 return false; 169 } 170 171 return true; 172 } 173 174 inline bool ShadowDOMSiblingTraversalStrategy::isFirstOfType(Element* element, const QualifiedName& type) const 175 { 176 UNUSED_PARAM(element); 177 178 ASSERT(element == toElement(m_siblings[m_nth])); 179 180 for (int i = m_nth - 1; i >= 0; --i) { 181 if (m_siblings[i]->hasTagName(type)) 182 return false; 183 } 184 185 return true; 186 } 187 188 inline bool ShadowDOMSiblingTraversalStrategy::isLastOfType(Element* element, const QualifiedName& type) const 189 { 190 UNUSED_PARAM(element); 191 192 ASSERT(element == toElement(m_siblings[m_nth])); 193 194 for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) { 195 if (m_siblings[i]->hasTagName(type)) 196 return false; 197 } 198 199 return true; 200 } 201 202 inline int ShadowDOMSiblingTraversalStrategy::countElementsBefore(Element* element) const 203 { 204 UNUSED_PARAM(element); 205 206 ASSERT(element == toElement(m_siblings[m_nth])); 207 208 int count = 0; 209 for (int i = m_nth - 1; i >= 0; --i) { 210 if (m_siblings[i]->isElementNode()) 211 ++count; 212 } 213 214 return count; 215 } 216 217 inline int ShadowDOMSiblingTraversalStrategy::countElementsAfter(Element* element) const 218 { 219 UNUSED_PARAM(element); 220 221 ASSERT(element == toElement(m_siblings[m_nth])); 222 223 int count = 0; 224 for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) { 225 if (m_siblings[i]->isElementNode()) 226 return ++count; 227 } 228 229 return count; 230 } 231 232 inline int ShadowDOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element* element, const QualifiedName& type) const 233 { 234 UNUSED_PARAM(element); 235 236 ASSERT(element == toElement(m_siblings[m_nth])); 237 238 int count = 0; 239 for (int i = m_nth - 1; i >= 0; --i) { 240 if (m_siblings[i]->hasTagName(type)) 241 ++count; 242 } 243 244 return count; 245 } 246 247 inline int ShadowDOMSiblingTraversalStrategy::countElementsOfTypeAfter(Element* element, const QualifiedName& type) const 248 { 249 UNUSED_PARAM(element); 250 251 ASSERT(element == toElement(m_siblings[m_nth])); 252 253 int count = 0; 254 for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) { 255 if (m_siblings[i]->hasTagName(type)) 256 return ++count; 257 } 258 259 return count; 260 } 261 262 } 263 264 #endif 265