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

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: Added a fixme saying that a generic solution can replace this one 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 // FIXME: Replace the MediaQueryTokenizer with a generic CSSTokenizer, once ther e is one,
eseidel 2014/03/08 22:08:07 Fantatisc, thank you for highlighting this.
21 // or better yet, replace the MediaQueryParser with a generic thread-safe CSS pa rser.
22 MediaQueryParser::MediaQueryParser(String queryString)
23 : m_state(&MediaQueryParser::readRestrictor)
24 {
25 MediaQueryTokenizer::tokenize(queryString, m_tokens);
26 }
27
28 // State machine member functions start here
29 void MediaQueryParser::readRestrictor(MediaQueryTokenType type, TokenIterator& t oken)
30 {
31 readMediaType(type, token);
32 }
33
34 void MediaQueryParser::readMediaType(MediaQueryTokenType type, TokenIterator& to ken)
35 {
36 if (type == LeftParenToken) {
37 m_state = &MediaQueryParser::readFeature;
38 } else if (type == IdentToken) {
39 if (m_state == &MediaQueryParser::readRestrictor && token->value().lower () == "not") {
40 m_mediaQueryData.setRestrictor(MediaQuery::Not);
41 m_state = &MediaQueryParser::readMediaType;
42 } else if (m_state == &MediaQueryParser::readRestrictor && token->value( ).lower() == "only") {
43 m_mediaQueryData.setRestrictor(MediaQuery::Only);
44 m_state = &MediaQueryParser::readMediaType;
45 } else {
46 m_mediaQueryData.setMediaType(token->value());
47 m_state = &MediaQueryParser::readAnd;
48 }
49 } else if (type == EOFToken && (!m_mediaQueryData.querySetSize() || m_state != &MediaQueryParser::readRestrictor)) {
50 m_state = &MediaQueryParser::done;
51 } else {
52 if (type == CommaToken)
53 --token;
54 m_state = &MediaQueryParser::skipTillComma;
55 }
56 }
57
58 void MediaQueryParser::readAnd(MediaQueryTokenType type, TokenIterator& token)
59 {
60 if (type == IdentToken && token->value().lower() == "and") {
61 m_state = &MediaQueryParser::readFeatureStart;
62 } else if (type == CommaToken) {
63 m_mediaQueryData.addCurrentMediaQuery();
64 m_state = &MediaQueryParser::readRestrictor;
65 } else if (type == EOFToken) {
66 m_state = &MediaQueryParser::done;
67 } else {
68 m_state = &MediaQueryParser::skipTillComma;
69 }
70 }
71
72 void MediaQueryParser::readFeatureStart(MediaQueryTokenType type, TokenIterator& token)
73 {
74 if (type == LeftParenToken)
75 m_state = &MediaQueryParser::readFeature;
76 else
77 m_state = &MediaQueryParser::skipTillComma;
78 }
79
80 void MediaQueryParser::readFeature(MediaQueryTokenType type, TokenIterator& toke n)
81 {
82 if (type == IdentToken) {
83 m_mediaQueryData.setMediaFeature(token->value());
84 m_state = &MediaQueryParser::readFeatureColon;
85 } else {
86 m_state = &MediaQueryParser::skipTillComma;
87 }
88 }
89
90 void MediaQueryParser::readFeatureColon(MediaQueryTokenType type, TokenIterator& token)
91 {
92 if (type == ColonToken) {
93 m_state = &MediaQueryParser::readFeatureValue;
94 } else if (type == RightParenToken || type == EOFToken) {
95 --token;
96 m_state = &MediaQueryParser::readFeatureEnd;
97 } else {
98 m_state = &MediaQueryParser::skipTillParen;
99 }
100 }
101
102 void MediaQueryParser::readFeatureValue(MediaQueryTokenType type, TokenIterator& token)
103 {
104 if (type == DimensionToken && token->unitType() == CSSPrimitiveValue::CSS_UN KNOWN) {
105 m_state = &MediaQueryParser::skipTillComma;
106 } else {
107 m_mediaQueryData.addParserValue(type, token);
108 m_state = &MediaQueryParser::readFeatureEnd;
109 }
110 }
111
112 void MediaQueryParser::readFeatureEnd(MediaQueryTokenType type, TokenIterator& t oken)
113 {
114 if (type == RightParenToken || type == EOFToken) {
115 if (m_mediaQueryData.addExpression())
116 m_state = &MediaQueryParser::readAnd;
117 else
118 m_state = &MediaQueryParser::skipTillComma;
119 } else if (type == DelimToken && token->delimiter() == '/') {
120 m_mediaQueryData.addParserValue(type, token);
121 m_state = &MediaQueryParser::readFeatureValue;
122 } else {
123 m_state = &MediaQueryParser::skipTillParen;
124 }
125 }
126
127 void MediaQueryParser::skipTillComma(MediaQueryTokenType type, TokenIterator& to ken)
128 {
129 if (type == CommaToken || type == EOFToken) {
130 m_state = &MediaQueryParser::readRestrictor;
131 m_mediaQueryData.resetCurrentQuery();
132 m_mediaQueryData.addNotAllMediaQuery();
133 }
134 }
135
136 void MediaQueryParser::skipTillParen(MediaQueryTokenType type, TokenIterator& to ken)
137 {
138 if (type == RightParenToken)
139 m_state = &MediaQueryParser::skipTillComma;
140 }
141
142 void MediaQueryParser::done(MediaQueryTokenType type, TokenIterator& token) { }
143
144 // The state machine loop
145 PassRefPtrWillBeRawPtr<MediaQuerySet> MediaQueryParser::parseImpl()
146 {
147 MediaQueryTokenType type;
148
149 for (Vector<MediaQueryToken>::iterator token = m_tokens.begin(); token != m_ tokens.end(); ++token) {
150 type = token->type();
151 if (type == WhitespaceToken)
152 continue;
153
154 // Call the function that handles current state
155 ((this)->*(m_state))(type, token);
156 }
157
158 if (m_state != &MediaQueryParser::readAnd && m_state != &MediaQueryParser::r eadRestrictor && m_state != &MediaQueryParser::done)
159 m_mediaQueryData.addNotAllMediaQuery();
160 else if (m_mediaQueryData.currentMediaQueryChanged())
161 m_mediaQueryData.addCurrentMediaQuery();
162
163 return m_mediaQueryData.querySet();
164 }
165
166 MediaQueryData::MediaQueryData()
167 : m_querySet(MediaQuerySet::create())
168 , m_restrictor(MediaQuery::None)
169 , m_mediaType(MediaTypeNames::all)
170 , m_expressions(adoptPtr(new ExpressionHeapVector()))
171 , m_mediaTypeSet(false)
172 {
173 }
174
175 void MediaQueryData::resetCurrentQuery()
176 {
177 m_mediaType = MediaTypeNames::all;
178 m_mediaTypeSet = false;
179 m_mediaFeature = "";
180 m_restrictor = MediaQuery::None;
181 m_valueList.clear();
182 m_expressions = adoptPtr(new ExpressionHeapVector());
183 }
184
185 void MediaQueryData::addCurrentMediaQuery()
186 {
187 m_querySet->addMediaQuery(adoptPtr(new MediaQuery(m_restrictor, m_mediaType, m_expressions.release())));
188 resetCurrentQuery();
189 }
190
191 bool MediaQueryData::addExpression()
192 {
193 OwnPtr<MediaQueryExp> expression = MediaQueryExp::create(m_mediaFeature, &(m _valueList));
194 bool retValue = (expression.get());
195 m_expressions->append(expression.release());
196 m_valueList.clear();
197 return retValue;
198 }
199
200 void MediaQueryData::addParserValue(MediaQueryTokenType type, MediaQueryToken* t oken)
201 {
202 CSSParserValue value;
203 if (type == NumberToken || type == PercentageToken || type == DimensionToken ) {
204 value.setFromNumber(token->numericValue(), token->unitType());
205 value.isInt = (token->numericValueType() == IntegerValueType);
206 } else if (type == DelimToken) {
207 value.unit = CSSParserValue::Operator;
208 value.iValue = token->delimiter();
209 } else {
210 CSSParserFunction* function = new CSSParserFunction;
211 function->name.init(token->value());
212 value.setFromFunction(function);
213 CSSParserString tokenValue;
214 tokenValue.init(token->value());
215 value.id = cssValueKeywordID(tokenValue);
216 }
217 m_valueList.addValue(value);
218 }
219
220 void MediaQueryData::setMediaType(const String& mediaType)
221 {
222 m_mediaType = mediaType;
223 m_mediaTypeSet = true;
224 }
225
226 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698