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