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

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: Fix a debug build error 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();
eseidel 2014/03/13 17:22:07 nit: This could even be one line: return MediaQuer
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 {
26 MediaQueryTokenizer::tokenize(queryString, m_tokens);
27 }
28
29 void MediaQueryParser::setStateAndRestrict(State state, MediaQuery::Restrictor r estrictor)
30 {
31 m_mediaQueryData.setRestrictor(restrictor);
32 m_state = state;
33 }
34
35 // State machine member functions start here
36 void MediaQueryParser::readRestrictor(MediaQueryTokenType type, TokenIterator& t oken)
37 {
38 readMediaType(type, token);
39 }
40
41 void MediaQueryParser::readMediaType(MediaQueryTokenType type, TokenIterator& to ken)
42 {
43 if (type == LeftParenthesisToken) {
44 m_state = ReadFeature;
45 } else if (type == IdentToken) {
46 if (m_state == ReadRestrictor && equalIgnoringCase(token->value(), "not" )) {
eseidel 2014/03/13 17:22:07 Does this compile? token.value() no?
47 setStateAndRestrict(ReadMediaType, MediaQuery::Not);
48 } else if (m_state == ReadRestrictor && equalIgnoringCase(token->value() , "only")) {
49 setStateAndRestrict(ReadMediaType, MediaQuery::Only);
50 } else {
51 m_mediaQueryData.setMediaType(token->value());
52 m_state = ReadAnd;
53 }
54 } else if (type == EOFToken && (!m_querySet->queryVector().size() || m_state != ReadRestrictor)) {
55 m_state = Done;
eseidel 2014/03/13 17:22:07 This reads much nicer, thanks.
56 } else {
57 if (type == CommaToken)
58 --token;
59 m_state = SkipUntilComma;
60 }
61 }
62
63 void MediaQueryParser::readAnd(MediaQueryTokenType type, TokenIterator& token)
64 {
65 if (type == IdentToken && equalIgnoringCase(token->value(), "and")) {
66 m_state = ReadFeatureStart;
67 } else if (type == CommaToken) {
68 m_querySet->addMediaQuery(m_mediaQueryData.takeMediaQueryAndClear());
69 m_state = ReadRestrictor;
70 } else if (type == EOFToken) {
71 m_state = Done;
72 } else {
73 m_state = SkipUntilComma;
74 }
75 }
76
77 void MediaQueryParser::readFeatureStart(MediaQueryTokenType type, TokenIterator& token)
78 {
79 if (type == LeftParenthesisToken)
80 m_state = ReadFeature;
81 else
82 m_state = SkipUntilComma;
83 }
84
85 void MediaQueryParser::readFeature(MediaQueryTokenType type, TokenIterator& toke n)
86 {
87 if (type == IdentToken) {
88 m_mediaQueryData.setMediaFeature(token->value());
89 m_state = ReadFeatureColon;
90 } else {
91 m_state = SkipUntilComma;
92 }
93 }
94
95 void MediaQueryParser::readFeatureColon(MediaQueryTokenType type, TokenIterator& token)
96 {
97 if (type == ColonToken) {
98 m_state = ReadFeatureValue;
99 } else if (type == RightParenthesisToken || type == EOFToken) {
100 --token;
101 m_state = ReadFeatureEnd;
102 } else {
103 m_state = SkipUntilParenthesis;
104 }
105 }
106
107 void MediaQueryParser::readFeatureValue(MediaQueryTokenType type, TokenIterator& token)
108 {
109 if (type == DimensionToken && token->unitType() == CSSPrimitiveValue::CSS_UN KNOWN) {
110 m_state = SkipUntilComma;
111 } else {
112 m_mediaQueryData.addParserValue(type, *token);
113 m_state = ReadFeatureEnd;
114 }
115 }
116
117 void MediaQueryParser::readFeatureEnd(MediaQueryTokenType type, TokenIterator& t oken)
118 {
119 if (type == RightParenthesisToken || type == EOFToken) {
120 if (m_mediaQueryData.addExpression())
121 m_state = ReadAnd;
122 else
123 m_state = SkipUntilComma;
124 } else if (type == DelimiterToken && token->delimiter() == '/') {
125 m_mediaQueryData.addParserValue(type, *token);
126 m_state = ReadFeatureValue;
127 } else {
128 m_state = SkipUntilParenthesis;
129 }
130 }
131
132 void MediaQueryParser::skipUntilComma(MediaQueryTokenType type, TokenIterator& t oken)
133 {
134 if (type == CommaToken || type == EOFToken) {
135 m_state = ReadRestrictor;
136 m_mediaQueryData = MediaQueryData();
137 m_querySet->addMediaQuery(MediaQuery::createNotAll());
138 }
139 }
140
141 void MediaQueryParser::skipUntilParenthesis(MediaQueryTokenType type, TokenItera tor& token)
142 {
143 if (type == RightParenthesisToken)
144 m_state = SkipUntilComma;
145 }
146
147 void MediaQueryParser::done(MediaQueryTokenType type, TokenIterator& token) { }
148
149 void MediaQueryParser::processToken(TokenIterator& token)
150 {
151 MediaQueryTokenType type = token->type();
152
153 // Call the function that handles current state
154 if (type != WhitespaceToken)
155 ((this)->*(m_state))(type, token);
156 }
157
158 // The state machine loop
159 PassRefPtrWillBeRawPtr<MediaQuerySet> MediaQueryParser::parseImpl()
160 {
161 for (Vector<MediaQueryToken>::iterator token = m_tokens.begin(); token != m_ tokens.end(); ++token)
162 processToken(token);
163
164 if (m_state != ReadAnd && m_state != ReadRestrictor && m_state != Done)
165 m_querySet->addMediaQuery(MediaQuery::createNotAll());
166 else if (m_mediaQueryData.currentMediaQueryChanged())
167 m_querySet->addMediaQuery(m_mediaQueryData.takeMediaQueryAndClear());
eseidel 2014/03/13 17:22:07 I think "take" implies "clear" for most readers.
168
169 return m_querySet;
170 }
171
172 MediaQueryData::MediaQueryData()
173 : m_restrictor(MediaQuery::None)
174 , m_mediaType(MediaTypeNames::all)
175 , m_expressions(adoptPtr(new ExpressionHeapVector()))
eseidel 2014/03/13 17:22:07 Is adoptPtr even needed with OwnPtr?
176 , m_mediaTypeSet(false)
177 {
178 }
179
180 PassOwnPtr<MediaQuery> MediaQueryData::takeMediaQueryAndClear()
181 {
182 MediaQuery* mediaQuery = new MediaQuery(m_restrictor, m_mediaType, m_express ions.release());
183 *this = MediaQueryData();
184 return adoptPtr(mediaQuery);
185 }
186
187 bool MediaQueryData::addExpression()
188 {
189 OwnPtr<MediaQueryExp> expression = MediaQueryExp::create(m_mediaFeature, &m_ valueList);
190 bool isValid = !!expression;
191 m_expressions->append(expression.release());
192 m_valueList.clear();
193 return isValid;
194 }
195
196 void MediaQueryData::addParserValue(MediaQueryTokenType type, MediaQueryToken& t oken)
197 {
198 CSSParserValue value;
199 if (type == NumberToken || type == PercentageToken || type == DimensionToken ) {
200 value.setFromNumber(token.numericValue(), token.unitType());
201 value.isInt = (token.numericValueType() == IntegerValueType);
202 } else if (type == DelimiterToken) {
203 value.unit = CSSParserValue::Operator;
204 value.iValue = token.delimiter();
205 } else {
206 CSSParserFunction* function = new CSSParserFunction;
207 function->name.init(token.value());
208 value.setFromFunction(function);
209 CSSParserString tokenValue;
210 tokenValue.init(token.value());
211 value.id = cssValueKeywordID(tokenValue);
212 }
213 m_valueList.addValue(value);
214 }
215
216 void MediaQueryData::setMediaType(const String& mediaType)
217 {
218 m_mediaType = mediaType;
219 m_mediaTypeSet = true;
220 }
221
222 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698