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 static void destroy(Vector<CSSParserValue, 4>& values) 33 { 34 size_t numValues = values.size(); 35 for (size_t i = 0; i < numValues; i++) { 36 if (values[i].unit == CSSParserValue::Function) 37 delete values[i].function; 38 else if (values[i].unit == CSSParserValue::ValueList) 39 delete values[i].valueList; 40 } 41 } 42 43 void CSSParserValueList::destroyAndClear() 44 { 45 destroy(m_values); 46 clearAndLeakValues(); 47 } 48 49 CSSParserValueList::~CSSParserValueList() 50 { 51 destroy(m_values); 52 } 53 54 void CSSParserValueList::addValue(const CSSParserValue& v) 55 { 56 m_values.append(v); 57 } 58 59 void CSSParserValueList::insertValueAt(unsigned i, const CSSParserValue& v) 60 { 61 m_values.insert(i, v); 62 } 63 64 void CSSParserValueList::stealValues(CSSParserValueList& valueList) 65 { 66 for (unsigned i = 0; i < valueList.size(); ++i) 67 m_values.append(*(valueList.valueAt(i))); 68 valueList.clearAndLeakValues(); 69 } 70 71 PassRefPtrWillBeRawPtr<CSSValue> CSSParserValue::createCSSValue() 72 { 73 if (id) 74 return CSSPrimitiveValue::createIdentifier(id); 75 76 if (unit == CSSParserValue::Operator) 77 return CSSPrimitiveValue::createParserOperator(iValue); 78 if (unit == CSSParserValue::Function) 79 return CSSFunctionValue::create(function); 80 if (unit == CSSParserValue::ValueList) 81 return CSSValueList::createFromParserValueList(valueList); 82 if (unit >= CSSParserValue::Q_EMS) 83 return CSSPrimitiveValue::createAllowingMarginQuirk(fValue, CSSPrimitiveValue::CSS_EMS); 84 85 CSSPrimitiveValue::UnitType primitiveUnit = static_cast<CSSPrimitiveValue::UnitType>(unit); 86 switch (primitiveUnit) { 87 case CSSPrimitiveValue::CSS_IDENT: 88 case CSSPrimitiveValue::CSS_PROPERTY_ID: 89 case CSSPrimitiveValue::CSS_VALUE_ID: 90 return CSSPrimitiveValue::create(string, CSSPrimitiveValue::CSS_PARSER_IDENTIFIER); 91 case CSSPrimitiveValue::CSS_NUMBER: 92 return CSSPrimitiveValue::create(fValue, isInt ? CSSPrimitiveValue::CSS_PARSER_INTEGER : CSSPrimitiveValue::CSS_NUMBER); 93 case CSSPrimitiveValue::CSS_STRING: 94 case CSSPrimitiveValue::CSS_URI: 95 case CSSPrimitiveValue::CSS_PARSER_HEXCOLOR: 96 return CSSPrimitiveValue::create(string, primitiveUnit); 97 case CSSPrimitiveValue::CSS_PERCENTAGE: 98 case CSSPrimitiveValue::CSS_EMS: 99 case CSSPrimitiveValue::CSS_EXS: 100 case CSSPrimitiveValue::CSS_PX: 101 case CSSPrimitiveValue::CSS_CM: 102 case CSSPrimitiveValue::CSS_MM: 103 case CSSPrimitiveValue::CSS_IN: 104 case CSSPrimitiveValue::CSS_PT: 105 case CSSPrimitiveValue::CSS_PC: 106 case CSSPrimitiveValue::CSS_DEG: 107 case CSSPrimitiveValue::CSS_RAD: 108 case CSSPrimitiveValue::CSS_GRAD: 109 case CSSPrimitiveValue::CSS_MS: 110 case CSSPrimitiveValue::CSS_S: 111 case CSSPrimitiveValue::CSS_HZ: 112 case CSSPrimitiveValue::CSS_KHZ: 113 case CSSPrimitiveValue::CSS_VW: 114 case CSSPrimitiveValue::CSS_VH: 115 case CSSPrimitiveValue::CSS_VMIN: 116 case CSSPrimitiveValue::CSS_VMAX: 117 case CSSPrimitiveValue::CSS_TURN: 118 case CSSPrimitiveValue::CSS_REMS: 119 case CSSPrimitiveValue::CSS_CHS: 120 case CSSPrimitiveValue::CSS_FR: 121 return CSSPrimitiveValue::create(fValue, primitiveUnit); 122 case CSSPrimitiveValue::CSS_UNKNOWN: 123 case CSSPrimitiveValue::CSS_DIMENSION: 124 case CSSPrimitiveValue::CSS_ATTR: 125 case CSSPrimitiveValue::CSS_COUNTER: 126 case CSSPrimitiveValue::CSS_RECT: 127 case CSSPrimitiveValue::CSS_RGBCOLOR: 128 case CSSPrimitiveValue::CSS_DPPX: 129 case CSSPrimitiveValue::CSS_DPI: 130 case CSSPrimitiveValue::CSS_DPCM: 131 case CSSPrimitiveValue::CSS_PAIR: 132 case CSSPrimitiveValue::CSS_UNICODE_RANGE: 133 case CSSPrimitiveValue::CSS_PARSER_INTEGER: 134 case CSSPrimitiveValue::CSS_PARSER_IDENTIFIER: 135 case CSSPrimitiveValue::CSS_PARSER_OPERATOR: 136 case CSSPrimitiveValue::CSS_COUNTER_NAME: 137 case CSSPrimitiveValue::CSS_SHAPE: 138 case CSSPrimitiveValue::CSS_QUAD: 139 case CSSPrimitiveValue::CSS_CALC: 140 case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER: 141 case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH: 142 return nullptr; 143 } 144 145 ASSERT_NOT_REACHED(); 146 return nullptr; 147 } 148 149 CSSParserSelector::CSSParserSelector() 150 : m_selector(adoptPtr(new CSSSelector())) 151 { 152 } 153 154 CSSParserSelector::CSSParserSelector(const QualifiedName& tagQName) 155 : m_selector(adoptPtr(new CSSSelector(tagQName))) 156 { 157 } 158 159 CSSParserSelector::~CSSParserSelector() 160 { 161 if (!m_tagHistory) 162 return; 163 Vector<OwnPtr<CSSParserSelector>, 16> toDelete; 164 OwnPtr<CSSParserSelector> selector = m_tagHistory.release(); 165 while (true) { 166 OwnPtr<CSSParserSelector> next = selector->m_tagHistory.release(); 167 toDelete.append(selector.release()); 168 if (!next) 169 break; 170 selector = next.release(); 171 } 172 } 173 174 void CSSParserSelector::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector) 175 { 176 CSSSelectorList* selectorList = new CSSSelectorList(); 177 selectorList->adoptSelectorVector(selectorVector); 178 m_selector->setSelectorList(adoptPtr(selectorList)); 179 } 180 181 bool CSSParserSelector::isSimple() const 182 { 183 if (m_selector->selectorList() || m_selector->matchesPseudoElement()) 184 return false; 185 186 if (!m_tagHistory) 187 return true; 188 189 if (m_selector->match() == CSSSelector::Tag) { 190 // We can't check against anyQName() here because namespace may not be nullAtom. 191 // Example: 192 // @namespace "http://www.w3.org/2000/svg"; 193 // svg:not(:root) { ... 194 if (m_selector->tagQName().localName() == starAtom) 195 return m_tagHistory->isSimple(); 196 } 197 198 return false; 199 } 200 201 void CSSParserSelector::insertTagHistory(CSSSelector::Relation before, PassOwnPtr<CSSParserSelector> selector, CSSSelector::Relation after) 202 { 203 if (m_tagHistory) 204 selector->setTagHistory(m_tagHistory.release()); 205 setRelation(before); 206 selector->setRelation(after); 207 m_tagHistory = selector; 208 } 209 210 void CSSParserSelector::appendTagHistory(CSSSelector::Relation relation, PassOwnPtr<CSSParserSelector> selector) 211 { 212 CSSParserSelector* end = this; 213 while (end->tagHistory()) 214 end = end->tagHistory(); 215 end->setRelation(relation); 216 end->setTagHistory(selector); 217 } 218 219 void CSSParserSelector::prependTagSelector(const QualifiedName& tagQName, bool tagIsForNamespaceRule) 220 { 221 OwnPtr<CSSParserSelector> second = adoptPtr(new CSSParserSelector); 222 second->m_selector = m_selector.release(); 223 second->m_tagHistory = m_tagHistory.release(); 224 m_tagHistory = second.release(); 225 226 m_selector = adoptPtr(new CSSSelector(tagQName, tagIsForNamespaceRule)); 227 m_selector->setRelation(CSSSelector::SubSelector); 228 } 229 230 bool CSSParserSelector::hasHostPseudoSelector() const 231 { 232 CSSParserSelector* selector = const_cast<CSSParserSelector*>(this); 233 do { 234 if (selector->pseudoType() == CSSSelector::PseudoHost || selector->pseudoType() == CSSSelector::PseudoHostContext) 235 return true; 236 } while ((selector = selector->tagHistory())); 237 return false; 238 } 239 240 } // namespace WebCore 241