1/*
2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2008 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#include "config.h"
22#include "CSSParserValues.h"
23
24#include "CSSPrimitiveValue.h"
25#include "CSSFunctionValue.h"
26#include "CSSSelector.h"
27#include "CSSSelectorList.h"
28#if ENABLE(CSS_VARIABLES)
29#include "CSSVariableValue.h"
30#endif
31
32namespace WebCore {
33
34using namespace WTF;
35
36CSSParserValueList::~CSSParserValueList()
37{
38    size_t numValues = m_values.size();
39    for (size_t i = 0; i < numValues; i++) {
40        if (m_values[i].unit == CSSParserValue::Function)
41            delete m_values[i].function;
42    }
43}
44
45void CSSParserValueList::addValue(const CSSParserValue& v)
46{
47    m_values.append(v);
48}
49
50void CSSParserValueList::insertValueAt(unsigned i, const CSSParserValue& v)
51{
52    m_values.insert(i, v);
53}
54
55void CSSParserValueList::deleteValueAt(unsigned i)
56{
57    m_values.remove(i);
58}
59
60void CSSParserValueList::extend(CSSParserValueList& valueList)
61{
62    for (unsigned int i = 0; i < valueList.size(); ++i)
63        m_values.append(*(valueList.valueAt(i)));
64}
65
66PassRefPtr<CSSValue> CSSParserValue::createCSSValue()
67{
68    RefPtr<CSSValue> parsedValue;
69    if (id)
70        return CSSPrimitiveValue::createIdentifier(id);
71
72    if (unit == CSSParserValue::Operator) {
73        RefPtr<CSSPrimitiveValue> primitiveValue = CSSPrimitiveValue::createIdentifier(iValue);
74        primitiveValue->setPrimitiveType(CSSPrimitiveValue::CSS_PARSER_OPERATOR);
75        return primitiveValue;
76    }
77    if (unit == CSSParserValue::Function)
78        return CSSFunctionValue::create(function);
79    if (unit >= CSSParserValue::Q_EMS)
80        return CSSPrimitiveValue::createAllowingMarginQuirk(fValue, CSSPrimitiveValue::CSS_EMS);
81
82    CSSPrimitiveValue::UnitTypes primitiveUnit = static_cast<CSSPrimitiveValue::UnitTypes>(unit);
83    switch (primitiveUnit) {
84    case CSSPrimitiveValue::CSS_IDENT:
85        return CSSPrimitiveValue::create(string, CSSPrimitiveValue::CSS_PARSER_IDENTIFIER);
86    case CSSPrimitiveValue::CSS_NUMBER:
87        return CSSPrimitiveValue::create(fValue, isInt ? CSSPrimitiveValue::CSS_PARSER_INTEGER : CSSPrimitiveValue::CSS_NUMBER);
88    case CSSPrimitiveValue::CSS_STRING:
89    case CSSPrimitiveValue::CSS_URI:
90#if ENABLE(CSS_VARIABLES)
91    case CSSPrimitiveValue::CSS_VARIABLE_NAME:
92#endif
93    case CSSPrimitiveValue::CSS_PARSER_HEXCOLOR:
94        return CSSPrimitiveValue::create(string, primitiveUnit);
95    case CSSPrimitiveValue::CSS_PERCENTAGE:
96    case CSSPrimitiveValue::CSS_EMS:
97    case CSSPrimitiveValue::CSS_EXS:
98    case CSSPrimitiveValue::CSS_PX:
99    case CSSPrimitiveValue::CSS_CM:
100    case CSSPrimitiveValue::CSS_MM:
101    case CSSPrimitiveValue::CSS_IN:
102    case CSSPrimitiveValue::CSS_PT:
103    case CSSPrimitiveValue::CSS_PC:
104    case CSSPrimitiveValue::CSS_DEG:
105    case CSSPrimitiveValue::CSS_RAD:
106    case CSSPrimitiveValue::CSS_GRAD:
107    case CSSPrimitiveValue::CSS_MS:
108    case CSSPrimitiveValue::CSS_S:
109    case CSSPrimitiveValue::CSS_HZ:
110    case CSSPrimitiveValue::CSS_KHZ:
111    case CSSPrimitiveValue::CSS_VW:
112    case CSSPrimitiveValue::CSS_VH:
113    case CSSPrimitiveValue::CSS_VMIN:
114    case CSSPrimitiveValue::CSS_VMAX:
115    case CSSPrimitiveValue::CSS_TURN:
116    case CSSPrimitiveValue::CSS_REMS:
117    case CSSPrimitiveValue::CSS_CHS:
118        return CSSPrimitiveValue::create(fValue, primitiveUnit);
119    case CSSPrimitiveValue::CSS_UNKNOWN:
120    case CSSPrimitiveValue::CSS_DIMENSION:
121    case CSSPrimitiveValue::CSS_ATTR:
122    case CSSPrimitiveValue::CSS_COUNTER:
123    case CSSPrimitiveValue::CSS_RECT:
124    case CSSPrimitiveValue::CSS_RGBCOLOR:
125    case CSSPrimitiveValue::CSS_DPPX:
126    case CSSPrimitiveValue::CSS_DPI:
127    case CSSPrimitiveValue::CSS_DPCM:
128    case CSSPrimitiveValue::CSS_PAIR:
129#if ENABLE(DASHBOARD_SUPPORT)
130    case CSSPrimitiveValue::CSS_DASHBOARD_REGION:
131#endif
132    case CSSPrimitiveValue::CSS_UNICODE_RANGE:
133    case CSSPrimitiveValue::CSS_PARSER_OPERATOR:
134    case CSSPrimitiveValue::CSS_PARSER_INTEGER:
135    case CSSPrimitiveValue::CSS_PARSER_IDENTIFIER:
136    case CSSPrimitiveValue::CSS_COUNTER_NAME:
137    case CSSPrimitiveValue::CSS_SHAPE:
138    case CSSPrimitiveValue::CSS_QUAD:
139    case CSSPrimitiveValue::CSS_CALC:
140    case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER:
141    case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH:
142        return 0;
143    }
144
145    ASSERT_NOT_REACHED();
146    return 0;
147}
148
149CSSParserSelector::CSSParserSelector()
150    : m_selector(adoptPtr(fastNew<CSSSelector>()))
151{
152}
153
154CSSParserSelector::CSSParserSelector(const QualifiedName& tagQName)
155    : m_selector(adoptPtr(new CSSSelector(tagQName)))
156{
157}
158
159CSSParserSelector::~CSSParserSelector()
160{
161    if (!m_tagHistory)
162        return;
163    Vector<OwnPtr<CSSParserSelector>, 16> toDelete;
164    OwnPtr<CSSParserSelector> selector = m_tagHistory.release();
165    while (true) {
166        OwnPtr<CSSParserSelector> next = selector->m_tagHistory.release();
167        toDelete.append(selector.release());
168        if (!next)
169            break;
170        selector = next.release();
171    }
172}
173
174void CSSParserSelector::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector)
175{
176    CSSSelectorList* selectorList = fastNew<CSSSelectorList>();
177    selectorList->adoptSelectorVector(selectorVector);
178    m_selector->setSelectorList(adoptPtr(selectorList));
179}
180
181bool CSSParserSelector::isSimple() const
182{
183    if (m_selector->selectorList() || m_selector->matchesPseudoElement())
184        return false;
185
186    if (!m_tagHistory)
187        return true;
188
189    if (m_selector->m_match == CSSSelector::Tag) {
190        // We can't check against anyQName() here because namespace may not be nullAtom.
191        // Example:
192        //     @namespace "http://www.w3.org/2000/svg";
193        //     svg:not(:root) { ...
194        if (m_selector->tagQName().localName() == starAtom)
195            return m_tagHistory->isSimple();
196    }
197
198    return false;
199}
200
201void CSSParserSelector::insertTagHistory(CSSSelector::Relation before, PassOwnPtr<CSSParserSelector> selector, CSSSelector::Relation after)
202{
203    if (m_tagHistory)
204        selector->setTagHistory(m_tagHistory.release());
205    setRelation(before);
206    selector->setRelation(after);
207    m_tagHistory = selector;
208}
209
210void CSSParserSelector::appendTagHistory(CSSSelector::Relation relation, PassOwnPtr<CSSParserSelector> selector)
211{
212    CSSParserSelector* end = this;
213    while (end->tagHistory())
214        end = end->tagHistory();
215    end->setRelation(relation);
216    end->setTagHistory(selector);
217}
218
219void CSSParserSelector::prependTagSelector(const QualifiedName& tagQName, bool tagIsForNamespaceRule)
220{
221    OwnPtr<CSSParserSelector> second = adoptPtr(new CSSParserSelector);
222    second->m_selector = m_selector.release();
223    second->m_tagHistory = m_tagHistory.release();
224    m_tagHistory = second.release();
225
226    m_selector = adoptPtr(new CSSSelector(tagQName, tagIsForNamespaceRule));
227    m_selector->m_relation = CSSSelector::SubSelector;
228}
229
230}
231
232