OLD | NEW |
| (Empty) |
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 "core/css/parser/CSSParserValues.h" | |
22 | |
23 #include "core/css/CSSFunctionValue.h" | |
24 #include "core/css/parser/CSSParserToken.h" | |
25 #include "core/css/parser/CSSParserTokenRange.h" | |
26 #include "core/css/parser/CSSPropertyParser.h" | |
27 #include "core/html/parser/HTMLParserIdioms.h" | |
28 | |
29 namespace blink { | |
30 | |
31 using namespace WTF; | |
32 | |
33 CSSParserValueList::CSSParserValueList(CSSParserTokenRange range) | |
34 : m_current(0) | |
35 { | |
36 Vector<CSSParserValueList*> stack; | |
37 Vector<int> bracketCounts; | |
38 stack.append(this); | |
39 bracketCounts.append(0); | |
40 while (!range.atEnd()) { | |
41 ASSERT(stack.size() == bracketCounts.size()); | |
42 ASSERT(!stack.isEmpty()); | |
43 const CSSParserToken& token = range.peek(); | |
44 if (token.type() != FunctionToken) | |
45 range.consume(); | |
46 CSSParserValue value; | |
47 switch (token.type()) { | |
48 case FunctionToken: { | |
49 if (token.valueEqualsIgnoringASCIICase("url")) { | |
50 range.consume(); | |
51 const CSSParserToken& next = range.consumeIncludingWhitespace(); | |
52 if (next.type() == BadStringToken || range.consume().type() != R
ightParenthesisToken) { | |
53 destroyAndClear(); | |
54 return; | |
55 } | |
56 ASSERT(next.type() == StringToken); | |
57 value.id = CSSValueInvalid; | |
58 value.isInt = false; | |
59 value.m_unit = CSSParserValue::URI; | |
60 value.string = next.value(); | |
61 break; | |
62 } | |
63 if (token.valueEqualsIgnoringASCIICase("var")) { | |
64 destroyAndClear(); | |
65 return; | |
66 } | |
67 | |
68 value.id = CSSValueInvalid; | |
69 value.isInt = false; | |
70 | |
71 CSSValueID id = token.functionId(); | |
72 if (id == CSSValueCalc || id == CSSValueWebkitCalc) { | |
73 value.m_unit = CSSParserValue::CalcFunction; | |
74 value.calcFunction = new CSSParserCalcFunction(range.consumeBloc
k()); | |
75 break; | |
76 } | |
77 range.consume(); | |
78 value.m_unit = CSSParserValue::Function; | |
79 CSSParserFunction* function = new CSSParserFunction; | |
80 function->id = id; | |
81 CSSParserValueList* list = new CSSParserValueList; | |
82 function->args = adoptPtr(list); | |
83 | |
84 value.function = function; | |
85 | |
86 stack.last()->addValue(value); | |
87 stack.append(list); | |
88 bracketCounts.append(0); | |
89 continue; | |
90 } | |
91 case LeftParenthesisToken: { | |
92 CSSParserValueList* list = new CSSParserValueList; | |
93 value.setFromValueList(adoptPtr(list)); | |
94 stack.last()->addValue(value); | |
95 stack.append(list); | |
96 bracketCounts.append(0); | |
97 continue; | |
98 } | |
99 case RightParenthesisToken: { | |
100 if (bracketCounts.last() == 0) { | |
101 stack.removeLast(); | |
102 bracketCounts.removeLast(); | |
103 if (bracketCounts.isEmpty()) { | |
104 destroyAndClear(); | |
105 return; | |
106 } | |
107 continue; | |
108 } | |
109 bracketCounts.last()--; | |
110 value.setFromOperator(')'); | |
111 break; | |
112 } | |
113 case IdentToken: { | |
114 value.id = token.id(); | |
115 value.isInt = false; | |
116 value.m_unit = CSSParserValue::Identifier; | |
117 value.string = token.value(); | |
118 break; | |
119 } | |
120 case DimensionToken: | |
121 if (token.unitType() == CSSPrimitiveValue::UnitType::Unknown) { | |
122 // Unknown dimensions are handled as a list of two values | |
123 value.m_unit = CSSParserValue::DimensionList; | |
124 CSSParserValueList* list = new CSSParserValueList; | |
125 value.valueList = list; | |
126 value.id = CSSValueInvalid; | |
127 | |
128 CSSParserValue number; | |
129 number.setFromNumber(token.numericValue(), CSSPrimitiveValue::Un
itType::Number); | |
130 number.isInt = (token.numericValueType() == IntegerValueType); | |
131 list->addValue(number); | |
132 | |
133 CSSParserValue unit; | |
134 unit.string = token.value(); | |
135 unit.m_unit = CSSParserValue::Identifier; | |
136 list->addValue(unit); | |
137 | |
138 break; | |
139 } | |
140 // fallthrough | |
141 case NumberToken: | |
142 case PercentageToken: | |
143 value.setFromNumber(token.numericValue(), token.unitType()); | |
144 value.isInt = (token.numericValueType() == IntegerValueType); | |
145 break; | |
146 case UnicodeRangeToken: { | |
147 value.id = CSSValueInvalid; | |
148 value.isInt = false; | |
149 value.m_unicodeRange.start = token.unicodeRangeStart(); | |
150 value.m_unicodeRange.end = token.unicodeRangeEnd(); | |
151 value.m_unit = CSSParserValue::UnicodeRange; | |
152 break; | |
153 } | |
154 case HashToken: | |
155 case StringToken: | |
156 case UrlToken: { | |
157 value.id = CSSValueInvalid; | |
158 value.isInt = false; | |
159 if (token.type() == HashToken) | |
160 value.m_unit = CSSParserValue::HexColor; | |
161 else if (token.type() == StringToken) | |
162 value.m_unit = CSSParserValue::String; | |
163 else | |
164 value.m_unit = CSSParserValue::URI; | |
165 value.string = token.value(); | |
166 break; | |
167 } | |
168 case DelimiterToken: | |
169 value.setFromOperator(token.delimiter()); | |
170 break; | |
171 case CommaToken: | |
172 value.setFromOperator(','); | |
173 break; | |
174 case LeftBracketToken: | |
175 value.setFromOperator('['); | |
176 break; | |
177 case RightBracketToken: | |
178 value.setFromOperator(']'); | |
179 break; | |
180 case LeftBraceToken: | |
181 value.setFromOperator('{'); | |
182 break; | |
183 case RightBraceToken: | |
184 value.setFromOperator('}'); | |
185 break; | |
186 case WhitespaceToken: | |
187 continue; | |
188 case CommentToken: | |
189 case EOFToken: | |
190 ASSERT_NOT_REACHED(); | |
191 case CDOToken: | |
192 case CDCToken: | |
193 case AtKeywordToken: | |
194 case IncludeMatchToken: | |
195 case DashMatchToken: | |
196 case PrefixMatchToken: | |
197 case SuffixMatchToken: | |
198 case SubstringMatchToken: | |
199 case ColumnToken: | |
200 case ColonToken: | |
201 case SemicolonToken: | |
202 destroyAndClear(); | |
203 return; | |
204 case BadStringToken: | |
205 case BadUrlToken: | |
206 destroyAndClear(); | |
207 return; | |
208 } | |
209 stack.last()->addValue(value); | |
210 } | |
211 | |
212 CSSParserValue rightParenthesis; | |
213 rightParenthesis.setFromOperator(')'); | |
214 while (!stack.isEmpty()) { | |
215 while (bracketCounts.last() > 0) { | |
216 bracketCounts.last()--; | |
217 stack.last()->addValue(rightParenthesis); | |
218 } | |
219 stack.removeLast(); | |
220 bracketCounts.removeLast(); | |
221 } | |
222 } | |
223 | |
224 static void destroy(Vector<CSSParserValue, 4>& values) | |
225 { | |
226 size_t numValues = values.size(); | |
227 for (size_t i = 0; i < numValues; i++) { | |
228 if (values[i].m_unit == CSSParserValue::Function) | |
229 delete values[i].function; | |
230 else if (values[i].m_unit == CSSParserValue::CalcFunction) | |
231 delete values[i].calcFunction; | |
232 else if (values[i].m_unit == CSSParserValue::ValueList | |
233 || values[i].m_unit == CSSParserValue::DimensionList) | |
234 delete values[i].valueList; | |
235 } | |
236 } | |
237 | |
238 void CSSParserValueList::destroyAndClear() | |
239 { | |
240 destroy(m_values); | |
241 clearAndLeakValues(); | |
242 } | |
243 | |
244 CSSParserValueList::~CSSParserValueList() | |
245 { | |
246 destroy(m_values); | |
247 } | |
248 | |
249 void CSSParserValueList::addValue(const CSSParserValue& v) | |
250 { | |
251 m_values.append(v); | |
252 } | |
253 | |
254 } // namespace blink | |
OLD | NEW |