1/*
2 * Copyright (C) 2007-2014 Apple Inc. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 *
19 */
20
21#pragma once
22
23#include <wtf/MainThread.h>
24#include <wtf/text/AtomString.h>
25
26namespace WebCore {
27
28class SpaceSplitStringData {
29 WTF_MAKE_NONCOPYABLE(SpaceSplitStringData);
30 WTF_MAKE_FAST_ALLOCATED;
31public:
32 static RefPtr<SpaceSplitStringData> create(const AtomString&);
33
34 bool contains(const AtomString& string)
35 {
36 const AtomString* data = tokenArrayStart();
37 unsigned i = 0;
38 do {
39 if (data[i] == string)
40 return true;
41 ++i;
42 } while (i < m_size);
43 return false;
44 }
45
46 bool containsAll(SpaceSplitStringData&);
47
48 unsigned size() const { return m_size; }
49 static ptrdiff_t sizeMemoryOffset() { return OBJECT_OFFSETOF(SpaceSplitStringData, m_size); }
50
51 const AtomString& operator[](unsigned i)
52 {
53 RELEASE_ASSERT(i < m_size);
54 return tokenArrayStart()[i];
55 }
56
57 void ref()
58 {
59 ASSERT(isMainThread());
60 ASSERT(m_refCount);
61 ++m_refCount;
62 }
63
64 void deref()
65 {
66 ASSERT(isMainThread());
67 ASSERT(m_refCount);
68 unsigned tempRefCount = m_refCount - 1;
69 if (!tempRefCount) {
70 destroy(this);
71 return;
72 }
73 m_refCount = tempRefCount;
74 }
75
76 static ptrdiff_t tokensMemoryOffset() { return sizeof(SpaceSplitStringData); }
77
78private:
79 static Ref<SpaceSplitStringData> create(const AtomString&, unsigned tokenCount);
80 SpaceSplitStringData(const AtomString& string, unsigned size)
81 : m_keyString(string)
82 , m_refCount(1)
83 , m_size(size)
84 {
85 ASSERT(!string.isEmpty());
86 ASSERT_WITH_MESSAGE(m_size, "SpaceSplitStringData should never be empty by definition. There is no difference between empty and null.");
87 }
88
89 ~SpaceSplitStringData() = default;
90 static void destroy(SpaceSplitStringData*);
91
92 AtomString* tokenArrayStart() { return reinterpret_cast<AtomString*>(this + 1); }
93
94 AtomString m_keyString;
95 unsigned m_refCount;
96 unsigned m_size;
97};
98
99class SpaceSplitString {
100public:
101 SpaceSplitString() = default;
102 SpaceSplitString(const AtomString& string, bool shouldFoldCase) { set(string, shouldFoldCase); }
103
104 bool operator!=(const SpaceSplitString& other) const { return m_data != other.m_data; }
105
106 void set(const AtomString&, bool shouldFoldCase);
107 void clear() { m_data = nullptr; }
108
109 bool contains(const AtomString& string) const { return m_data && m_data->contains(string); }
110 bool containsAll(const SpaceSplitString& names) const { return !names.m_data || (m_data && m_data->containsAll(*names.m_data)); }
111
112 unsigned size() const { return m_data ? m_data->size() : 0; }
113 bool isEmpty() const { return !m_data; }
114 const AtomString& operator[](unsigned i) const
115 {
116 ASSERT_WITH_SECURITY_IMPLICATION(m_data);
117 return (*m_data)[i];
118 }
119
120 static bool spaceSplitStringContainsValue(const String& spaceSplitString, const char* value, unsigned length, bool shouldFoldCase);
121 template<size_t length>
122 static bool spaceSplitStringContainsValue(const String& spaceSplitString, const char (&value)[length], bool shouldFoldCase)
123 {
124 return spaceSplitStringContainsValue(spaceSplitString, value, length - 1, shouldFoldCase);
125 }
126
127private:
128 RefPtr<SpaceSplitStringData> m_data;
129};
130
131} // namespace WebCore
132