1 /* 2 * Copyright (C) 2003 Lars Knoll (knoll (at) kde.org) 3 * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public License 16 * along with this library; see the file COPYING.LIB. If not, write to 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21 #ifndef CSSParserValues_h 22 #define CSSParserValues_h 23 24 #include "core/CSSValueKeywords.h" 25 #include "core/css/CSSPrimitiveValue.h" 26 #include "core/css/CSSSelector.h" 27 #include "core/css/CSSValueList.h" 28 #include "wtf/text/AtomicString.h" 29 #include "wtf/text/WTFString.h" 30 31 namespace blink { 32 33 class QualifiedName; 34 35 struct CSSParserString { 36 void init(const LChar* characters, unsigned length) 37 { 38 m_data.characters8 = characters; 39 m_length = length; 40 m_is8Bit = true; 41 } 42 43 void init(const UChar* characters, unsigned length) 44 { 45 m_data.characters16 = characters; 46 m_length = length; 47 m_is8Bit = false; 48 } 49 50 void init(const String& string) 51 { 52 init(string, 0, string.length()); 53 } 54 55 void init(const String& string, unsigned startOffset, unsigned length) 56 { 57 m_length = length; 58 if (!m_length) { 59 m_data.characters8 = 0; 60 m_is8Bit = true; 61 return; 62 } 63 if (string.is8Bit()) { 64 m_data.characters8 = const_cast<LChar*>(string.characters8()) + startOffset; 65 m_is8Bit = true; 66 } else { 67 m_data.characters16 = const_cast<UChar*>(string.characters16()) + startOffset; 68 m_is8Bit = false; 69 } 70 } 71 72 void clear() 73 { 74 m_data.characters8 = 0; 75 m_length = 0; 76 m_is8Bit = true; 77 } 78 79 bool is8Bit() const { return m_is8Bit; } 80 const LChar* characters8() const { ASSERT(is8Bit()); return m_data.characters8; } 81 const UChar* characters16() const { ASSERT(!is8Bit()); return m_data.characters16; } 82 template <typename CharacterType> 83 const CharacterType* characters() const; 84 85 unsigned length() const { return m_length; } 86 void setLength(unsigned length) { m_length = length; } 87 88 UChar operator[](unsigned i) const 89 { 90 ASSERT_WITH_SECURITY_IMPLICATION(i < m_length); 91 if (is8Bit()) 92 return m_data.characters8[i]; 93 return m_data.characters16[i]; 94 } 95 96 bool equalIgnoringCase(const char* str) const 97 { 98 bool match = is8Bit() ? WTF::equalIgnoringCase(str, characters8(), length()) : WTF::equalIgnoringCase(str, characters16(), length()); 99 if (!match) 100 return false; 101 ASSERT(strlen(str) >= length()); 102 return str[length()] == '\0'; 103 } 104 105 template <size_t strLength> 106 bool startsWithIgnoringCase(const char (&str)[strLength]) const 107 { 108 return startsWithIgnoringCase(str, strLength - 1); 109 } 110 111 bool startsWithIgnoringCase(const char* str, size_t strLength) const 112 { 113 if (length() < strLength) 114 return false; 115 return is8Bit() ? WTF::equalIgnoringCase(str, characters8(), strLength) : WTF::equalIgnoringCase(str, characters16(), strLength); 116 } 117 118 operator String() const { return is8Bit() ? String(m_data.characters8, m_length) : StringImpl::create8BitIfPossible(m_data.characters16, m_length); } 119 operator AtomicString() const { return is8Bit() ? AtomicString(m_data.characters8, m_length) : AtomicString(m_data.characters16, m_length); } 120 121 bool isFunction() const { return length() > 0 && (*this)[length() - 1] == '('; } 122 123 union { 124 const LChar* characters8; 125 const UChar* characters16; 126 } m_data; 127 unsigned m_length; 128 bool m_is8Bit; 129 }; 130 131 template <> 132 inline const LChar* CSSParserString::characters<LChar>() const { return characters8(); } 133 134 template <> 135 inline const UChar* CSSParserString::characters<UChar>() const { return characters16(); } 136 137 struct CSSParserFunction; 138 class CSSParserValueList; 139 140 struct CSSParserValue { 141 CSSValueID id; 142 bool isInt; 143 union { 144 double fValue; 145 int iValue; 146 CSSParserString string; 147 CSSParserFunction* function; 148 CSSParserValueList* valueList; 149 }; 150 enum { 151 Operator = 0x100000, 152 Function = 0x100001, 153 ValueList = 0x100002, 154 Q_EMS = 0x100003, 155 }; 156 int unit; 157 158 inline void setFromNumber(double value, int unit = CSSPrimitiveValue::CSS_NUMBER); 159 inline void setFromFunction(CSSParserFunction*); 160 inline void setFromValueList(PassOwnPtr<CSSParserValueList>); 161 }; 162 163 class CSSParserValueList { 164 WTF_MAKE_FAST_ALLOCATED; 165 public: 166 CSSParserValueList() 167 : m_current(0) 168 { 169 } 170 ~CSSParserValueList(); 171 172 void addValue(const CSSParserValue&); 173 void insertValueAt(unsigned, const CSSParserValue&); 174 void stealValues(CSSParserValueList&); 175 176 unsigned size() const { return m_values.size(); } 177 unsigned currentIndex() { return m_current; } 178 CSSParserValue* current() { return m_current < m_values.size() ? &m_values[m_current] : 0; } 179 CSSParserValue* next() { ++m_current; return current(); } 180 CSSParserValue* previous() 181 { 182 if (!m_current) 183 return 0; 184 --m_current; 185 return current(); 186 } 187 void setCurrentIndex(unsigned index) 188 { 189 ASSERT(index < m_values.size()); 190 if (index < m_values.size()) 191 m_current = index; 192 } 193 194 CSSParserValue* valueAt(unsigned i) { return i < m_values.size() ? &m_values[i] : 0; } 195 196 void clearAndLeakValues() { m_values.clear(); m_current = 0;} 197 void destroyAndClear(); 198 199 private: 200 unsigned m_current; 201 Vector<CSSParserValue, 4> m_values; 202 }; 203 204 struct CSSParserFunction { 205 WTF_MAKE_FAST_ALLOCATED; 206 public: 207 CSSParserString name; 208 OwnPtr<CSSParserValueList> args; 209 }; 210 211 class CSSParserSelector { 212 WTF_MAKE_NONCOPYABLE(CSSParserSelector); WTF_MAKE_FAST_ALLOCATED; 213 public: 214 CSSParserSelector(); 215 explicit CSSParserSelector(const QualifiedName&); 216 ~CSSParserSelector(); 217 218 PassOwnPtr<CSSSelector> releaseSelector() { return m_selector.release(); } 219 220 CSSSelector::Relation relation() const { return m_selector->relation(); } 221 void setValue(const AtomicString& value) { m_selector->setValue(value); } 222 void setAttribute(const QualifiedName& value, CSSSelector::AttributeMatchType matchType) { m_selector->setAttribute(value, matchType); } 223 void setArgument(const AtomicString& value) { m_selector->setArgument(value); } 224 void setMatch(CSSSelector::Match value) { m_selector->setMatch(value); } 225 void setRelation(CSSSelector::Relation value) { m_selector->setRelation(value); } 226 void setForPage() { m_selector->setForPage(); } 227 void setRelationIsAffectedByPseudoContent() { m_selector->setRelationIsAffectedByPseudoContent(); } 228 bool relationIsAffectedByPseudoContent() const { return m_selector->relationIsAffectedByPseudoContent(); } 229 230 void adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector); 231 232 bool hasHostPseudoSelector() const; 233 bool isContentPseudoElement() const { return m_selector->isContentPseudoElement(); } 234 235 CSSSelector::PseudoType pseudoType() const { return m_selector->pseudoType(); } 236 bool isCustomPseudoElement() const { return m_selector->isCustomPseudoElement(); } 237 bool crossesTreeScopes() const { return isCustomPseudoElement() || pseudoType() == CSSSelector::PseudoCue || pseudoType() == CSSSelector::PseudoShadow; } 238 239 bool isSimple() const; 240 bool hasShadowPseudo() const; 241 242 CSSParserSelector* tagHistory() const { return m_tagHistory.get(); } 243 void setTagHistory(PassOwnPtr<CSSParserSelector> selector) { m_tagHistory = selector; } 244 void clearTagHistory() { m_tagHistory.clear(); } 245 void insertTagHistory(CSSSelector::Relation before, PassOwnPtr<CSSParserSelector>, CSSSelector::Relation after); 246 void appendTagHistory(CSSSelector::Relation, PassOwnPtr<CSSParserSelector>); 247 void prependTagSelector(const QualifiedName&, bool tagIsForNamespaceRule = false); 248 249 private: 250 OwnPtr<CSSSelector> m_selector; 251 OwnPtr<CSSParserSelector> m_tagHistory; 252 }; 253 254 inline bool CSSParserSelector::hasShadowPseudo() const 255 { 256 return m_selector->relation() == CSSSelector::ShadowPseudo; 257 } 258 259 inline void CSSParserValue::setFromNumber(double value, int unit) 260 { 261 id = CSSValueInvalid; 262 isInt = false; 263 if (std::isfinite(value)) 264 fValue = value; 265 else 266 fValue = 0; 267 this->unit = unit; 268 } 269 270 inline void CSSParserValue::setFromFunction(CSSParserFunction* function) 271 { 272 id = CSSValueInvalid; 273 this->function = function; 274 unit = Function; 275 isInt = false; 276 } 277 278 inline void CSSParserValue::setFromValueList(PassOwnPtr<CSSParserValueList> valueList) 279 { 280 id = CSSValueInvalid; 281 this->valueList = valueList.leakPtr(); 282 unit = ValueList; 283 isInt = false; 284 } 285 286 } 287 288 #endif 289