9097017a28cd30d652e95a7922a5f0d707ca82a8
[WebKit-https.git] / Source / WebCore / css / parser / CSSParserValues.h
1 /*
2  * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2014 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 #pragma once
22
23 #include "CSSSelector.h"
24 #include "CSSValueKeywords.h"
25 #include "CSSValueList.h"
26 #include <wtf/text/AtomicString.h>
27 #include <wtf/text/AtomicStringHash.h>
28 #include <wtf/text/WTFString.h>
29
30 namespace WebCore {
31
32 class CSSValue;
33 class QualifiedName;
34
35 // This should be a StringView but currently it can't because it's used as an element of a union in CSSParserValue.
36 struct CSSParserString {
37     void init(LChar* characters, unsigned length)
38     {
39         m_data.characters8 = characters;
40         m_length = length;
41         m_is8Bit = true;
42     }
43
44     void init(UChar* characters, unsigned length)
45     {
46         m_data.characters16 = characters;
47         m_length = length;
48         m_is8Bit = false;
49     }
50
51     void init(const String& string)
52     {
53         m_length = string.length();
54         if (!m_length || string.is8Bit()) {
55             m_data.characters8 = const_cast<LChar*>(string.characters8());
56             m_is8Bit = true;
57         } else {
58             m_data.characters16 = const_cast<UChar*>(string.characters16());
59             m_is8Bit = false;
60         }
61     }
62
63     void clear()
64     {
65         m_data.characters8 = 0;
66         m_length = 0;
67         m_is8Bit = true;
68     }
69
70     bool is8Bit() const { return m_is8Bit; }
71     LChar* characters8() const { ASSERT(is8Bit()); return m_data.characters8; }
72     UChar* characters16() const { ASSERT(!is8Bit()); return m_data.characters16; }
73     template<typename CharacterType> CharacterType* characters() const;
74
75     unsigned length() const { return m_length; }
76     void setLength(unsigned length) { m_length = length; }
77
78     void convertToASCIILowercaseInPlace();
79
80     UChar operator[](unsigned i) const
81     {
82         ASSERT_WITH_SECURITY_IMPLICATION(i < m_length);
83         if (is8Bit())
84             return m_data.characters8[i];
85         return m_data.characters16[i];
86     }
87
88     operator String() const { return is8Bit() ? String(m_data.characters8, m_length) : String(m_data.characters16, m_length); }
89     operator AtomicString() const { return is8Bit() ? AtomicString(m_data.characters8, m_length) : AtomicString(m_data.characters16, m_length); }
90     StringView toStringView() const { return is8Bit() ? StringView(m_data.characters8, m_length) : StringView(m_data.characters16, m_length); }
91
92     union {
93         LChar* characters8;
94         UChar* characters16;
95     } m_data;
96     unsigned m_length;
97     bool m_is8Bit;
98 };
99
100 template<unsigned length> bool equalLettersIgnoringASCIICase(const CSSParserString&, const char (&lowercaseLetters)[length]);
101
102 struct CSSParserFunction;
103 struct CSSParserVariable;
104
105 struct CSSParserValue {
106     CSSValueID id;
107     bool isInt;
108     union {
109         double fValue;
110         int iValue;
111         CSSParserString string;
112         CSSParserFunction* function;
113         CSSParserVariable* variable;
114         CSSParserValueList* valueList;
115     };
116     enum {
117         Operator  = 0x100000,
118         Function  = 0x100001,
119         ValueList = 0x100002,
120         Q_EMS     = 0x100003,
121         Variable  = 0x100004
122     };
123     int unit;
124
125     void setFromValueList(std::unique_ptr<CSSParserValueList>);
126
127     RefPtr<CSSValue> createCSSValue();
128 };
129
130 void destroy(const CSSParserValue&);
131
132 class CSSParserValueList {
133     WTF_MAKE_FAST_ALLOCATED;
134 public:
135     CSSParserValueList()
136         : m_current(0)
137     {
138     }
139     ~CSSParserValueList();
140
141     void addValue(const CSSParserValue&);
142     void insertValueAt(unsigned, const CSSParserValue&);
143     void extend(CSSParserValueList&);
144
145     unsigned size() const { return m_values.size(); }
146     unsigned currentIndex() { return m_current; }
147     CSSParserValue* current() { return m_current < m_values.size() ? &m_values[m_current] : 0; }
148     CSSParserValue* next() { ++m_current; return current(); }
149     CSSParserValue* previous()
150     {
151         if (!m_current)
152             return 0;
153         --m_current;
154         return current();
155     }
156     void setCurrentIndex(unsigned index)
157     {
158         ASSERT(index < m_values.size());
159         if (index < m_values.size())
160             m_current = index;
161     }
162
163     CSSParserValue* valueAt(unsigned i) { return i < m_values.size() ? &m_values[i] : 0; }
164
165     void clear() { m_values.clear(); }
166     
167     String toString();
168     
169     bool containsVariables() const;
170
171 private:
172     unsigned m_current;
173     Vector<CSSParserValue, 4> m_values;
174 };
175
176 struct CSSParserFunction {
177     WTF_MAKE_FAST_ALLOCATED;
178 public:
179     CSSParserString name;
180     std::unique_ptr<CSSParserValueList> args;
181 };
182
183 struct CSSParserVariable {
184     WTF_MAKE_FAST_ALLOCATED;
185 public:
186     CSSParserString name; // The custom property name
187     std::unique_ptr<CSSParserValueList> args; // The fallback args
188 };
189
190 enum class CSSParserSelectorCombinator {
191     Child,
192     DescendantSpace,
193 #if ENABLE(CSS_SELECTORS_LEVEL4)
194     DescendantDoubleChild,
195 #endif
196     DirectAdjacent,
197     IndirectAdjacent
198 };
199
200 class CSSParserSelector {
201     WTF_MAKE_FAST_ALLOCATED;
202 public:
203     // FIXME-NEWPARSER: Remove the CSSParserString-based parsing functions once the old parser is gone.
204     static CSSParserSelector* parsePagePseudoSelector(const CSSParserString& pseudoTypeString);
205     static CSSParserSelector* parsePseudoElementSelector(CSSParserString& pseudoTypeString);
206     static CSSParserSelector* parsePseudoElementCueFunctionSelector(const CSSParserString& functionIdentifier, Vector<std::unique_ptr<CSSParserSelector>>*);
207     static CSSParserSelector* parsePseudoElementSlottedFunctionSelector(const CSSParserString& functionIdentifier, CSSParserSelector*);
208     static CSSParserSelector* parsePseudoClassHostFunctionSelector(const CSSParserString& functionIdentifier, CSSParserSelector*);
209     static CSSParserSelector* parsePseudoClassAndCompatibilityElementSelector(CSSParserString& pseudoTypeString);
210
211     static CSSParserSelector* parsePseudoClassSelectorFromStringView(StringView&);
212     static CSSParserSelector* parsePseudoElementSelectorFromStringView(StringView&);
213     static CSSParserSelector* parsePagePseudoSelector(const AtomicString&);
214     
215     CSSParserSelector();
216     explicit CSSParserSelector(const QualifiedName&);
217     ~CSSParserSelector();
218
219     std::unique_ptr<CSSSelector> releaseSelector() { return WTFMove(m_selector); }
220
221     void setValue(const AtomicString& value) { m_selector->setValue(value); }
222     
223     // FIXME-NEWPARSER: These two methods can go away once old parser is gone.
224     void setAttribute(const QualifiedName& value, bool isCaseInsensitive) { m_selector->setAttribute(value, isCaseInsensitive); }
225     void setAttributeValueMatchingIsCaseInsensitive(bool isCaseInsensitive) { m_selector->setAttributeValueMatchingIsCaseInsensitive(isCaseInsensitive); }
226     
227     void setAttribute(const QualifiedName& value, bool convertToLowercase, CSSSelector::AttributeMatchType type) { m_selector->setAttribute(value, convertToLowercase, type); }
228     
229     void setArgument(const AtomicString& value) { m_selector->setArgument(value); }
230     void setNth(int a, int b) { m_selector->setNth(a, b); }
231     void setMatch(CSSSelector::Match value) { m_selector->setMatch(value); }
232     void setRelation(CSSSelector::RelationType value) { m_selector->setRelation(value); }
233     void setForPage() { m_selector->setForPage(); }
234
235     CSSSelector::Match match() const { return m_selector->match(); }
236     CSSSelector::PseudoElementType pseudoElementType() const { return m_selector->pseudoElementType(); }
237     const CSSSelectorList* selectorList() const { return m_selector->selectorList(); }
238     
239     void setPseudoElementType(CSSSelector::PseudoElementType type) { m_selector->setPseudoElementType(type); }
240
241     void adoptSelectorVector(Vector<std::unique_ptr<CSSParserSelector>>& selectorVector);
242     void setLangArgumentList(const Vector<CSSParserString>& stringVector);
243     void setLangArgumentList(std::unique_ptr<Vector<AtomicString>>);
244     void setSelectorList(std::unique_ptr<CSSSelectorList>);
245
246     void setPseudoClassValue(const CSSParserString& pseudoClassString);
247     CSSSelector::PseudoClassType pseudoClassType() const { return m_selector->pseudoClassType(); }
248     bool isCustomPseudoElement() const { return m_selector->isCustomPseudoElement(); }
249
250     bool isPseudoElementCueFunction() const
251     {
252 #if ENABLE(VIDEO_TRACK)
253         return m_selector->match() == CSSSelector::PseudoElement && m_selector->pseudoElementType() == CSSSelector::PseudoElementCue;
254 #else
255         return false;
256 #endif
257     }
258
259     bool hasShadowDescendant() const;
260     bool matchesPseudoElement() const;
261
262     bool isHostPseudoSelector() const;
263
264     // FIXME-NEWPARSER: "slotted" was removed here for now, since it leads to a combinator
265     // connection of ShadowDescendant, and the current shadow DOM code doesn't expect this. When
266     // we do fix this issue, make sure to patch the namespace prependTag code to remove the slotted
267     // special case, since it will be covered by this function once again.
268     bool needsImplicitShadowCombinatorForMatching() const;
269
270     CSSParserSelector* tagHistory() const { return m_tagHistory.get(); }
271     void setTagHistory(std::unique_ptr<CSSParserSelector> selector) { m_tagHistory = WTFMove(selector); }
272     void clearTagHistory() { m_tagHistory.reset(); }
273     void insertTagHistory(CSSSelector::RelationType before, std::unique_ptr<CSSParserSelector>, CSSSelector::RelationType after);
274     void appendTagHistory(CSSSelector::RelationType, std::unique_ptr<CSSParserSelector>);
275     void appendTagHistory(CSSParserSelectorCombinator, std::unique_ptr<CSSParserSelector>);
276     void prependTagSelector(const QualifiedName&, bool tagIsForNamespaceRule = false);
277     std::unique_ptr<CSSParserSelector> releaseTagHistory();
278
279 private:
280     std::unique_ptr<CSSSelector> m_selector;
281     std::unique_ptr<CSSParserSelector> m_tagHistory;
282 };
283
284 inline bool CSSParserSelector::hasShadowDescendant() const
285 {
286     return m_selector->relation() == CSSSelector::ShadowDescendant;
287 }
288
289 inline bool CSSParserSelector::needsImplicitShadowCombinatorForMatching() const
290 {
291     return match() == CSSSelector::PseudoElement
292         && (pseudoElementType() == CSSSelector::PseudoElementWebKitCustom
293             || pseudoElementType() == CSSSelector::PseudoElementUserAgentCustom
294 #if ENABLE(VIDEO_TRACK)
295             || pseudoElementType() == CSSSelector::PseudoElementCue
296 #endif
297             || pseudoElementType() == CSSSelector::PseudoElementWebKitCustomLegacyPrefixed);
298 }
299
300 inline void CSSParserValue::setFromValueList(std::unique_ptr<CSSParserValueList> valueList)
301 {
302     id = CSSValueInvalid;
303     this->valueList = valueList.release();
304     unit = ValueList;
305 }
306
307 template<unsigned length> inline bool equalLettersIgnoringASCIICase(const CSSParserString& string, const char (&lowercaseLetters)[length])
308 {
309     return WTF::equalLettersIgnoringASCIICaseCommon(string, lowercaseLetters);
310 }
311
312 }