tizen beta release
[framework/web/webkit-efl.git] / Source / WebCore / css / CSSSelectorList.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  * Copyright (C) 2009 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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.
25  */
26
27 #include "config.h"
28 #include "CSSSelectorList.h"
29
30 #include "CSSParserValues.h"
31 #include <wtf/text/StringBuilder.h>
32
33 namespace WebCore {
34
35 CSSSelectorList::~CSSSelectorList()
36 {
37     deleteSelectors();
38 }
39
40 void CSSSelectorList::adopt(CSSSelectorList& list)
41 {
42     deleteSelectors();
43     m_selectorArray = list.m_selectorArray;
44     list.m_selectorArray = 0;
45 }
46
47 void CSSSelectorList::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector)
48 {
49     deleteSelectors();
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())
54             ++flattenedSize;
55     }
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);
62         return;
63     }
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();
68         while (current) {
69             OwnPtr<CSSSelector> selector = current->releaseSelector();
70             current = current->tagHistory();
71             move(selector.release(), &m_selectorArray[arrayIndex]);
72             ASSERT(!m_selectorArray[arrayIndex].isLastInSelectorList());
73             if (current)
74                 m_selectorArray[arrayIndex].setNotLastInTagHistory();
75             ++arrayIndex;
76         }
77         ASSERT(m_selectorArray[arrayIndex - 1].isLastInTagHistory());
78     }
79     ASSERT(flattenedSize == arrayIndex);
80     m_selectorArray[arrayIndex - 1].setLastInSelectorList();
81     selectorVector.shrink(0);
82 }
83
84 void CSSSelectorList::deleteSelectors()
85 {
86     if (!m_selectorArray)
87         return;
88
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();
95     if (done)
96         delete s;
97     else {
98         while (1) {
99             s->~CSSSelector();
100             if (done)
101                 break;
102             ++s;
103             done = s->isLastInSelectorList();
104         }
105         fastFree(m_selectorArray);
106     }
107 }
108
109 String CSSSelectorList::selectorsText() const
110 {
111     StringBuilder result;
112
113     for (CSSSelector* s = first(); s; s = next(s)) {
114         if (s != first())
115             result.append(", ");
116         result.append(s->selectorText());
117     }
118
119     return result.toString();
120 }
121
122 template <typename Functor>
123 static bool forEachTagSelector(Functor& functor, CSSSelector* selector)
124 {
125     ASSERT(selector);
126
127     do {
128         if (functor(selector))
129             return true;
130         if (CSSSelectorList* selectorList = selector->selectorList()) {
131             for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
132                 if (forEachTagSelector(functor, subSelector))
133                     return true;
134             }
135         }
136     } while ((selector = selector->tagHistory()));
137
138     return false;
139 }
140
141 template <typename Functor>
142 static bool forEachSelector(Functor& functor, const CSSSelectorList* selectorList)
143 {
144     for (CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(selector)) {
145         if (forEachTagSelector(functor, selector))
146             return true;
147     }
148
149     return false;
150 }
151
152 class SelectorNeedsNamespaceResolutionFunctor {
153 public:
154     bool operator()(CSSSelector* selector)
155     {
156         if (selector->hasTag() && selector->tag().prefix() != nullAtom && selector->tag().prefix() != starAtom)
157             return true;
158         if (selector->isAttributeSelector() && selector->attribute().prefix() != nullAtom && selector->attribute().prefix() != starAtom)
159             return true;
160         return false;
161     }
162 };
163
164 bool CSSSelectorList::selectorsNeedNamespaceResolution()
165 {
166     SelectorNeedsNamespaceResolutionFunctor functor;
167     return forEachSelector(functor, this);
168 }
169
170 class SelectorHasUnknownPseudoElementFunctor {
171 public:
172     bool operator()(CSSSelector* selector)
173     {
174         return selector->isUnknownPseudoElement();
175     }
176 };
177
178 bool CSSSelectorList::hasUnknownPseudoElements() const
179 {
180     SelectorHasUnknownPseudoElementFunctor functor;
181     return forEachSelector(functor, this);
182 }
183
184
185
186 } // namespace WebCore