OLD | NEW |
1 #ifndef SkTHash_DEFINED | 1 #ifndef SkTHash_DEFINED |
2 #define SkTHash_DEFINED | 2 #define SkTHash_DEFINED |
3 | 3 |
4 #include "SkTypes.h" | 4 #include "SkTypes.h" |
5 #include "SkTemplates.h" | 5 #include "SkTemplates.h" |
6 | 6 |
7 // Before trying to use SkTHashTable, look below to see if SkTHashMap or SkTHash
Set works for you. | 7 // Before trying to use SkTHashTable, look below to see if SkTHashMap or SkTHash
Set works for you. |
8 // They're easier to use, usually perform the same, and have fewer sharp edges. | 8 // They're easier to use, usually perform the same, and have fewer sharp edges. |
9 | 9 |
10 // T and K are treated as ordinary copyable C++ types. | 10 // T and K are treated as ordinary copyable C++ types. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 if (hash == s.hash && key == Traits::GetKey(s.val)) { | 58 if (hash == s.hash && key == Traits::GetKey(s.val)) { |
59 return &s.val; | 59 return &s.val; |
60 } | 60 } |
61 index = this->next(index, n); | 61 index = this->next(index, n); |
62 } | 62 } |
63 SkASSERT(fCapacity == 0); | 63 SkASSERT(fCapacity == 0); |
64 return NULL; | 64 return NULL; |
65 } | 65 } |
66 | 66 |
67 // Call fn on every entry in the table. You may mutate the entries, but be
very careful. | 67 // Call fn on every entry in the table. You may mutate the entries, but be
very careful. |
68 template <typename Arg> | 68 template <typename Fn> // f(T*) |
69 void foreach(void(*fn)(T*, Arg), Arg arg) { | 69 void foreach(Fn&& fn) { |
70 for (int i = 0; i < fCapacity; i++) { | 70 for (int i = 0; i < fCapacity; i++) { |
71 Slot& s = fSlots[i]; | 71 if (!fSlots[i].empty()) { |
72 if (!s.empty()) { | 72 fn(&fSlots[i].val); |
73 fn(&s.val, arg); | |
74 } | 73 } |
75 } | 74 } |
76 } | 75 } |
| 76 |
| 77 // Call fn on every entry in the table. You may not mutate anything. |
| 78 template <typename Fn> // f(T) or f(const T&) |
| 79 void foreach(Fn&& fn) const { |
| 80 for (int i = 0; i < fCapacity; i++) { |
| 81 if (!fSlots[i].empty()) { |
| 82 fn(fSlots[i].val); |
| 83 } |
| 84 } |
| 85 } |
77 | 86 |
78 private: | 87 private: |
79 T* uncheckedSet(const T& val) { | 88 T* uncheckedSet(const T& val) { |
80 const K& key = Traits::GetKey(val); | 89 const K& key = Traits::GetKey(val); |
81 uint32_t hash = Hash(key); | 90 uint32_t hash = Hash(key); |
82 int index = hash & (fCapacity-1); | 91 int index = hash & (fCapacity-1); |
83 for (int n = 0; n < fCapacity; n++) { | 92 for (int n = 0; n < fCapacity; n++) { |
84 Slot& s = fSlots[index]; | 93 Slot& s = fSlots[index]; |
85 if (s.empty()) { | 94 if (s.empty()) { |
86 // New entry. | 95 // New entry. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 T val; | 147 T val; |
139 uint32_t hash; | 148 uint32_t hash; |
140 }; | 149 }; |
141 | 150 |
142 int fCount, fCapacity; | 151 int fCount, fCapacity; |
143 SkAutoTArray<Slot> fSlots; | 152 SkAutoTArray<Slot> fSlots; |
144 }; | 153 }; |
145 | 154 |
146 // Maps K->V. A more user-friendly wrapper around SkTHashTable, suitable for mo
st use cases. | 155 // Maps K->V. A more user-friendly wrapper around SkTHashTable, suitable for mo
st use cases. |
147 // K and V are treated as ordinary copyable C++ types, with no assumed relations
hip between the two. | 156 // K and V are treated as ordinary copyable C++ types, with no assumed relations
hip between the two. |
148 template <typename K, typename V, uint32_t(*HashK)(const K&)> | 157 template <typename K, typename V, uint32_t(*HashK)(const K&) = &SkGoodHash> |
149 class SkTHashMap : SkNoncopyable { | 158 class SkTHashMap : SkNoncopyable { |
150 public: | 159 public: |
151 SkTHashMap() {} | 160 SkTHashMap() {} |
152 | 161 |
153 // Clear the map. | 162 // Clear the map. |
154 void reset() { fTable.reset(); } | 163 void reset() { fTable.reset(); } |
155 | 164 |
156 // How many key/value pairs are in the table? | 165 // How many key/value pairs are in the table? |
157 int count() const { return fTable.count(); } | 166 int count() const { return fTable.count(); } |
158 | 167 |
(...skipping 10 matching lines...) Expand all Loading... |
169 // If there is key/value entry in the table with this key, return a pointer
to the value. | 178 // If there is key/value entry in the table with this key, return a pointer
to the value. |
170 // If not, return NULL. | 179 // If not, return NULL. |
171 V* find(const K& key) const { | 180 V* find(const K& key) const { |
172 if (Pair* p = fTable.find(key)) { | 181 if (Pair* p = fTable.find(key)) { |
173 return &p->val; | 182 return &p->val; |
174 } | 183 } |
175 return NULL; | 184 return NULL; |
176 } | 185 } |
177 | 186 |
178 // Call fn on every key/value pair in the table. You may mutate the value b
ut not the key. | 187 // Call fn on every key/value pair in the table. You may mutate the value b
ut not the key. |
179 void foreach(void(*fn)(K, V*)) { fTable.foreach(ForEach, fn); } | 188 template <typename Fn> // f(K, V*) or f(const K&, V*) |
| 189 void foreach(Fn&& fn) { |
| 190 fTable.foreach([&fn](Pair* p){ fn(p->key, &p->val); }); |
| 191 } |
| 192 |
| 193 // Call fn on every key/value pair in the table. You may not mutate anythin
g. |
| 194 template <typename Fn> // f(K, V), f(const K&, V), f(K, const V&) or f(cons
t K&, const V&). |
| 195 void foreach(Fn&& fn) const { |
| 196 fTable.foreach([&fn](const Pair& p){ fn(p.key, p.val); }); |
| 197 } |
180 | 198 |
181 private: | 199 private: |
182 struct Pair { | 200 struct Pair { |
183 K key; | 201 K key; |
184 V val; | 202 V val; |
185 static const K& GetKey(const Pair& p) { return p.key; } | 203 static const K& GetKey(const Pair& p) { return p.key; } |
186 static uint32_t Hash(const K& key) { return HashK(key); } | 204 static uint32_t Hash(const K& key) { return HashK(key); } |
187 }; | 205 }; |
188 static void ForEach(Pair* p, void (*fn)(K, V*)) { fn(p->key, &p->val); } | |
189 | 206 |
190 SkTHashTable<Pair, K> fTable; | 207 SkTHashTable<Pair, K> fTable; |
191 }; | 208 }; |
192 | 209 |
193 // A set of T. T is treated as an ordiary copyable C++ type. | 210 // A set of T. T is treated as an ordiary copyable C++ type. |
194 template <typename T, uint32_t(*HashT)(const T&)> | 211 template <typename T, uint32_t(*HashT)(const T&) = &SkGoodHash> |
195 class SkTHashSet : SkNoncopyable { | 212 class SkTHashSet : SkNoncopyable { |
196 public: | 213 public: |
197 SkTHashSet() {} | 214 SkTHashSet() {} |
198 | 215 |
199 // Clear the set. | 216 // Clear the set. |
200 void reset() { fTable.reset(); } | 217 void reset() { fTable.reset(); } |
201 | 218 |
202 // How many items are in the set? | 219 // How many items are in the set? |
203 int count() const { return fTable.count(); } | 220 int count() const { return fTable.count(); } |
204 | 221 |
205 // Copy an item into the set. | 222 // Copy an item into the set. |
206 void add(const T& item) { fTable.set(item); } | 223 void add(const T& item) { fTable.set(item); } |
207 | 224 |
208 // Is this item in the set? | 225 // Is this item in the set? |
209 bool contains(const T& item) const { return SkToBool(fTable.find(item)); } | 226 bool contains(const T& item) const { return SkToBool(fTable.find(item)); } |
210 | 227 |
211 private: | 228 private: |
212 struct Traits { | 229 struct Traits { |
213 static const T& GetKey(const T& item) { return item; } | 230 static const T& GetKey(const T& item) { return item; } |
214 static uint32_t Hash(const T& item) { return HashT(item); } | 231 static uint32_t Hash(const T& item) { return HashT(item); } |
215 }; | 232 }; |
216 SkTHashTable<T, T, Traits> fTable; | 233 SkTHashTable<T, T, Traits> fTable; |
217 }; | 234 }; |
218 | 235 |
219 #endif//SkTHash_DEFINED | 236 #endif//SkTHash_DEFINED |
OLD | NEW |