1/*
2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 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#ifndef CSSParserValues_h
22#define CSSParserValues_h
23
24#include "CSSSelector.h"
25#include "CSSValueKeywords.h"
26#include "CSSValueList.h"
27#include <wtf/text/AtomicString.h>
28#include <wtf/text/WTFString.h>
29
30namespace WebCore {
31
32class CSSValue;
33class QualifiedName;
34
35struct CSSParserString {
36    void init(LChar* characters, unsigned length)
37    {
38        m_data.characters8 = characters;
39        m_length = length;
40        m_is8Bit = true;
41    }
42
43    void init(UChar* characters, unsigned length)
44    {
45        m_data.characters16 = characters;
46        m_length = length;
47        m_is8Bit = false;
48    }
49
50    void init(const String& string)
51    {
52        m_length = string.length();
53        if (!m_length || string.is8Bit()) {
54            m_data.characters8 = const_cast<LChar*>(string.characters8());
55            m_is8Bit = true;
56        } else {
57            m_data.characters16 = const_cast<UChar*>(string.characters16());
58            m_is8Bit = false;
59        }
60    }
61
62    void clear()
63    {
64        m_data.characters8 = 0;
65        m_length = 0;
66        m_is8Bit = true;
67    }
68
69    bool is8Bit() const { return m_is8Bit; }
70    LChar* characters8() const { ASSERT(is8Bit()); return m_data.characters8; }
71    UChar* characters16() const { ASSERT(!is8Bit()); return m_data.characters16; }
72    template <typename CharacterType>
73    CharacterType* characters() const;
74
75    unsigned length() const { return m_length; }
76    void setLength(unsigned length) { m_length = length; }
77
78    void lower();
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    bool equalIgnoringCase(const char* str) const
89    {
90        if (is8Bit())
91            return WTF::equalIgnoringCase(str, characters8(), length());
92        return WTF::equalIgnoringCase(str, characters16(), length());
93    }
94
95    operator String() const { return is8Bit() ? String(m_data.characters8, m_length) : String(m_data.characters16, m_length); }
96    operator AtomicString() const { return is8Bit() ? AtomicString(m_data.characters8, m_length) : AtomicString(m_data.characters16, m_length); }
97
98    union {
99        LChar* characters8;
100        UChar* characters16;
101    } m_data;
102    unsigned m_length;
103    bool m_is8Bit;
104};
105
106struct CSSParserFunction;
107
108struct CSSParserValue {
109    CSSValueID id;
110    bool isInt;
111    union {
112        double fValue;
113        int iValue;
114        CSSParserString string;
115        CSSParserFunction* function;
116        CSSParserValueList* valueList;
117    };
118    enum {
119        Operator  = 0x100000,
120        Function  = 0x100001,
121        ValueList = 0x100002,
122        Q_EMS     = 0x100003,
123    };
124    int unit;
125
126    void setFromValueList(std::unique_ptr<CSSParserValueList>);
127
128    PassRefPtr<CSSValue> createCSSValue();
129};
130
131void destroy(const CSSParserValue&);
132
133class CSSParserValueList {
134    WTF_MAKE_FAST_ALLOCATED;
135public:
136    CSSParserValueList()
137        : m_current(0)
138    {
139    }
140    ~CSSParserValueList();
141
142    void addValue(const CSSParserValue&);
143    void insertValueAt(unsigned, const CSSParserValue&);
144    void deleteValueAt(unsigned);
145    void extend(CSSParserValueList&);
146
147    unsigned size() const { return m_values.size(); }
148    unsigned currentIndex() { return m_current; }
149    CSSParserValue* current() { return m_current < m_values.size() ? &m_values[m_current] : 0; }
150    CSSParserValue* next() { ++m_current; return current(); }
151    CSSParserValue* previous()
152    {
153        if (!m_current)
154            return 0;
155        --m_current;
156        return current();
157    }
158    void setCurrentIndex(unsigned index)
159    {
160        ASSERT(index < m_values.size());
161        if (index < m_values.size())
162            m_current = index;
163    }
164
165    CSSParserValue* valueAt(unsigned i) { return i < m_values.size() ? &m_values[i] : 0; }
166
167    void clear() { m_values.clear(); }
168
169private:
170    unsigned m_current;
171    Vector<CSSParserValue, 4> m_values;
172};
173
174struct CSSParserFunction {
175    WTF_MAKE_FAST_ALLOCATED;
176public:
177    CSSParserString name;
178    std::unique_ptr<CSSParserValueList> args;
179};
180
181class CSSParserSelector {
182    WTF_MAKE_FAST_ALLOCATED;
183public:
184    static CSSParserSelector* parsePagePseudoSelector(const CSSParserString& pseudoTypeString);
185    static CSSParserSelector* parsePseudoElementSelector(CSSParserString& pseudoTypeString);
186    static CSSParserSelector* parsePseudoElementCueFunctionSelector(const CSSParserString& functionIdentifier, Vector<std::unique_ptr<CSSParserSelector>>* selectorVector);
187    static CSSParserSelector* parsePseudoClassAndCompatibilityElementSelector(CSSParserString& pseudoTypeString);
188
189    CSSParserSelector();
190    explicit CSSParserSelector(const QualifiedName&);
191    ~CSSParserSelector();
192
193    std::unique_ptr<CSSSelector> releaseSelector() { return WTF::move(m_selector); }
194
195    void setValue(const AtomicString& value) { m_selector->setValue(value); }
196    void setAttribute(const QualifiedName& value, bool isCaseInsensitive) { m_selector->setAttribute(value, isCaseInsensitive); }
197    void setArgument(const AtomicString& value) { m_selector->setArgument(value); }
198    void setMatch(CSSSelector::Match value) { m_selector->m_match = value; }
199    void setRelation(CSSSelector::Relation value) { m_selector->m_relation = value; }
200    void setForPage() { m_selector->setForPage(); }
201
202
203    void adoptSelectorVector(Vector<std::unique_ptr<CSSParserSelector>>& selectorVector);
204
205    void setPseudoClassValue(const CSSParserString& pseudoClassString);
206    CSSSelector::PseudoClassType pseudoClassType() const { return m_selector->pseudoClassType(); }
207    bool isCustomPseudoElement() const { return m_selector->isCustomPseudoElement(); }
208
209    bool isPseudoElementCueFunction() const
210    {
211#if ENABLE(VIDEO_TRACK)
212        return m_selector->m_match == CSSSelector::PseudoElement && m_selector->pseudoElementType() == CSSSelector::PseudoElementCue;
213#else
214        return false;
215#endif
216    }
217
218    bool isSimple() const;
219    bool hasShadowDescendant() const;
220
221    CSSParserSelector* tagHistory() const { return m_tagHistory.get(); }
222    void setTagHistory(std::unique_ptr<CSSParserSelector> selector) { m_tagHistory = WTF::move(selector); }
223    void clearTagHistory() { m_tagHistory.reset(); }
224    void insertTagHistory(CSSSelector::Relation before, std::unique_ptr<CSSParserSelector>, CSSSelector::Relation after);
225    void appendTagHistory(CSSSelector::Relation, std::unique_ptr<CSSParserSelector>);
226    void prependTagSelector(const QualifiedName&, bool tagIsForNamespaceRule = false);
227
228private:
229    std::unique_ptr<CSSSelector> m_selector;
230    std::unique_ptr<CSSParserSelector> m_tagHistory;
231};
232
233inline bool CSSParserSelector::hasShadowDescendant() const
234{
235    return m_selector->relation() == CSSSelector::ShadowDescendant;
236}
237
238inline void CSSParserValue::setFromValueList(std::unique_ptr<CSSParserValueList> valueList)
239{
240    id = CSSValueInvalid;
241    this->valueList = valueList.release();
242    unit = ValueList;
243}
244}
245
246#endif
247