1/*
2 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2010 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/CSSValueList.h"
23
24#include "core/css/CSSPrimitiveValue.h"
25#include "wtf/text/StringBuilder.h"
26
27namespace blink {
28
29CSSValueList::CSSValueList(ClassType classType, ValueListSeparator listSeparator)
30    : CSSValue(classType)
31{
32    m_valueListSeparator = listSeparator;
33}
34
35CSSValueList::CSSValueList(ValueListSeparator listSeparator)
36    : CSSValue(ValueListClass)
37{
38    m_valueListSeparator = listSeparator;
39}
40
41bool CSSValueList::removeAll(CSSValue* val)
42{
43    bool found = false;
44    for (size_t index = 0; index < m_values.size(); index++) {
45        RefPtrWillBeMember<CSSValue>& value = m_values.at(index);
46        if (value && val && value->equals(*val)) {
47            m_values.remove(index);
48            found = true;
49        }
50    }
51
52    return found;
53}
54
55bool CSSValueList::hasValue(CSSValue* val) const
56{
57    for (size_t index = 0; index < m_values.size(); index++) {
58        const RefPtrWillBeMember<CSSValue>& value = m_values.at(index);
59        if (value && val && value->equals(*val))
60            return true;
61    }
62    return false;
63}
64
65PassRefPtrWillBeRawPtr<CSSValueList> CSSValueList::copy()
66{
67    RefPtrWillBeRawPtr<CSSValueList> newList = nullptr;
68    switch (m_valueListSeparator) {
69    case SpaceSeparator:
70        newList = createSpaceSeparated();
71        break;
72    case CommaSeparator:
73        newList = createCommaSeparated();
74        break;
75    case SlashSeparator:
76        newList = createSlashSeparated();
77        break;
78    default:
79        ASSERT_NOT_REACHED();
80    }
81    for (size_t index = 0; index < m_values.size(); index++)
82        newList->append(m_values[index]);
83    return newList.release();
84}
85
86String CSSValueList::customCSSText(CSSTextFormattingFlags formattingFlag) const
87{
88    StringBuilder result;
89    String separator;
90    switch (m_valueListSeparator) {
91    case SpaceSeparator:
92        separator = " ";
93        break;
94    case CommaSeparator:
95        separator = ", ";
96        break;
97    case SlashSeparator:
98        separator = " / ";
99        break;
100    default:
101        ASSERT_NOT_REACHED();
102    }
103
104    unsigned size = m_values.size();
105    for (unsigned i = 0; i < size; i++) {
106        if (!result.isEmpty())
107            result.append(separator);
108        if (formattingFlag == AlwaysQuoteCSSString && m_values[i]->isPrimitiveValue())
109            result.append(toCSSPrimitiveValue(m_values[i].get())->customCSSText(AlwaysQuoteCSSString));
110        else
111            result.append(m_values[i]->cssText());
112    }
113
114    return result.toString();
115}
116
117bool CSSValueList::equals(const CSSValueList& other) const
118{
119    return m_valueListSeparator == other.m_valueListSeparator && compareCSSValueVector(m_values, other.m_values);
120}
121
122bool CSSValueList::equals(const CSSValue& other) const
123{
124    if (m_values.size() != 1)
125        return false;
126
127    const RefPtrWillBeMember<CSSValue>& value = m_values[0];
128    return value && value->equals(other);
129}
130
131bool CSSValueList::hasFailedOrCanceledSubresources() const
132{
133    for (unsigned i = 0; i < m_values.size(); ++i) {
134        if (m_values[i]->hasFailedOrCanceledSubresources())
135            return true;
136    }
137    return false;
138}
139
140CSSValueList::CSSValueList(const CSSValueList& cloneFrom)
141    : CSSValue(cloneFrom.classType(), /* isCSSOMSafe */ true)
142{
143    m_valueListSeparator = cloneFrom.m_valueListSeparator;
144    m_values.resize(cloneFrom.m_values.size());
145    for (unsigned i = 0; i < m_values.size(); ++i)
146        m_values[i] = cloneFrom.m_values[i]->cloneForCSSOM();
147}
148
149PassRefPtrWillBeRawPtr<CSSValueList> CSSValueList::cloneForCSSOM() const
150{
151    return adoptRefWillBeNoop(new CSSValueList(*this));
152}
153
154void CSSValueList::traceAfterDispatch(Visitor* visitor)
155{
156    visitor->trace(m_values);
157    CSSValue::traceAfterDispatch(visitor);
158}
159
160} // namespace blink
161