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 CSSSelectorList::CSSSelectorList(const CSSSelectorList& o)
42 CSSSelector* current = o.m_selectorArray;
43 while (!current->isLastInSelectorList())
45 unsigned length = (current - o.m_selectorArray) + 1;
47 // Destructor expects a single selector to be allocated by new, multiple with fastMalloc.
48 m_selectorArray = new CSSSelector(o.m_selectorArray[0]);
51 m_selectorArray = reinterpret_cast<CSSSelector*>(fastMalloc(sizeof(CSSSelector) * length));
52 for (unsigned i = 0; i < length; ++i)
53 new (&m_selectorArray[i]) CSSSelector(o.m_selectorArray[i]);
56 void CSSSelectorList::adopt(CSSSelectorList& list)
59 m_selectorArray = list.m_selectorArray;
60 list.m_selectorArray = 0;
63 void CSSSelectorList::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector)
66 const size_t vectorSize = selectorVector.size();
67 size_t flattenedSize = 0;
68 for (size_t i = 0; i < vectorSize; ++i) {
69 for (CSSParserSelector* selector = selectorVector[i].get(); selector; selector = selector->tagHistory())
72 ASSERT(flattenedSize);
73 if (flattenedSize == 1) {
74 m_selectorArray = selectorVector[0]->releaseSelector().leakPtr();
75 m_selectorArray->setLastInSelectorList();
76 ASSERT(m_selectorArray->isLastInTagHistory());
77 selectorVector.shrink(0);
80 m_selectorArray = reinterpret_cast<CSSSelector*>(fastMalloc(sizeof(CSSSelector) * flattenedSize));
81 size_t arrayIndex = 0;
82 for (size_t i = 0; i < vectorSize; ++i) {
83 CSSParserSelector* current = selectorVector[i].get();
85 OwnPtr<CSSSelector> selector = current->releaseSelector();
86 current = current->tagHistory();
87 move(selector.release(), &m_selectorArray[arrayIndex]);
88 ASSERT(!m_selectorArray[arrayIndex].isLastInSelectorList());
90 m_selectorArray[arrayIndex].setNotLastInTagHistory();
93 ASSERT(m_selectorArray[arrayIndex - 1].isLastInTagHistory());
95 ASSERT(flattenedSize == arrayIndex);
96 m_selectorArray[arrayIndex - 1].setLastInSelectorList();
97 selectorVector.shrink(0);
100 void CSSSelectorList::deleteSelectors()
102 if (!m_selectorArray)
105 // We had two cases in adoptSelectVector. The fast case of a 1 element
106 // vector took the CSSSelector directly, which was allocated with new.
107 // The second case we allocated a new fastMalloc buffer, which should be
108 // freed with fastFree, and the destructors called manually.
109 CSSSelector* s = m_selectorArray;
110 bool done = s->isLastInSelectorList();
119 done = s->isLastInSelectorList();
121 fastFree(m_selectorArray);
125 String CSSSelectorList::selectorsText() const
127 StringBuilder result;
129 for (CSSSelector* s = first(); s; s = next(s)) {
132 result.append(s->selectorText());
135 return result.toString();
138 template <typename Functor>
139 static bool forEachTagSelector(Functor& functor, CSSSelector* selector)
144 if (functor(selector))
146 if (CSSSelectorList* selectorList = selector->selectorList()) {
147 for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
148 if (forEachTagSelector(functor, subSelector))
152 } while ((selector = selector->tagHistory()));
157 template <typename Functor>
158 static bool forEachSelector(Functor& functor, const CSSSelectorList* selectorList)
160 for (CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(selector)) {
161 if (forEachTagSelector(functor, selector))
168 class SelectorNeedsNamespaceResolutionFunctor {
170 bool operator()(CSSSelector* selector)
172 if (selector->hasTag() && selector->tag().prefix() != nullAtom && selector->tag().prefix() != starAtom)
174 if (selector->isAttributeSelector() && selector->attribute().prefix() != nullAtom && selector->attribute().prefix() != starAtom)
180 bool CSSSelectorList::selectorsNeedNamespaceResolution()
182 SelectorNeedsNamespaceResolutionFunctor functor;
183 return forEachSelector(functor, this);
186 class SelectorHasUnknownPseudoElementFunctor {
188 bool operator()(CSSSelector* selector)
190 return selector->isUnknownPseudoElement();
194 bool CSSSelectorList::hasUnknownPseudoElements() const
196 SelectorHasUnknownPseudoElementFunctor functor;
197 return forEachSelector(functor, this);
202 } // namespace WebCore