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