2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2009 Google Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "CSSSelectorList.h"
30 #include "CSSParserValues.h"
31 #include <wtf/text/StringBuilder.h>
35 CSSSelectorList::~CSSSelectorList()
40 void CSSSelectorList::adopt(CSSSelectorList& list)
43 m_selectorArray = list.m_selectorArray;
44 list.m_selectorArray = 0;
47 void CSSSelectorList::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector)
50 const size_t vectorSize = selectorVector.size();
51 size_t flattenedSize = 0;
52 for (size_t i = 0; i < vectorSize; ++i) {
53 for (CSSParserSelector* selector = selectorVector[i].get(); selector; selector = selector->tagHistory())
56 ASSERT(flattenedSize);
57 if (flattenedSize == 1) {
58 m_selectorArray = selectorVector[0]->releaseSelector().leakPtr();
59 m_selectorArray->setLastInSelectorList();
60 ASSERT(m_selectorArray->isLastInTagHistory());
61 selectorVector.shrink(0);
64 m_selectorArray = reinterpret_cast<CSSSelector*>(fastMalloc(sizeof(CSSSelector) * flattenedSize));
65 size_t arrayIndex = 0;
66 for (size_t i = 0; i < vectorSize; ++i) {
67 CSSParserSelector* current = selectorVector[i].get();
69 OwnPtr<CSSSelector> selector = current->releaseSelector();
70 current = current->tagHistory();
71 move(selector.release(), &m_selectorArray[arrayIndex]);
72 ASSERT(!m_selectorArray[arrayIndex].isLastInSelectorList());
74 m_selectorArray[arrayIndex].setNotLastInTagHistory();
77 ASSERT(m_selectorArray[arrayIndex - 1].isLastInTagHistory());
79 ASSERT(flattenedSize == arrayIndex);
80 m_selectorArray[arrayIndex - 1].setLastInSelectorList();
81 selectorVector.shrink(0);
84 void CSSSelectorList::deleteSelectors()
89 // We had two cases in adoptSelectVector. The fast case of a 1 element
90 // vector took the CSSSelector directly, which was allocated with new.
91 // The second case we allocated a new fastMalloc buffer, which should be
92 // freed with fastFree, and the destructors called manually.
93 CSSSelector* s = m_selectorArray;
94 bool done = s->isLastInSelectorList();
103 done = s->isLastInSelectorList();
105 fastFree(m_selectorArray);
109 String CSSSelectorList::selectorsText() const
111 StringBuilder result;
113 for (CSSSelector* s = first(); s; s = next(s)) {
116 result.append(s->selectorText());
119 return result.toString();
122 template <typename Functor>
123 static bool forEachTagSelector(Functor& functor, CSSSelector* selector)
128 if (functor(selector))
130 if (CSSSelectorList* selectorList = selector->selectorList()) {
131 for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
132 if (forEachTagSelector(functor, subSelector))
136 } while ((selector = selector->tagHistory()));
141 template <typename Functor>
142 static bool forEachSelector(Functor& functor, const CSSSelectorList* selectorList)
144 for (CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(selector)) {
145 if (forEachTagSelector(functor, selector))
152 class SelectorNeedsNamespaceResolutionFunctor {
154 bool operator()(CSSSelector* selector)
156 if (selector->hasTag() && selector->tag().prefix() != nullAtom && selector->tag().prefix() != starAtom)
158 if (selector->isAttributeSelector() && selector->attribute().prefix() != nullAtom && selector->attribute().prefix() != starAtom)
164 bool CSSSelectorList::selectorsNeedNamespaceResolution()
166 SelectorNeedsNamespaceResolutionFunctor functor;
167 return forEachSelector(functor, this);
170 class SelectorHasUnknownPseudoElementFunctor {
172 bool operator()(CSSSelector* selector)
174 return selector->isUnknownPseudoElement();
178 bool CSSSelectorList::hasUnknownPseudoElements() const
180 SelectorHasUnknownPseudoElementFunctor functor;
181 return forEachSelector(functor, this);
186 } // namespace WebCore