1 /*
2 * Copyright (C) 2003 Lars Knoll (knoll@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
atomicSubstring(unsigned position,unsigned length) const32 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
trimTrailingWhitespace()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
~CSSParserValueList()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
addValue(const CSSParserValue & v)63 void CSSParserValueList::addValue(const CSSParserValue& v)
64 {
65 m_values.append(v);
66 }
67
insertValueAt(unsigned i,const CSSParserValue & v)68 void CSSParserValueList::insertValueAt(unsigned i, const CSSParserValue& v)
69 {
70 m_values.insert(i, v);
71 }
72
deleteValueAt(unsigned i)73 void CSSParserValueList::deleteValueAt(unsigned i)
74 {
75 m_values.remove(i);
76 }
77
extend(CSSParserValueList & valueList)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
createCSSValue()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
CSSParserSelector()167 CSSParserSelector::CSSParserSelector()
168 : m_selector(adoptPtr(new CSSSelector()))
169 , m_functionArgumentSelector(0)
170 {
171 }
172
CSSParserSelector(const QualifiedName & tagQName)173 CSSParserSelector::CSSParserSelector(const QualifiedName& tagQName)
174 : m_selector(adoptPtr(new CSSSelector(tagQName)))
175 , m_functionArgumentSelector(0)
176 {
177 }
178
~CSSParserSelector()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
adoptSelectorVector(Vector<OwnPtr<CSSParserSelector>> & selectorVector)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
isSimple() const201 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
insertTagHistory(CSSSelector::Relation before,PassOwnPtr<CSSParserSelector> selector,CSSSelector::Relation after)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
appendTagHistory(CSSSelector::Relation relation,PassOwnPtr<CSSParserSelector> selector)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
prependTagSelector(const QualifiedName & tagQName,bool tagIsForNamespaceRule)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
findDistributedPseudoElementSelector() const250 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