1 /* 2 * Copyright (C) 2003 Lars Knoll (knoll (at) kde.org) 3 * Copyright (C) 2004, 2005, 2006, 2008 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 #include "config.h" 22 #include "core/css/CSSParserValues.h" 23 24 #include "core/css/CSSFunctionValue.h" 25 #include "core/css/CSSSelectorList.h" 26 #include "core/html/parser/HTMLParserIdioms.h" 27 28 namespace WebCore { 29 30 using namespace WTF; 31 32 AtomicString CSSParserString::atomicSubstring(unsigned position, unsigned length) const 33 { 34 ASSERT(m_length >= position + length); 35 36 if (is8Bit()) 37 return AtomicString(characters8() + position, length); 38 return AtomicString(characters16() + position, length); 39 } 40 41 void CSSParserString::trimTrailingWhitespace() 42 { 43 if (is8Bit()) { 44 while (m_length > 0 && isHTMLSpace<LChar>(m_data.characters8[m_length - 1])) 45 --m_length; 46 } else { 47 while (m_length > 0 && isHTMLSpace<UChar>(m_data.characters16[m_length - 1])) 48 --m_length; 49 } 50 } 51 52 CSSParserValueList::~CSSParserValueList() 53 { 54 size_t numValues = m_values.size(); 55 for (size_t i = 0; i < numValues; i++) { 56 if (m_values[i].unit == CSSParserValue::Function) 57 delete m_values[i].function; 58 else if (m_values[i].unit == CSSParserValue::ValueList) 59 delete m_values[i].valueList; 60 } 61 } 62 63 void CSSParserValueList::addValue(const CSSParserValue& v) 64 { 65 m_values.append(v); 66 } 67 68 void CSSParserValueList::insertValueAt(unsigned i, const CSSParserValue& v) 69 { 70 m_values.insert(i, v); 71 } 72 73 void CSSParserValueList::deleteValueAt(unsigned i) 74 { 75 m_values.remove(i); 76 } 77 78 void CSSParserValueList::extend(CSSParserValueList& valueList) 79 { 80 for (unsigned int i = 0; i < valueList.size(); ++i) 81 m_values.append(*(valueList.valueAt(i))); 82 } 83 84 PassRefPtr<CSSValue> CSSParserValue::createCSSValue() 85 { 86 RefPtr<CSSValue> parsedValue; 87 if (id) 88 return CSSPrimitiveValue::createIdentifier(id); 89 90 if (unit == CSSParserValue::Operator) { 91 RefPtr<CSSPrimitiveValue> primitiveValue = CSSPrimitiveValue::createParserOperator(iValue); 92 primitiveValue->setPrimitiveType(CSSPrimitiveValue::CSS_PARSER_OPERATOR); 93 return primitiveValue; 94 } 95 if (unit == CSSParserValue::Function) 96 return CSSFunctionValue::create(function); 97 if (unit == CSSParserValue::ValueList) 98 return CSSValueList::createFromParserValueList(valueList); 99 if (unit >= CSSParserValue::Q_EMS) 100 return CSSPrimitiveValue::createAllowingMarginQuirk(fValue, CSSPrimitiveValue::CSS_EMS); 101 102 CSSPrimitiveValue::UnitTypes primitiveUnit = static_cast<CSSPrimitiveValue::UnitTypes>(unit); 103 switch (primitiveUnit) { 104 case CSSPrimitiveValue::CSS_IDENT: 105 case CSSPrimitiveValue::CSS_PROPERTY_ID: 106 case CSSPrimitiveValue::CSS_VALUE_ID: 107 return CSSPrimitiveValue::create(string, CSSPrimitiveValue::CSS_PARSER_IDENTIFIER); 108 case CSSPrimitiveValue::CSS_NUMBER: 109 return CSSPrimitiveValue::create(fValue, isInt ? CSSPrimitiveValue::CSS_PARSER_INTEGER : CSSPrimitiveValue::CSS_NUMBER); 110 case CSSPrimitiveValue::CSS_STRING: 111 case CSSPrimitiveValue::CSS_URI: 112 case CSSPrimitiveValue::CSS_VARIABLE_NAME: 113 case CSSPrimitiveValue::CSS_PARSER_HEXCOLOR: 114 return CSSPrimitiveValue::create(string, primitiveUnit); 115 case CSSPrimitiveValue::CSS_PERCENTAGE: 116 case CSSPrimitiveValue::CSS_EMS: 117 case CSSPrimitiveValue::CSS_EXS: 118 case CSSPrimitiveValue::CSS_PX: 119 case CSSPrimitiveValue::CSS_CM: 120 case CSSPrimitiveValue::CSS_MM: 121 case CSSPrimitiveValue::CSS_IN: 122 case CSSPrimitiveValue::CSS_PT: 123 case CSSPrimitiveValue::CSS_PC: 124 case CSSPrimitiveValue::CSS_DEG: 125 case CSSPrimitiveValue::CSS_RAD: 126 case CSSPrimitiveValue::CSS_GRAD: 127 case CSSPrimitiveValue::CSS_MS: 128 case CSSPrimitiveValue::CSS_S: 129 case CSSPrimitiveValue::CSS_HZ: 130 case CSSPrimitiveValue::CSS_KHZ: 131 case CSSPrimitiveValue::CSS_VW: 132 case CSSPrimitiveValue::CSS_VH: 133 case CSSPrimitiveValue::CSS_VMIN: 134 case CSSPrimitiveValue::CSS_VMAX: 135 case CSSPrimitiveValue::CSS_TURN: 136 case CSSPrimitiveValue::CSS_REMS: 137 case CSSPrimitiveValue::CSS_CHS: 138 case CSSPrimitiveValue::CSS_FR: 139 return CSSPrimitiveValue::create(fValue, primitiveUnit); 140 case CSSPrimitiveValue::CSS_UNKNOWN: 141 case CSSPrimitiveValue::CSS_DIMENSION: 142 case CSSPrimitiveValue::CSS_ATTR: 143 case CSSPrimitiveValue::CSS_COUNTER: 144 case CSSPrimitiveValue::CSS_RECT: 145 case CSSPrimitiveValue::CSS_RGBCOLOR: 146 case CSSPrimitiveValue::CSS_DPPX: 147 case CSSPrimitiveValue::CSS_DPI: 148 case CSSPrimitiveValue::CSS_DPCM: 149 case CSSPrimitiveValue::CSS_PAIR: 150 case CSSPrimitiveValue::CSS_UNICODE_RANGE: 151 case CSSPrimitiveValue::CSS_PARSER_OPERATOR: 152 case CSSPrimitiveValue::CSS_PARSER_INTEGER: 153 case CSSPrimitiveValue::CSS_PARSER_IDENTIFIER: 154 case CSSPrimitiveValue::CSS_COUNTER_NAME: 155 case CSSPrimitiveValue::CSS_SHAPE: 156 case CSSPrimitiveValue::CSS_QUAD: 157 case CSSPrimitiveValue::CSS_CALC: 158 case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER: 159 case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH: 160 return 0; 161 } 162 163 ASSERT_NOT_REACHED(); 164 return 0; 165 } 166 167 CSSParserSelector::CSSParserSelector() 168 : m_selector(adoptPtr(new CSSSelector())) 169 , m_functionArgumentSelector(0) 170 { 171 } 172 173 CSSParserSelector::CSSParserSelector(const QualifiedName& tagQName) 174 : m_selector(adoptPtr(new CSSSelector(tagQName))) 175 , m_functionArgumentSelector(0) 176 { 177 } 178 179 CSSParserSelector::~CSSParserSelector() 180 { 181 if (!m_tagHistory) 182 return; 183 Vector<OwnPtr<CSSParserSelector>, 16> toDelete; 184 OwnPtr<CSSParserSelector> selector = m_tagHistory.release(); 185 while (true) { 186 OwnPtr<CSSParserSelector> next = selector->m_tagHistory.release(); 187 toDelete.append(selector.release()); 188 if (!next) 189 break; 190 selector = next.release(); 191 } 192 } 193 194 void CSSParserSelector::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector) 195 { 196 CSSSelectorList* selectorList = new CSSSelectorList(); 197 selectorList->adoptSelectorVector(selectorVector); 198 m_selector->setSelectorList(adoptPtr(selectorList)); 199 } 200 201 bool CSSParserSelector::isSimple() const 202 { 203 if (m_selector->selectorList() || m_selector->matchesPseudoElement()) 204 return false; 205 206 if (!m_tagHistory) 207 return true; 208 209 if (m_selector->m_match == CSSSelector::Tag) { 210 // We can't check against anyQName() here because namespace may not be nullAtom. 211 // Example: 212 // @namespace "http://www.w3.org/2000/svg"; 213 // svg:not(:root) { ... 214 if (m_selector->tagQName().localName() == starAtom) 215 return m_tagHistory->isSimple(); 216 } 217 218 return false; 219 } 220 221 void CSSParserSelector::insertTagHistory(CSSSelector::Relation before, PassOwnPtr<CSSParserSelector> selector, CSSSelector::Relation after) 222 { 223 if (m_tagHistory) 224 selector->setTagHistory(m_tagHistory.release()); 225 setRelation(before); 226 selector->setRelation(after); 227 m_tagHistory = selector; 228 } 229 230 void CSSParserSelector::appendTagHistory(CSSSelector::Relation relation, PassOwnPtr<CSSParserSelector> selector) 231 { 232 CSSParserSelector* end = this; 233 while (end->tagHistory()) 234 end = end->tagHistory(); 235 end->setRelation(relation); 236 end->setTagHistory(selector); 237 } 238 239 void CSSParserSelector::prependTagSelector(const QualifiedName& tagQName, bool tagIsForNamespaceRule) 240 { 241 OwnPtr<CSSParserSelector> second = adoptPtr(new CSSParserSelector); 242 second->m_selector = m_selector.release(); 243 second->m_tagHistory = m_tagHistory.release(); 244 m_tagHistory = second.release(); 245 246 m_selector = adoptPtr(new CSSSelector(tagQName, tagIsForNamespaceRule)); 247 m_selector->m_relation = CSSSelector::SubSelector; 248 } 249 250 CSSParserSelector* CSSParserSelector::findDistributedPseudoElementSelector() const 251 { 252 CSSParserSelector* selector = const_cast<CSSParserSelector*>(this); 253 do { 254 if (selector->isDistributedPseudoElement()) 255 return selector; 256 } while ((selector = selector->tagHistory())); 257 return 0; 258 } 259 260 } // namespace WebCore 261