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

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: Fixed gcc compile issues and debug asserts 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(const String& quer yString)
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,
21 // or better yet, replace the MediaQueryParser with a generic thread-safe CSS pa rser.
22 MediaQueryParser::MediaQueryParser(const String& queryString)
23 : m_state(&MediaQueryParser::readRestrictor)
24 , m_querySet(MediaQuerySet::create())
25 , ReadRestrictor(&MediaQueryParser::readRestrictor)
eseidel 2014/03/13 17:58:45 I'm surprised these can't just be static? Either
26 , ReadMediaType(&MediaQueryParser::readMediaType)
27 , ReadAnd(&MediaQueryParser::readAnd)
28 , ReadFeatureStart(&MediaQueryParser::readFeatureStart)
29 , ReadFeature(&MediaQueryParser::readFeature)
30 , ReadFeatureColon(&MediaQueryParser::readFeatureColon)
31 , ReadFeatureValue(&MediaQueryParser::readFeatureValue)
32 , ReadFeatureEnd(&MediaQueryParser::readFeatureEnd)
33 , SkipUntilComma(&MediaQueryParser::skipUntilComma)
34 , SkipUntilParenthesis(&MediaQueryParser::skipUntilParenthesis)
35 , Done(&MediaQueryParser::done)
36
37 {
38 MediaQueryTokenizer::tokenize(queryString, m_tokens);
39 }
40
41 void MediaQueryParser::setStateAndRestrict(State state, MediaQuery::Restrictor r estrictor)
42 {
43 m_mediaQueryData.setRestrictor(restrictor);
44 m_state = state;
45 }
46
47 // State machine member functions start here
48 void MediaQueryParser::readRestrictor(MediaQueryTokenType type, TokenIterator& t oken)
49 {
50 readMediaType(type, token);
51 }
52
53 void MediaQueryParser::readMediaType(MediaQueryTokenType type, TokenIterator& to ken)
54 {
55 if (type == LeftParenthesisToken) {
56 m_state = ReadFeature;
57 } else if (type == IdentToken) {
58 if (m_state == ReadRestrictor && equalIgnoringCase(token->value(), "not" )) {
eseidel 2014/03/13 17:58:45 I see, so -> dereferences the iterator's current v
Yoav Weiss 2014/03/13 22:19:16 Yeah
59 setStateAndRestrict(ReadMediaType, MediaQuery::Not);
60 } else if (m_state == ReadRestrictor && equalIgnoringCase(token->value() , "only")) {
61 setStateAndRestrict(ReadMediaType, MediaQuery::Only);
62 } else {
63 m_mediaQueryData.setMediaType(token->value());
64 m_state = ReadAnd;
65 }
66 } else if (type == EOFToken && (!m_querySet->queryVector().size() || m_state != ReadRestrictor)) {
67 m_state = Done;
68 } else {
69 if (type == CommaToken)
70 --token;
71 m_state = SkipUntilComma;
72 }
73 }
74
75 void MediaQueryParser::readAnd(MediaQueryTokenType type, TokenIterator& token)
76 {
77 if (type == IdentToken && equalIgnoringCase(token->value(), "and")) {
78 m_state = ReadFeatureStart;
79 } else if (type == CommaToken) {
80 m_querySet->addMediaQuery(m_mediaQueryData.takeMediaQueryAndClear());
81 m_state = ReadRestrictor;
82 } else if (type == EOFToken) {
83 m_state = Done;
84 } else {
85 m_state = SkipUntilComma;
86 }
87 }
88
89 void MediaQueryParser::readFeatureStart(MediaQueryTokenType type, TokenIterator& token)
90 {
91 if (type == LeftParenthesisToken)
92 m_state = ReadFeature;
93 else
94 m_state = SkipUntilComma;
95 }
96
97 void MediaQueryParser::readFeature(MediaQueryTokenType type, TokenIterator& toke n)
98 {
99 if (type == IdentToken) {
100 m_mediaQueryData.setMediaFeature(token->value());
101 m_state = ReadFeatureColon;
102 } else {
103 m_state = SkipUntilComma;
104 }
105 }
106
107 void MediaQueryParser::readFeatureColon(MediaQueryTokenType type, TokenIterator& token)
108 {
109 if (type == ColonToken) {
110 m_state = ReadFeatureValue;
111 } else if (type == RightParenthesisToken || type == EOFToken) {
112 --token;
113 m_state = ReadFeatureEnd;
114 } else {
115 m_state = SkipUntilParenthesis;
116 }
117 }
118
119 void MediaQueryParser::readFeatureValue(MediaQueryTokenType type, TokenIterator& token)
120 {
121 if (type == DimensionToken && token->unitType() == CSSPrimitiveValue::CSS_UN KNOWN) {
122 m_state = SkipUntilComma;
123 } else {
124 m_mediaQueryData.addParserValue(type, *token);
125 m_state = ReadFeatureEnd;
126 }
127 }
128
129 void MediaQueryParser::readFeatureEnd(MediaQueryTokenType type, TokenIterator& t oken)
130 {
131 if (type == RightParenthesisToken || type == EOFToken) {
132 if (m_mediaQueryData.addExpression())
133 m_state = ReadAnd;
134 else
135 m_state = SkipUntilComma;
136 } else if (type == DelimiterToken && token->delimiter() == '/') {
137 m_mediaQueryData.addParserValue(type, *token);
138 m_state = ReadFeatureValue;
139 } else {
140 m_state = SkipUntilParenthesis;
141 }
142 }
143
144 void MediaQueryParser::skipUntilComma(MediaQueryTokenType type, TokenIterator& t oken)
145 {
146 if (type == CommaToken || type == EOFToken) {
147 m_state = ReadRestrictor;
148 m_mediaQueryData.clear();
149 m_querySet->addMediaQuery(MediaQuery::createNotAll());
150 }
151 }
152
153 void MediaQueryParser::skipUntilParenthesis(MediaQueryTokenType type, TokenItera tor& token)
154 {
155 if (type == RightParenthesisToken)
156 m_state = SkipUntilComma;
157 }
158
159 void MediaQueryParser::done(MediaQueryTokenType type, TokenIterator& token) { }
160
161 void MediaQueryParser::processToken(TokenIterator& token)
162 {
163 MediaQueryTokenType type = token->type();
164
165 // Call the function that handles current state
166 if (type != WhitespaceToken)
167 ((this)->*(m_state))(type, token);
168 }
169
170 // The state machine loop
171 PassRefPtrWillBeRawPtr<MediaQuerySet> MediaQueryParser::parseImpl()
172 {
173 for (Vector<MediaQueryToken>::iterator token = m_tokens.begin(); token != m_ tokens.end(); ++token)
174 processToken(token);
175
176 if (m_state != ReadAnd && m_state != ReadRestrictor && m_state != Done)
177 m_querySet->addMediaQuery(MediaQuery::createNotAll());
178 else if (m_mediaQueryData.currentMediaQueryChanged())
179 m_querySet->addMediaQuery(m_mediaQueryData.takeMediaQueryAndClear());
180
181 return m_querySet;
182 }
183
184 MediaQueryData::MediaQueryData()
185 : m_restrictor(MediaQuery::None)
186 , m_mediaType(MediaTypeNames::all)
187 , m_expressions(adoptPtr(new ExpressionHeapVector))
eseidel 2014/03/13 17:58:45 I'm surprised the adoptPtr is needed?
Yoav Weiss 2014/03/13 22:19:16 When doing `, m_expressions(new ExpressionHeapVect
188 , m_mediaTypeSet(false)
189 {
190 }
191
192 void MediaQueryData::clear()
193 {
194 m_restrictor = MediaQuery::None;
195 m_mediaType = MediaTypeNames::all;
196 m_mediaTypeSet = false;
197 m_mediaFeature = String();
198 m_valueList.clear();
199 m_expressions = adoptPtr(new ExpressionHeapVector);
200 }
201
202 PassOwnPtr<MediaQuery> MediaQueryData::takeMediaQueryAndClear()
203 {
204 MediaQuery* mediaQuery = new MediaQuery(m_restrictor, m_mediaType, m_express ions.release());
eseidel 2014/03/13 17:58:45 Normally adoptPtr is on the same line as new. che
205 clear();
206 return adoptPtr(mediaQuery);
207 }
208
209 bool MediaQueryData::addExpression()
210 {
211 OwnPtr<MediaQueryExp> expression = MediaQueryExp::create(m_mediaFeature, &m_ valueList);
eseidel 2014/03/13 17:58:45 We need to rename the create() method if it can re
212 bool isValid = !!expression;
213 m_expressions->append(expression.release());
214 m_valueList.clear();
215 return isValid;
216 }
217
218 void MediaQueryData::addParserValue(MediaQueryTokenType type, MediaQueryToken& t oken)
219 {
220 CSSParserValue value;
221 if (type == NumberToken || type == PercentageToken || type == DimensionToken ) {
222 value.setFromNumber(token.numericValue(), token.unitType());
223 value.isInt = (token.numericValueType() == IntegerValueType);
224 } else if (type == DelimiterToken) {
225 value.unit = CSSParserValue::Operator;
226 value.iValue = token.delimiter();
227 } else {
228 CSSParserFunction* function = new CSSParserFunction;
eseidel 2014/03/13 17:58:45 How is memory management dealt with here?
Yoav Weiss 2014/03/13 22:19:16 function (CSSParserFunction) is added to value (CS
229 function->name.init(token.value());
230 value.setFromFunction(function);
231 CSSParserString tokenValue;
232 tokenValue.init(token.value());
233 value.id = cssValueKeywordID(tokenValue);
234 }
235 m_valueList.addValue(value);
236 }
237
238 void MediaQueryData::setMediaType(const String& mediaType)
239 {
240 m_mediaType = mediaType;
241 m_mediaTypeSet = true;
242 }
243
244 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698