1/*
2 * Copyright (C) 2017 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include <wtf/DataLog.h>
29#include <wtf/HashSet.h>
30#include <wtf/LoggingHashID.h>
31#include <wtf/LoggingHashTraits.h>
32
33namespace WTF {
34
35template<
36 const char* typeArguments,
37 typename ValueArg, typename HashArg = typename DefaultHash<ValueArg>::Hash,
38 typename TraitsArg = HashTraits<ValueArg>,
39 typename LoggingTraits = LoggingHashKeyTraits<ValueArg>>
40class LoggingHashSet final {
41 WTF_MAKE_FAST_ALLOCATED;
42
43 typedef TraitsArg ValueTraits;
44 typedef typename ValueTraits::TakeType TakeType;
45
46public:
47 typedef WTF::HashSet<ValueArg, HashArg, TraitsArg> HashSet;
48
49 typedef typename HashSet::ValueType ValueType;
50 typedef typename HashSet::iterator iterator;
51 typedef typename HashSet::const_iterator const_iterator;
52 typedef typename HashSet::AddResult AddResult;
53
54 LoggingHashSet()
55 {
56 dataLog("auto* ", m_id, " = new HashSet<", typeArguments, ">();\n");
57 }
58
59 ~LoggingHashSet()
60 {
61 dataLog("delete ", m_id, ";\n");
62 }
63
64 LoggingHashSet(const LoggingHashSet& other)
65 : m_set(other.m_set)
66 {
67 dataLog("auto* ", m_id, " = new HashSet<", typeArguments, ">(*", other.m_id, ");\n");
68 }
69
70 LoggingHashSet(LoggingHashSet&& other)
71 : m_set(other.m_set)
72 {
73 dataLog("auto* ", m_id, " = new HashSet<", typeArguments, ">(WTFMove(*", other.m_id, "));\n");
74 }
75
76 LoggingHashSet& operator=(const LoggingHashSet& other)
77 {
78 dataLog("*", m_id, " = *", other.m_id, ";\n");
79 m_set = other.m_set;
80 return *this;
81 }
82
83 LoggingHashSet& operator=(LoggingHashSet&& other)
84 {
85 dataLog("*", m_id, " = WTFMove(*", other.m_id, ");\n");
86 m_set = WTFMove(other.m_set);
87 return *this;
88 }
89
90 void swap(LoggingHashSet& other)
91 {
92 dataLog(m_id, "->swap(*", other.m_id, ");\n");
93 m_set.swap(other.m_set);
94 }
95
96 unsigned size() const { return m_set.size(); }
97 unsigned capacity() const { return m_set.capacity(); }
98 bool isEmpty() const { return m_set.isEmpty(); }
99
100 iterator begin() const { return m_set.begin(); }
101 iterator end() const { return m_set.end(); }
102
103 iterator random() { return m_set.random(); }
104 const_iterator random() const { return m_set.random(); }
105
106 iterator find(const ValueType& value) const
107 {
108 StringPrintStream string;
109 string.print("{\n");
110 string.print(" auto iter = ", m_id, "->find(");
111 LoggingTraits::print(string, value);
112 string.print(");\n");
113 iterator result = m_set.find(value);
114 if (result == m_set.end())
115 string.print(" RELEASE_ASSERT(iter == ", m_id, "->end());\n");
116 else
117 string.print(" RELEASE_ASSERT(iter != ", m_id, "->end());\n");
118 string.print("}\n");
119 dataLog(string.toCString());
120 return result;
121 }
122
123 bool contains(const ValueType& value) const
124 {
125 return find(value) != end();
126 }
127
128 // FIXME: Implement the translator versions of find() and friends.
129
130 AddResult add(const ValueType& value)
131 {
132 StringPrintStream string;
133 string.print(m_id, "->add(");
134 LoggingTraits::print(string, value);
135 string.print(");\n");
136 dataLog(string.toCString());
137 return m_set.add(value);
138 }
139
140 AddResult add(ValueType&& value)
141 {
142 StringPrintStream string;
143 string.print(m_id, "->add(");
144 LoggingTraits::print(string, value);
145 string.print(");\n");
146 dataLog(string.toCString());
147 return m_set.add(WTFMove(value));
148 }
149
150 void addVoid(const ValueType& value)
151 {
152 StringPrintStream string;
153 string.print(m_id, "->addVoid(");
154 LoggingTraits::print(string, value);
155 string.print(");\n");
156 dataLog(string.toCString());
157 m_set.addVoid(value);
158 }
159
160 void addVoid(ValueType&& value)
161 {
162 StringPrintStream string;
163 string.print(m_id, "->addVoid(");
164 LoggingTraits::print(string, value);
165 string.print(");\n");
166 dataLog(string.toCString());
167 m_set.addVoid(WTFMove(value));
168 }
169
170 template<typename IteratorType>
171 bool add(IteratorType begin, IteratorType end)
172 {
173 bool changed = false;
174 for (IteratorType iter = begin; iter != end; ++iter)
175 changed |= add(*iter).isNewEntry;
176 return changed;
177 }
178
179 bool remove(iterator iter)
180 {
181 // FIXME: We should do much better than this!
182 if (iter == end())
183 return false;
184 return remove(*iter);
185 }
186
187 bool remove(const ValueType& value)
188 {
189 StringPrintStream string;
190 string.print(m_id, "->remove(");
191 LoggingTraits::print(string, value);
192 string.print(");\n");
193 dataLog(string.toCString());
194 return m_set.remove(value);
195 }
196
197 // FIXME: Implement removeIf
198
199 void clear()
200 {
201 dataLog(m_id, "->clear();\n");
202 m_set.clear();
203 }
204
205 TakeType take(const ValueType& value)
206 {
207 StringPrintStream string;
208 string.print(m_id, "->remove(");
209 LoggingTraits::print(string, value);
210 string.print(");\n");
211 dataLog(string.toCString());
212 return m_set.take(value);
213 }
214
215 TakeType take(iterator iter)
216 {
217 return take(*iter);
218 }
219
220 TakeType takeAny()
221 {
222 dataLog(m_id, "->takeAny();\n");
223 return m_set.takeAny();
224 }
225
226 template<typename OtherCollection>
227 bool operator==(const OtherCollection& otherCollection) const
228 {
229 if (size() != otherCollection.size())
230 return false;
231 for (const auto& other : otherCollection) {
232 if (!contains(other))
233 return false;
234 }
235 return true;
236 }
237
238 template<typename OtherCollection>
239 bool operator!=(const OtherCollection& other) const
240 {
241 return !(*this == other);
242 }
243
244private:
245 HashSet m_set;
246 LoggingHashID m_id;
247};
248
249} // namespace WTF
250
251using WTF::LoggingHashSet;
252