OLD | NEW |
1 /* | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. | 2 // Use of this source code is governed by a BSD-style license that can be |
3 * | 3 // found in the LICENSE file. |
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., 51 Franklin Street, Fifth Floor, | |
17 * Boston, MA 02110-1301, USA. | |
18 * | |
19 */ | |
20 | 4 |
21 #ifndef WTF_HashCountedSet_h | 5 #include "platform/wtf/HashCountedSet.h" |
22 #define WTF_HashCountedSet_h | |
23 | 6 |
24 #include "wtf/Assertions.h" | 7 // The contents of this header was moved to platform/wtf as part of |
25 #include "wtf/HashMap.h" | 8 // WTF migration project. See the following post for details: |
26 #include "wtf/Vector.h" | 9 // https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gY
CAAJ |
27 #include "wtf/allocator/PartitionAllocator.h" | |
28 | |
29 namespace WTF { | |
30 | |
31 // An unordered hash set that keeps track of how many times you added an item to | |
32 // the set. The iterators have fields ->key and ->value that return the set | |
33 // members and their counts, respectively. | |
34 template <typename Value, | |
35 typename HashFunctions = typename DefaultHash<Value>::Hash, | |
36 typename Traits = HashTraits<Value>, | |
37 typename Allocator = PartitionAllocator> | |
38 class HashCountedSet { | |
39 USE_ALLOCATOR(HashCountedSet, Allocator); | |
40 WTF_MAKE_NONCOPYABLE(HashCountedSet); | |
41 | |
42 private: | |
43 typedef HashMap<Value, | |
44 unsigned, | |
45 HashFunctions, | |
46 Traits, | |
47 HashTraits<unsigned>, | |
48 Allocator> | |
49 ImplType; | |
50 | |
51 public: | |
52 typedef Value ValueType; | |
53 using value_type = ValueType; | |
54 typedef typename ImplType::iterator iterator; | |
55 typedef typename ImplType::const_iterator const_iterator; | |
56 typedef typename ImplType::AddResult AddResult; | |
57 | |
58 HashCountedSet() { | |
59 static_assert(Allocator::isGarbageCollected || | |
60 !IsPointerToGarbageCollectedType<Value>::value, | |
61 "Cannot put raw pointers to garbage-collected classes into " | |
62 "an off-heap HashCountedSet. Use " | |
63 "HeapHashCountedSet<Member<T>> instead."); | |
64 } | |
65 | |
66 void swap(HashCountedSet& other) { m_impl.swap(other.m_impl); } | |
67 | |
68 unsigned size() const { return m_impl.size(); } | |
69 unsigned capacity() const { return m_impl.capacity(); } | |
70 bool isEmpty() const { return m_impl.isEmpty(); } | |
71 | |
72 // Iterators iterate over pairs of values (called key) and counts (called | |
73 // value). | |
74 iterator begin() { return m_impl.begin(); } | |
75 iterator end() { return m_impl.end(); } | |
76 const_iterator begin() const { return m_impl.begin(); } | |
77 const_iterator end() const { return m_impl.end(); } | |
78 | |
79 iterator find(const ValueType& value) { return m_impl.find(value); } | |
80 const_iterator find(const ValueType& value) const { | |
81 return m_impl.find(value); | |
82 } | |
83 bool contains(const ValueType& value) const { return m_impl.contains(value); } | |
84 unsigned count(const ValueType& value) const { return m_impl.at(value); } | |
85 | |
86 // Increases the count if an equal value is already present the return value | |
87 // is a pair of an iterator to the new value's location, and a bool that is | |
88 // true if an new entry was added. | |
89 AddResult add(const ValueType&); | |
90 | |
91 // Generalized add(), adding the value N times. | |
92 AddResult add(const ValueType&, unsigned); | |
93 | |
94 // Reduces the count of the value, and removes it if count goes down to | |
95 // zero, returns true if the value is removed. | |
96 bool remove(const ValueType& value) { return remove(find(value)); } | |
97 bool remove(iterator); | |
98 | |
99 // Removes the value, regardless of its count. | |
100 void removeAll(const ValueType& value) { removeAll(find(value)); } | |
101 void removeAll(iterator); | |
102 | |
103 // Clears the whole set. | |
104 void clear() { m_impl.clear(); } | |
105 | |
106 Vector<Value> asVector() const; | |
107 | |
108 template <typename VisitorDispatcher> | |
109 void trace(VisitorDispatcher visitor) { | |
110 m_impl.trace(visitor); | |
111 } | |
112 | |
113 private: | |
114 ImplType m_impl; | |
115 }; | |
116 | |
117 template <typename T, typename U, typename V, typename W> | |
118 inline typename HashCountedSet<T, U, V, W>::AddResult | |
119 HashCountedSet<T, U, V, W>::add(const ValueType& value, unsigned count) { | |
120 DCHECK_GT(count, 0u); | |
121 AddResult result = m_impl.insert(value, 0); | |
122 result.storedValue->value += count; | |
123 return result; | |
124 } | |
125 | |
126 template <typename T, typename U, typename V, typename W> | |
127 inline typename HashCountedSet<T, U, V, W>::AddResult | |
128 HashCountedSet<T, U, V, W>::add(const ValueType& value) { | |
129 return add(value, 1u); | |
130 } | |
131 | |
132 template <typename T, typename U, typename V, typename W> | |
133 inline bool HashCountedSet<T, U, V, W>::remove(iterator it) { | |
134 if (it == end()) | |
135 return false; | |
136 | |
137 unsigned oldVal = it->value; | |
138 DCHECK(oldVal); | |
139 unsigned newVal = oldVal - 1; | |
140 if (newVal) { | |
141 it->value = newVal; | |
142 return false; | |
143 } | |
144 | |
145 m_impl.erase(it); | |
146 return true; | |
147 } | |
148 | |
149 template <typename T, typename U, typename V, typename W> | |
150 inline void HashCountedSet<T, U, V, W>::removeAll(iterator it) { | |
151 if (it == end()) | |
152 return; | |
153 | |
154 m_impl.erase(it); | |
155 } | |
156 | |
157 template <typename Value, | |
158 typename HashFunctions, | |
159 typename Traits, | |
160 typename Allocator, | |
161 typename VectorType> | |
162 inline void copyToVector( | |
163 const HashCountedSet<Value, HashFunctions, Traits, Allocator>& collection, | |
164 VectorType& vector) { | |
165 { | |
166 // Disallow GC across resize allocation, see crbug.com/568173 | |
167 typename VectorType::GCForbiddenScope scope; | |
168 vector.resize(collection.size()); | |
169 } | |
170 | |
171 auto it = collection.begin(); | |
172 auto end = collection.end(); | |
173 for (unsigned i = 0; it != end; ++it, ++i) | |
174 vector[i] = (*it).key; | |
175 } | |
176 | |
177 template <typename T, typename U, typename V, typename W> | |
178 inline Vector<T> HashCountedSet<T, U, V, W>::asVector() const { | |
179 Vector<T> vector; | |
180 copyToVector(*this, vector); | |
181 return vector; | |
182 } | |
183 | |
184 } // namespace WTF | |
185 | |
186 using WTF::HashCountedSet; | |
187 | |
188 #endif // WTF_HashCountedSet_h | |
OLD | NEW |