Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Side by Side Diff: Source/core/css/parser/MediaQueryParser.cpp

Issue 171383002: A thread-safe Media Query Parser (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Rebased and fixed float parsing Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "core/css/parser/MediaQueryParser.h"
7
8 #include "MediaTypeNames.h"
9 #include "core/css/parser/CSSPropertyParser.h"
10 #include "core/css/parser/MediaQueryTokenizer.h"
11
12 namespace WebCore {
13
14 PassRefPtrWillBeRawPtr<MediaQuerySet> MediaQueryParser::parse(String queryString )
15 {
16 MediaQueryParser parser(queryString);
17 return parser.parseImpl();
18 }
19
20 MediaQueryParser::MediaQueryParser(String queryString)
21 : m_state(&MediaQueryParser::readRestrictor)
22 {
23 MediaQueryTokenizer::tokenize(queryString, m_tokens);
24 }
25
26 // State machine member functions start here
27 void MediaQueryParser::readRestrictor(CSSTokenType type, TokenIterator& token)
28 {
29 readMediaType(type, token);
30 }
31
32 void MediaQueryParser::readMediaType(CSSTokenType type, TokenIterator& token)
33 {
34 if (type == LeftParenToken) {
35 m_state = &MediaQueryParser::readFeature;
36 } else if (type == IdentToken) {
37 if (m_state == &MediaQueryParser::readRestrictor && token->value().lower () == "not") {
38 m_mediaQueryData.setRestrictor(MediaQuery::Not);
39 m_state = &MediaQueryParser::readMediaType;
40 } else if (m_state == &MediaQueryParser::readRestrictor && token->value( ).lower() == "only") {
41 m_mediaQueryData.setRestrictor(MediaQuery::Only);
42 m_state = &MediaQueryParser::readMediaType;
43 } else {
44 m_mediaQueryData.setMediaType(token->value());
45 m_state = &MediaQueryParser::readAnd;
46 }
47 } else if (type == EOFToken && (!m_mediaQueryData.querySetSize() || m_state != &MediaQueryParser::readRestrictor)) {
48 m_state = &MediaQueryParser::done;
49 } else {
50 if (type == CommaToken)
51 --token;
52 m_state = &MediaQueryParser::skipTillComma;
53 }
54 }
55
56 void MediaQueryParser::readAnd(CSSTokenType type, TokenIterator& token)
57 {
58 if (type == IdentToken && token->value().lower() == "and") {
59 m_state = &MediaQueryParser::readFeatureStart;
60 } else if (type == CommaToken) {
61 m_mediaQueryData.addCurrentMediaQuery();
62 m_state = &MediaQueryParser::readRestrictor;
63 } else if (type == EOFToken) {
64 m_state = &MediaQueryParser::done;
65 } else {
66 m_state = &MediaQueryParser::skipTillComma;
67 }
68 }
69
70 void MediaQueryParser::readFeatureStart(CSSTokenType type, TokenIterator& token)
71 {
72 if (type == LeftParenToken)
73 m_state = &MediaQueryParser::readFeature;
74 else
75 m_state = &MediaQueryParser::skipTillComma;
76 }
77
78 void MediaQueryParser::readFeature(CSSTokenType type, TokenIterator& token)
79 {
80 if (type == IdentToken) {
81 m_mediaQueryData.setMediaFeature(token->value());
82 m_state = &MediaQueryParser::readFeatureColon;
83 } else {
84 m_state = &MediaQueryParser::skipTillComma;
85 }
86 }
87
88 void MediaQueryParser::readFeatureColon(CSSTokenType type, TokenIterator& token)
89 {
90 if (type == ColonToken) {
91 m_state = &MediaQueryParser::readFeatureValue;
92 } else if (type == RightParenToken || type == EOFToken) {
93 --token;
94 m_state = &MediaQueryParser::readFeatureEnd;
95 } else {
96 m_state = &MediaQueryParser::skipTillParen;
97 }
98 }
99
100 void MediaQueryParser::readFeatureValue(CSSTokenType type, TokenIterator& token)
101 {
102 if (type == DimensionToken && token->unitType() == CSSPrimitiveValue::CSS_UN KNOWN) {
103 m_state = &MediaQueryParser::skipTillComma;
104 } else {
105 m_mediaQueryData.addParserValue(type, token);
106 m_state = &MediaQueryParser::readFeatureEnd;
107 }
108 }
109
110 void MediaQueryParser::readFeatureEnd(CSSTokenType type, TokenIterator& token)
111 {
112 if (type == RightParenToken || type == EOFToken) {
113 if (m_mediaQueryData.addExpression())
114 m_state = &MediaQueryParser::readAnd;
115 else
116 m_state = &MediaQueryParser::skipTillComma;
117 } else if (type == DelimToken && token->delimiter() == '/') {
118 m_mediaQueryData.addParserValue(type, token);
119 m_state = &MediaQueryParser::readFeatureValue;
120 } else {
121 m_state = &MediaQueryParser::skipTillParen;
122 }
123 }
124
125 void MediaQueryParser::skipTillComma(CSSTokenType type, TokenIterator& token)
126 {
127 if (type == CommaToken || type == EOFToken) {
128 m_state = &MediaQueryParser::readRestrictor;
129 m_mediaQueryData.resetCurrentQuery();
130 m_mediaQueryData.addNotAllMediaQuery();
131 }
132 }
133
134 void MediaQueryParser::skipTillParen(CSSTokenType type, TokenIterator& token)
135 {
136 if (type == RightParenToken)
137 m_state = &MediaQueryParser::skipTillComma;
138 }
139
140 void MediaQueryParser::done(CSSTokenType type, TokenIterator& token) { }
141
142 // The state machine loop
143 PassRefPtrWillBeRawPtr<MediaQuerySet> MediaQueryParser::parseImpl()
144 {
145 CSSTokenType type;
146
147 for (Vector<CSSToken>::iterator token = m_tokens.begin(); token != m_tokens. end(); ++token) {
148 type = token->type();
149 if (type == WhitespaceToken)
150 continue;
151
152 // Call the function that handles current state
153 ((this)->*(m_state))(type, token);
154 }
155
156 if (m_state != &MediaQueryParser::readAnd && m_state != &MediaQueryParser::r eadRestrictor && m_state != &MediaQueryParser::done)
157 m_mediaQueryData.addNotAllMediaQuery();
158 else if (m_mediaQueryData.currentMediaQueryChanged())
159 m_mediaQueryData.addCurrentMediaQuery();
160
161 return m_mediaQueryData.querySet();
162 }
163
164 MediaQueryData::MediaQueryData()
165 : m_querySet(MediaQuerySet::create())
166 , m_restrictor(MediaQuery::None)
167 , m_mediaType(MediaTypeNames::all)
168 , m_expressions(adoptPtr(new ExpressionHeapVector()))
169 , m_mediaTypeSet(false)
170 {
171 }
172
173 void MediaQueryData::resetCurrentQuery()
174 {
175 m_mediaType = MediaTypeNames::all;
176 m_mediaTypeSet = false;
177 m_mediaFeature = "";
178 m_restrictor = MediaQuery::None;
179 m_valueList.clear();
180 m_expressions = adoptPtr(new ExpressionHeapVector());
181 }
182
183 void MediaQueryData::addCurrentMediaQuery()
184 {
185 m_querySet->addMediaQuery(adoptPtr(new MediaQuery(m_restrictor, m_mediaType, m_expressions.release())));
186 resetCurrentQuery();
187 }
188
189 bool MediaQueryData::addExpression()
190 {
191 OwnPtr<MediaQueryExp> expression = MediaQueryExp::create(m_mediaFeature, &(m _valueList));
192 bool retValue = (expression.get());
193 m_expressions->append(expression.release());
194 m_valueList.clear();
195 return retValue;
196 }
197
198 void MediaQueryData::addParserValue(CSSTokenType type, CSSToken* token)
199 {
200 CSSParserValue value;
201 if (type == NumberToken || type == PercentageToken || type == DimensionToken ) {
202 value.setFromNumber(token->numericValue(), token->unitType());
203 value.isInt = (token->numericValueType() == IntegerValueType);
204 } else if (type == DelimToken) {
205 value.unit = CSSParserValue::Operator;
206 value.iValue = token->delimiter();
207 } else {
208 CSSParserFunction* function = new CSSParserFunction;
209 function->name.init(token->value());
210 value.setFromFunction(function);
211 CSSParserString tokenValue;
212 tokenValue.init(token->value());
213 value.id = cssValueKeywordID(tokenValue);
214 }
215 m_valueList.addValue(value);
216 }
217
218 void MediaQueryData::setMediaType(const String& mediaType)
219 {
220 m_mediaType = mediaType;
221 m_mediaTypeSet = true;
222 }
223
224 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698