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 "CSSValueList.h"
26#include <wtf/text/AtomicString.h>
27#include <wtf/text/WTFString.h>
28
29namespace WebCore {
30
31class CSSValue;
32class QualifiedName;
33
34struct CSSParserString {
35    void init(LChar* characters, unsigned length)
36    {
37        m_data.characters8 = characters;
38        m_length = length;
39        m_is8Bit = true;
40    }
41
42    void init(UChar* characters, unsigned length)
43    {
44        m_data.characters16 = characters;
45        m_length = length;
46        m_is8Bit = false;
47    }
48
49    void init(const String& string)
50    {
51        m_length = string.length();
52        if (m_length && string.is8Bit()) {
53            m_data.characters8 = const_cast<LChar*>(string.characters8());
54            m_is8Bit = true;
55        } else {
56            m_data.characters16 = const_cast<UChar*>(string.characters());
57            m_is8Bit = false;
58        }
59    }
60
61    void clear()
62    {
63        m_data.characters8 = 0;
64        m_length = 0;
65        m_is8Bit = false;
66    }
67
68    bool is8Bit() const { return m_is8Bit; }
69    LChar* characters8() const { ASSERT(is8Bit()); return m_data.characters8; }
70    UChar* characters16() const { ASSERT(!is8Bit()); return m_data.characters16; }
71    template <typename CharacterType>
72    CharacterType* characters() const;
73
74    unsigned length() const { return m_length; }
75    void setLength(unsigned length) { m_length = length; }
76
77    void lower();
78
79    UChar operator[](unsigned i)
80    {
81        ASSERT_WITH_SECURITY_IMPLICATION(i < m_length);
82        if (is8Bit())
83            return m_data.characters8[i];
84        return m_data.characters16[i];
85    }
86
87    bool equalIgnoringCase(const char* str)
88    {
89        if (is8Bit())
90            return WTF::equalIgnoringCase(str, characters8(), length());
91        return WTF::equalIgnoringCase(str, characters16(), length());
92    }
93
94    operator String() const { return is8Bit() ? String(m_data.characters8, m_length) : String(m_data.characters16, m_length); }
95    operator AtomicString() const { return is8Bit() ? AtomicString(m_data.characters8, m_length) : AtomicString(m_data.characters16, m_length); }
96
97#if ENABLE(CSS_VARIABLES)
98    AtomicString substring(unsigned position, unsigned length) const;
99#endif
100
101    union {
102        LChar* characters8;
103        UChar* characters16;
104    } m_data;
105    unsigned m_length;
106    bool m_is8Bit;
107};
108
109struct CSSParserFunction;
110
111struct CSSParserValue {
112    int id;
113    bool isInt;
114    union {
115        double fValue;
116        int iValue;
117        CSSParserString string;
118        CSSParserFunction* function;
119    };
120    enum {
121        Operator = 0x100000,
122        Function = 0x100001,
123        Q_EMS    = 0x100002
124    };
125    int unit;
126
127
128    PassRefPtr<CSSValue> createCSSValue();
129};
130
131class CSSParserValueList {
132    WTF_MAKE_FAST_ALLOCATED;
133public:
134    CSSParserValueList()
135        : m_current(0)
136    {
137    }
138    ~CSSParserValueList();
139
140    void addValue(const CSSParserValue&);
141    void insertValueAt(unsigned, const CSSParserValue&);
142    void deleteValueAt(unsigned);
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
157    CSSParserValue* valueAt(unsigned i) { return i < m_values.size() ? &m_values[i] : 0; }
158
159    void clear() { m_values.clear(); }
160
161private:
162    unsigned m_current;
163    Vector<CSSParserValue, 4> m_values;
164};
165
166struct CSSParserFunction {
167    WTF_MAKE_FAST_ALLOCATED;
168public:
169    CSSParserString name;
170    OwnPtr<CSSParserValueList> args;
171};
172
173class CSSParserSelector {
174    WTF_MAKE_FAST_ALLOCATED;
175public:
176    CSSParserSelector();
177    explicit CSSParserSelector(const QualifiedName&);
178    ~CSSParserSelector();
179
180    PassOwnPtr<CSSSelector> releaseSelector() { return m_selector.release(); }
181
182    void setValue(const AtomicString& value) { m_selector->setValue(value); }
183    void setAttribute(const QualifiedName& value) { m_selector->setAttribute(value); }
184    void setArgument(const AtomicString& value) { m_selector->setArgument(value); }
185    void setMatch(CSSSelector::Match value) { m_selector->m_match = value; }
186    void setRelation(CSSSelector::Relation value) { m_selector->m_relation = value; }
187    void setForPage() { m_selector->setForPage(); }
188
189    void adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector);
190
191    CSSSelector::PseudoType pseudoType() const { return m_selector->pseudoType(); }
192    bool isCustomPseudoElement() const { return m_selector->isCustomPseudoElement(); }
193
194    bool isSimple() const;
195    bool hasShadowDescendant() const;
196
197    CSSParserSelector* tagHistory() const { return m_tagHistory.get(); }
198    void setTagHistory(PassOwnPtr<CSSParserSelector> selector) { m_tagHistory = selector; }
199    void clearTagHistory() { m_tagHistory.clear(); }
200    void insertTagHistory(CSSSelector::Relation before, PassOwnPtr<CSSParserSelector>, CSSSelector::Relation after);
201    void appendTagHistory(CSSSelector::Relation, PassOwnPtr<CSSParserSelector>);
202    void prependTagSelector(const QualifiedName&, bool tagIsForNamespaceRule = false);
203
204private:
205    OwnPtr<CSSSelector> m_selector;
206    OwnPtr<CSSParserSelector> m_tagHistory;
207};
208
209inline bool CSSParserSelector::hasShadowDescendant() const
210{
211    return m_selector->relation() == CSSSelector::ShadowDescendant;
212}
213
214}
215
216#endif
217