1/*
2 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2010, 2013 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 "CSSValueList.h"
23
24#include "CSSParserValues.h"
25#include <wtf/PassOwnPtr.h>
26#include <wtf/text/StringBuilder.h>
27
28namespace WebCore {
29
30CSSValueList::CSSValueList(ClassType classType, ValueListSeparator listSeparator)
31    : CSSValue(classType)
32{
33    m_valueListSeparator = listSeparator;
34}
35
36CSSValueList::CSSValueList(ValueListSeparator listSeparator)
37    : CSSValue(ValueListClass)
38{
39    m_valueListSeparator = listSeparator;
40}
41
42CSSValueList::CSSValueList(CSSParserValueList* parserValues)
43    : CSSValue(ValueListClass)
44{
45    m_valueListSeparator = SpaceSeparator;
46    if (parserValues) {
47        m_values.reserveInitialCapacity(parserValues->size());
48        for (unsigned i = 0; i < parserValues->size(); ++i)
49            m_values.uncheckedAppend(parserValues->valueAt(i)->createCSSValue());
50    }
51}
52
53bool CSSValueList::removeAll(CSSValue* val)
54{
55    bool found = false;
56    for (size_t index = 0; index < m_values.size(); index++) {
57        RefPtr<CSSValue>& value = m_values.at(index);
58        if (value && val && value->equals(*val)) {
59            m_values.remove(index);
60            found = true;
61        }
62    }
63
64    return found;
65}
66
67bool CSSValueList::hasValue(CSSValue* val) const
68{
69    for (size_t index = 0; index < m_values.size(); index++) {
70        const RefPtr<CSSValue>& value = m_values.at(index);
71        if (value && val && value->equals(*val))
72            return true;
73    }
74    return false;
75}
76
77PassRefPtr<CSSValueList> CSSValueList::copy()
78{
79    RefPtr<CSSValueList> newList;
80    switch (m_valueListSeparator) {
81    case SpaceSeparator:
82        newList = createSpaceSeparated();
83        break;
84    case CommaSeparator:
85        newList = createCommaSeparated();
86        break;
87    case SlashSeparator:
88        newList = createSlashSeparated();
89        break;
90    default:
91        ASSERT_NOT_REACHED();
92    }
93    for (size_t index = 0; index < m_values.size(); index++)
94        newList->append(m_values[index]);
95    return newList.release();
96}
97
98String CSSValueList::customCssText() const
99{
100    StringBuilder result;
101    String separator;
102    switch (m_valueListSeparator) {
103    case SpaceSeparator:
104        separator = ASCIILiteral(" ");
105        break;
106    case CommaSeparator:
107        separator = ASCIILiteral(", ");
108        break;
109    case SlashSeparator:
110        separator = ASCIILiteral(" / ");
111        break;
112    default:
113        ASSERT_NOT_REACHED();
114    }
115
116    unsigned size = m_values.size();
117    for (unsigned i = 0; i < size; i++) {
118        if (!result.isEmpty())
119            result.append(separator);
120        result.append(m_values[i]->cssText());
121    }
122
123    return result.toString();
124}
125
126bool CSSValueList::equals(const CSSValueList& other) const
127{
128    return m_valueListSeparator == other.m_valueListSeparator && compareCSSValueVector<CSSValue>(m_values, other.m_values);
129}
130
131bool CSSValueList::equals(const CSSValue& other) const
132{
133    if (m_values.size() != 1)
134        return false;
135
136    const RefPtr<CSSValue>& value = m_values[0];
137    return value && value->equals(other);
138}
139
140#if ENABLE(CSS_VARIABLES)
141String CSSValueList::customSerializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
142{
143    StringBuilder result;
144    String separator;
145    switch (m_valueListSeparator) {
146    case SpaceSeparator:
147        separator = ASCIILiteral(" ");
148        break;
149    case CommaSeparator:
150        separator = ASCIILiteral(", ");
151        break;
152    case SlashSeparator:
153        separator = ASCIILiteral(" / ");
154        break;
155    default:
156        ASSERT_NOT_REACHED();
157    }
158
159    unsigned size = m_values.size();
160    for (unsigned i = 0; i < size; i++) {
161        if (!result.isEmpty())
162            result.append(separator);
163        result.append(m_values[i]->serializeResolvingVariables(variables));
164    }
165
166    return result.toString();
167}
168#endif
169
170void CSSValueList::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const StyleSheetContents* styleSheet) const
171{
172    size_t size = m_values.size();
173    for (size_t i = 0; i < size; ++i)
174        m_values[i]->addSubresourceStyleURLs(urls, styleSheet);
175}
176
177bool CSSValueList::hasFailedOrCanceledSubresources() const
178{
179    for (unsigned i = 0; i < m_values.size(); ++i) {
180        if (m_values[i]->hasFailedOrCanceledSubresources())
181            return true;
182    }
183    return false;
184}
185
186CSSValueList::CSSValueList(const CSSValueList& cloneFrom)
187    : CSSValue(cloneFrom.classType(), /* isCSSOMSafe */ true)
188{
189    m_valueListSeparator = cloneFrom.m_valueListSeparator;
190    m_values.resize(cloneFrom.m_values.size());
191    for (unsigned i = 0; i < m_values.size(); ++i)
192        m_values[i] = cloneFrom.m_values[i]->cloneForCSSOM();
193}
194
195PassRefPtr<CSSValueList> CSSValueList::cloneForCSSOM() const
196{
197    return adoptRef(new CSSValueList(*this));
198}
199
200} // namespace WebCore
201