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