Home | History | Annotate | Download | only in parser
      1 /*
      2  * Copyright (C) 2003 Lars Knoll (knoll (at) 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/parser/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 blink {
     29 
     30 using namespace WTF;
     31 
     32 static void destroy(Vector<CSSParserValue, 4>& values)
     33 {
     34     size_t numValues = values.size();
     35     for (size_t i = 0; i < numValues; i++) {
     36         if (values[i].unit == CSSParserValue::Function)
     37             delete values[i].function;
     38         else if (values[i].unit == CSSParserValue::ValueList)
     39             delete values[i].valueList;
     40     }
     41 }
     42 
     43 void CSSParserValueList::destroyAndClear()
     44 {
     45     destroy(m_values);
     46     clearAndLeakValues();
     47 }
     48 
     49 CSSParserValueList::~CSSParserValueList()
     50 {
     51     destroy(m_values);
     52 }
     53 
     54 void CSSParserValueList::addValue(const CSSParserValue& v)
     55 {
     56     m_values.append(v);
     57 }
     58 
     59 void CSSParserValueList::insertValueAt(unsigned i, const CSSParserValue& v)
     60 {
     61     m_values.insert(i, v);
     62 }
     63 
     64 void CSSParserValueList::stealValues(CSSParserValueList& valueList)
     65 {
     66     for (unsigned i = 0; i < valueList.size(); ++i)
     67         m_values.append(*(valueList.valueAt(i)));
     68     valueList.clearAndLeakValues();
     69 }
     70 
     71 CSSParserSelector::CSSParserSelector()
     72     : m_selector(adoptPtr(new CSSSelector()))
     73 {
     74 }
     75 
     76 CSSParserSelector::CSSParserSelector(const QualifiedName& tagQName)
     77     : m_selector(adoptPtr(new CSSSelector(tagQName)))
     78 {
     79 }
     80 
     81 CSSParserSelector::~CSSParserSelector()
     82 {
     83     if (!m_tagHistory)
     84         return;
     85     Vector<OwnPtr<CSSParserSelector>, 16> toDelete;
     86     OwnPtr<CSSParserSelector> selector = m_tagHistory.release();
     87     while (true) {
     88         OwnPtr<CSSParserSelector> next = selector->m_tagHistory.release();
     89         toDelete.append(selector.release());
     90         if (!next)
     91             break;
     92         selector = next.release();
     93     }
     94 }
     95 
     96 void CSSParserSelector::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector)
     97 {
     98     CSSSelectorList* selectorList = new CSSSelectorList();
     99     selectorList->adoptSelectorVector(selectorVector);
    100     m_selector->setSelectorList(adoptPtr(selectorList));
    101 }
    102 
    103 bool CSSParserSelector::isSimple() const
    104 {
    105     if (m_selector->selectorList() || m_selector->matchesPseudoElement())
    106         return false;
    107 
    108     if (!m_tagHistory)
    109         return true;
    110 
    111     if (m_selector->match() == CSSSelector::Tag) {
    112         // We can't check against anyQName() here because namespace may not be nullAtom.
    113         // Example:
    114         //     @namespace "http://www.w3.org/2000/svg";
    115         //     svg:not(:root) { ...
    116         if (m_selector->tagQName().localName() == starAtom)
    117             return m_tagHistory->isSimple();
    118     }
    119 
    120     return false;
    121 }
    122 
    123 void CSSParserSelector::insertTagHistory(CSSSelector::Relation before, PassOwnPtr<CSSParserSelector> selector, CSSSelector::Relation after)
    124 {
    125     if (m_tagHistory)
    126         selector->setTagHistory(m_tagHistory.release());
    127     setRelation(before);
    128     selector->setRelation(after);
    129     m_tagHistory = selector;
    130 }
    131 
    132 void CSSParserSelector::appendTagHistory(CSSSelector::Relation relation, PassOwnPtr<CSSParserSelector> selector)
    133 {
    134     CSSParserSelector* end = this;
    135     while (end->tagHistory())
    136         end = end->tagHistory();
    137     end->setRelation(relation);
    138     end->setTagHistory(selector);
    139 }
    140 
    141 void CSSParserSelector::prependTagSelector(const QualifiedName& tagQName, bool tagIsForNamespaceRule)
    142 {
    143     OwnPtr<CSSParserSelector> second = adoptPtr(new CSSParserSelector);
    144     second->m_selector = m_selector.release();
    145     second->m_tagHistory = m_tagHistory.release();
    146     m_tagHistory = second.release();
    147 
    148     m_selector = adoptPtr(new CSSSelector(tagQName, tagIsForNamespaceRule));
    149     m_selector->setRelation(CSSSelector::SubSelector);
    150 }
    151 
    152 bool CSSParserSelector::hasHostPseudoSelector() const
    153 {
    154     for (CSSParserSelector* selector = const_cast<CSSParserSelector*>(this); selector; selector = selector->tagHistory()) {
    155         if (selector->pseudoType() == CSSSelector::PseudoHost || selector->pseudoType() == CSSSelector::PseudoHostContext)
    156             return true;
    157     }
    158     return false;
    159 }
    160 
    161 } // namespace blink
    162