Loading...
Searching...
No Matches
hashmap.h
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the Apache License, Version 2.0 (the "Apache License")
5// with the following modification; you may not use this file except in
6// compliance with the Apache License and the following modification to it:
7// Section 6. Trademarks. is deleted and replaced with:
8//
9// 6. Trademarks. This License does not grant permission to use the trade
10// names, trademarks, service marks, or product names of the Licensor
11// and its affiliates, except as required to comply with Section 4(c) of
12// the License and to reproduce the content of the NOTICE file.
13//
14// You may obtain a copy of the Apache License at
15//
16// http://www.apache.org/licenses/LICENSE-2.0
17//
18// Unless required by applicable law or agreed to in writing, software
19// distributed under the Apache License with the above modification is
20// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21// KIND, either express or implied. See the Apache License for the specific
22// language governing permissions and limitations under the Apache License.
23//
24// Wrap one of various unordered map implementations. The exposed API
25// is similar to std::unordered_map but is missing some methods and
26// erase(const_iterator) returns nothing.
27//
28// Wrapping provides a convenient way to switch between implementations.
29// The GNU extension (currently) has the best overall performance but
30// isn't standard. Otherwise we use the C++11 standard implementation.
31
32#ifndef PXR_BASE_TF_HASHMAP_H
33#define PXR_BASE_TF_HASHMAP_H
34
35#include "pxr/pxr.h"
36#include "pxr/base/arch/defines.h"
37
38#if defined(ARCH_HAS_GNU_STL_EXTENSIONS)
39#include <ext/hash_map>
40#else
41#include <unordered_map>
42#endif // ARCH_HAS_GNU_STL_EXTENSIONS
43
44PXR_NAMESPACE_OPEN_SCOPE
45
46#if defined(ARCH_HAS_GNU_STL_EXTENSIONS)
47
48template<class Key, class Mapped, class HashFn = __gnu_cxx::hash<Key>,
49 class EqualKey = __gnu_cxx::equal_to<Key>,
50 class Alloc = __gnu_cxx::allocator<Mapped> >
51class TfHashMap :
52 private __gnu_cxx::hash_map<Key, Mapped, HashFn, EqualKey, Alloc> {
53 typedef __gnu_cxx::hash_map<Key, Mapped, HashFn, EqualKey, Alloc> _Base;
54public:
55 typedef typename _Base::key_type key_type;
56 typedef typename _Base::mapped_type mapped_type;
57 typedef typename _Base::value_type value_type;
58 typedef typename _Base::hasher hasher;
59 typedef typename _Base::key_equal key_equal;
60 typedef typename _Base::size_type size_type;
61 typedef typename _Base::difference_type difference_type;
62 typedef typename _Base::pointer pointer;
63 typedef typename _Base::const_pointer const_pointer;
64 typedef typename _Base::reference reference;
65 typedef typename _Base::const_reference const_reference;
66 typedef typename _Base::iterator iterator;
67 typedef typename _Base::const_iterator const_iterator;
68 typedef typename _Base::allocator_type allocator_type;
69 // No local_iterator nor any methods using them.
70
71 TfHashMap() : _Base() { }
72 explicit
73 TfHashMap(size_type n, const hasher& hf = hasher(),
74 const key_equal& eql = key_equal(),
75 const allocator_type& alloc = allocator_type()) :
76 _Base(n, hf, eql, alloc) { }
77 explicit
78 TfHashMap(const allocator_type& alloc) :
79 _Base(0, hasher(), key_equal(), alloc) { }
80 template<class InputIterator>
81 TfHashMap(InputIterator first, InputIterator last,
82 size_type n = 0, const hasher& hf = hasher(),
83 const key_equal& eql = key_equal(),
84 const allocator_type& alloc = allocator_type()) :
85 _Base(first, last, n, hf, eql, alloc) { }
86 TfHashMap(const TfHashMap& other) : _Base(other) { }
87
88 TfHashMap& operator=(const TfHashMap& rhs) {
89 _Base::operator=(rhs);
90 return *this;
91 }
92
93 iterator begin() { return _Base::begin(); }
94 const_iterator begin() const { return const_iterator(_Base::begin()); }
95 // size_type bucket(const key_type& key) const;
96 using _Base::bucket_count;
97 size_type bucket_size(size_type n) const { return _Base::elems_in_bucket(n); }
98 const_iterator cbegin() const { return const_iterator(_Base::begin()); }
99 const_iterator cend() const { return const_iterator(_Base::end()); }
100 using _Base::clear;
101 using _Base::count;
102 using _Base::empty;
103 iterator end() { return _Base::end(); }
104 const_iterator end() const { return const_iterator(_Base::end()); }
105 std::pair<iterator,iterator> equal_range(const key_type& key) {
106 return _Base::equal_range(key);
107 }
108 std::pair<const_iterator,const_iterator> equal_range(const key_type& key) const {
109 return _Base::equal_range(key);
110 }
111 size_type erase(const key_type& key) { return _Base::erase(key); }
112 void erase(const_iterator position) {
113 _Base::erase(_MakeIterator(position));
114 }
115 void erase(const_iterator first, const_iterator last) {
116 _Base::erase(_MakeIterator(first), _MakeIterator(last));
117 }
118 iterator find(const key_type& key) { return _Base::find(key); }
119 const_iterator find(const key_type& key) const {
120 return const_iterator(_Base::find(key));
121 }
122 using _Base::get_allocator;
123 hasher hash_function() const { return _Base::hash_funct(); }
124 using _Base::insert;
125 iterator insert(const_iterator, const value_type& v) {
126 return insert(v).first;
127 }
128 using _Base::key_eq;
129 float load_factor() const {
130 return static_cast<float>(static_cast<double>(size()) / bucket_count());
131 }
132 using _Base::max_bucket_count;
133 float max_load_factor() const { return 1.0; }
134 // void max_load_factor(float) { }
135 using _Base::max_size;
136 void rehash(size_type n) { _Base::resize(__gnu_cxx::__stl_next_prime(n)); }
137 void reserve(size_type n) { _Base::resize(n); }
138 using _Base::size;
139 void swap(TfHashMap& other) { _Base::swap(other); }
140 mapped_type& operator[](const key_type& k) { return _Base::operator[](k); }
141
142 template<class Key2, class Mapped2, class HashFn2, class EqualKey2, class Alloc2>
143 friend bool
144 operator==(const TfHashMap<Key2, Mapped2, HashFn2, EqualKey2, Alloc2>&,
145 const TfHashMap<Key2, Mapped2, HashFn2, EqualKey2, Alloc2>&);
146
147private:
148 // _Base::erase() takes an iterator, not a const_iterator. We happen
149 // to know const_iterator and iterator have the same layout.
150 static const iterator& _MakeIterator(const const_iterator& i) {
151 return reinterpret_cast<const iterator&>(i);
152 }
153};
154
155template<class Key, class Mapped, class HashFn = __gnu_cxx::hash<Key>,
156 class EqualKey = __gnu_cxx::equal_to<Key>,
157 class Alloc = __gnu_cxx::allocator<Mapped> >
158class TfHashMultiMap :
159 private __gnu_cxx::hash_multimap<Key, Mapped, HashFn, EqualKey, Alloc> {
160 typedef __gnu_cxx::hash_multimap<Key, Mapped, HashFn, EqualKey, Alloc> _Base;
161public:
162 typedef typename _Base::key_type key_type;
163 typedef typename _Base::mapped_type mapped_type;
164 typedef typename _Base::value_type value_type;
165 typedef typename _Base::hasher hasher;
166 typedef typename _Base::key_equal key_equal;
167 typedef typename _Base::size_type size_type;
168 typedef typename _Base::difference_type difference_type;
169 typedef typename _Base::pointer pointer;
170 typedef typename _Base::const_pointer const_pointer;
171 typedef typename _Base::reference reference;
172 typedef typename _Base::const_reference const_reference;
173 typedef typename _Base::iterator iterator;
174 typedef typename _Base::const_iterator const_iterator;
175 typedef typename _Base::allocator_type allocator_type;
176 // No local_iterator nor any methods using them.
177
178 TfHashMultiMap() : _Base() { }
179 explicit
180 TfHashMultiMap(size_type n, const hasher& hf = hasher(),
181 const key_equal& eql = key_equal(),
182 const allocator_type& alloc = allocator_type()) :
183 _Base(n, hf, eql, alloc) { }
184 explicit
185 TfHashMultiMap(const allocator_type& alloc) :
186 _Base(0, hasher(), key_equal(), alloc) { }
187 template<class InputIterator>
188 TfHashMultiMap(InputIterator first, InputIterator last,
189 size_type n = 0, const hasher& hf = hasher(),
190 const key_equal& eql = key_equal(),
191 const allocator_type& alloc = allocator_type()) :
192 _Base(first, last, n, hf, eql, alloc) { }
193 TfHashMultiMap(const TfHashMultiMap& other) : _Base(other) { }
194
195 TfHashMultiMap& operator=(const TfHashMultiMap& rhs) {
196 _Base::operator=(rhs);
197 return *this;
198 }
199
200 iterator begin() { return _Base::begin(); }
201 const_iterator begin() const { return const_iterator(_Base::begin()); }
202 // size_type bucket(const key_type& key) const;
203 using _Base::bucket_count;
204 size_type bucket_size(size_type n) const { return _Base::elems_in_bucket(n); }
205 const_iterator cbegin() const { return const_iterator(_Base::begin()); }
206 const_iterator cend() const { return const_iterator(_Base::end()); }
207 using _Base::clear;
208 using _Base::count;
209 using _Base::empty;
210 iterator end() { return _Base::end(); }
211 const_iterator end() const { return const_iterator(_Base::end()); }
212 std::pair<iterator,iterator> equal_range(const key_type& key) {
213 return _Base::equal_range(key);
214 }
215 std::pair<const_iterator,const_iterator> equal_range(const key_type& key) const {
216 return _Base::equal_range(key);
217 }
218 size_type erase(const key_type& key) { return _Base::erase(key); }
219 void erase(const_iterator position) {
220 _Base::erase(_MakeIterator(position));
221 }
222 void erase(const_iterator first, const_iterator last) {
223 _Base::erase(_MakeIterator(first), _MakeIterator(last));
224 }
225 iterator find(const key_type& key) { return _Base::find(key); }
226 const_iterator find(const key_type& key) const {
227 return const_iterator(_Base::find(key));
228 }
229 using _Base::get_allocator;
230 hasher hash_function() const { return _Base::hash_funct(); }
231 using _Base::insert;
232 iterator insert(const_iterator, const value_type& v) {
233 return insert(v).first;
234 }
235 using _Base::key_eq;
236 float load_factor() const {
237 return static_cast<float>(static_cast<double>(size()) / bucket_count());
238 }
239 using _Base::max_bucket_count;
240 float max_load_factor() const { return 1.0; }
241 // void max_load_factor(float) { }
242 using _Base::max_size;
243 void rehash(size_type n) { _Base::resize(__gnu_cxx::__stl_next_prime(n)); }
244 void reserve(size_type n) { _Base::resize(n); }
245 using _Base::size;
246 void swap(TfHashMultiMap& other) { _Base::swap(other); }
247 mapped_type& operator[](const key_type& k) { return _Base::operator[](k); }
248
249 template<class Key2, class Mapped2, class HashFn2, class EqualKey2, class Alloc2>
250 friend bool
251 operator==(const TfHashMap<Key2, Mapped2, HashFn2, EqualKey2, Alloc2>&,
252 const TfHashMap<Key2, Mapped2, HashFn2, EqualKey2, Alloc2>&);
253
254private:
255 // _Base::erase() takes an iterator, not a const_iterator. We happen
256 // to know const_iterator and iterator have the same layout.
257 static const iterator& _MakeIterator(const const_iterator& i) {
258 return reinterpret_cast<const iterator&>(i);
259 }
260};
261
262#else
263
264template<class Key, class Mapped, class HashFn = std::hash<Key>,
265 class EqualKey = std::equal_to<Key>,
266 class Alloc = std::allocator<std::pair<const Key, Mapped> > >
267class TfHashMap :
268 private std::unordered_map<Key, Mapped, HashFn, EqualKey, Alloc> {
269 typedef std::unordered_map<Key, Mapped, HashFn, EqualKey, Alloc> _Base;
270public:
271 typedef typename _Base::key_type key_type;
272 typedef typename _Base::mapped_type mapped_type;
273 typedef typename _Base::value_type value_type;
274 typedef typename _Base::hasher hasher;
275 typedef typename _Base::key_equal key_equal;
276 typedef typename _Base::size_type size_type;
277 typedef typename _Base::difference_type difference_type;
278 typedef typename _Base::pointer pointer;
279 typedef typename _Base::const_pointer const_pointer;
280 typedef typename _Base::reference reference;
281 typedef typename _Base::const_reference const_reference;
282 typedef typename _Base::iterator iterator;
283 typedef typename _Base::const_iterator const_iterator;
284 typedef typename _Base::allocator_type allocator_type;
285 // No local_iterator nor any methods using them.
286
287 TfHashMap() : _Base() { }
288 explicit
289 TfHashMap(size_type n, const hasher& hf = hasher(),
290 const key_equal& eql = key_equal(),
291 const allocator_type& alloc = allocator_type()) :
292 _Base(n, hf, eql, alloc) { }
293 explicit
294 TfHashMap(const allocator_type& alloc) : _Base(alloc) { }
295 template<class InputIterator>
296 TfHashMap(InputIterator first, InputIterator last,
297 size_type n = 0, const hasher& hf = hasher(),
298 const key_equal& eql = key_equal(),
299 const allocator_type& alloc = allocator_type()) :
300 _Base(first, last, n, hf, eql, alloc) { }
301 TfHashMap(const TfHashMap& other) : _Base(other) { }
302
303 TfHashMap& operator=(const TfHashMap& rhs) {
304 _Base::operator=(rhs);
305 return *this;
306 }
307
308 iterator begin() { return _Base::begin(); }
309 const_iterator begin() const { return _Base::begin(); }
310 // using _Base::bucket;
311 using _Base::bucket_count;
312 using _Base::bucket_size;
313 const_iterator cbegin() const { return _Base::cbegin(); }
314 const_iterator cend() const { return _Base::cend(); }
315 using _Base::clear;
316 using _Base::count;
317 using _Base::empty;
318 iterator end() { return _Base::end(); }
319 const_iterator end() const { return _Base::end(); }
320 using _Base::equal_range;
321 size_type erase(const key_type& key) { return _Base::erase(key); }
322 void erase(const_iterator position) { _Base::erase(position); }
323 void erase(const_iterator first, const_iterator last) {
324 _Base::erase(first, last);
325 }
326 using _Base::find;
327 using _Base::get_allocator;
328 using _Base::hash_function;
329 std::pair<iterator, bool> insert(const value_type& v) {
330 return _Base::insert(v);
331 }
332 iterator insert(const_iterator hint, const value_type& v) {
333 return _Base::insert(hint, v);
334 }
335 template<class InputIterator>
336 void insert(InputIterator first, InputIterator last) {
337 _Base::insert(first, last);
338 }
339 using _Base::key_eq;
340 using _Base::load_factor;
341 using _Base::max_bucket_count;
342 using _Base::max_load_factor;
343 // using _Base::max_load_factor;
344 using _Base::max_size;
345 using _Base::rehash;
346 using _Base::reserve;
347 using _Base::size;
348 void swap(TfHashMap& other) { _Base::swap(other); }
349 mapped_type& operator[](const key_type& k) { return _Base::operator[](k); }
350
351 template<class Key2, class Mapped2, class HashFn2, class EqualKey2, class Alloc2>
352 friend bool
353 operator==(const TfHashMap<Key2, Mapped2, HashFn2, EqualKey2, Alloc2>&,
354 const TfHashMap<Key2, Mapped2, HashFn2, EqualKey2, Alloc2>&);
355};
356
357template<class Key, class Mapped, class HashFn = std::hash<Key>,
358 class EqualKey = std::equal_to<Key>,
359 class Alloc = std::allocator<std::pair<const Key, Mapped> > >
360class TfHashMultiMap :
361 private std::unordered_multimap<Key, Mapped, HashFn, EqualKey, Alloc> {
362 typedef std::unordered_multimap<Key, Mapped, HashFn, EqualKey, Alloc> _Base;
363public:
364 typedef typename _Base::key_type key_type;
365 typedef typename _Base::mapped_type mapped_type;
366 typedef typename _Base::value_type value_type;
367 typedef typename _Base::hasher hasher;
368 typedef typename _Base::key_equal key_equal;
369 typedef typename _Base::size_type size_type;
370 typedef typename _Base::difference_type difference_type;
371 typedef typename _Base::pointer pointer;
372 typedef typename _Base::const_pointer const_pointer;
373 typedef typename _Base::reference reference;
374 typedef typename _Base::const_reference const_reference;
375 typedef typename _Base::iterator iterator;
376 typedef typename _Base::const_iterator const_iterator;
377 typedef typename _Base::allocator_type allocator_type;
378 // No local_iterator nor any methods using them.
379
380 TfHashMultiMap() : _Base() { }
381 explicit
382 TfHashMultiMap(size_type n, const hasher& hf = hasher(),
383 const key_equal& eql = key_equal(),
384 const allocator_type& alloc = allocator_type()) :
385 _Base(n, hf, eql, alloc) { }
386 explicit
387 TfHashMultiMap(const allocator_type& alloc) : _Base(alloc) { }
388 template<class InputIterator>
389 TfHashMultiMap(InputIterator first, InputIterator last,
390 size_type n = 0, const hasher& hf = hasher(),
391 const key_equal& eql = key_equal(),
392 const allocator_type& alloc = allocator_type()) :
393 _Base(first, last, n, hf, eql, alloc) { }
394 TfHashMultiMap(const TfHashMultiMap& other) : _Base(other) { }
395
396 TfHashMultiMap& operator=(const TfHashMultiMap& rhs) {
397 _Base::operator=(rhs);
398 return *this;
399 }
400
401 iterator begin() { return _Base::begin(); }
402 const_iterator begin() const { return _Base::begin(); }
403 // using _Base::bucket;
404 using _Base::bucket_count;
405 using _Base::bucket_size;
406 const_iterator cbegin() const { return _Base::cbegin(); }
407 const_iterator cend() const { return _Base::cend(); }
408 using _Base::clear;
409 using _Base::count;
410 using _Base::empty;
411 iterator end() { return _Base::end(); }
412 const_iterator end() const { return _Base::end(); }
413 using _Base::equal_range;
414 size_type erase(const key_type& key) { return _Base::erase(key); }
415 void erase(const_iterator position) { _Base::erase(position); }
416 void erase(const_iterator first, const_iterator last) {
417 _Base::erase(first, last);
418 }
419 using _Base::find;
420 using _Base::get_allocator;
421 using _Base::hash_function;
422 iterator insert(const value_type& v) {
423 return _Base::insert(v);
424 }
425 iterator insert(const_iterator hint, const value_type& v) {
426 return _Base::insert(hint, v);
427 }
428 template<class InputIterator>
429 void insert(InputIterator first, InputIterator last) {
430 _Base::insert(first, last);
431 }
432 using _Base::key_eq;
433 using _Base::load_factor;
434 using _Base::max_bucket_count;
435 using _Base::max_load_factor;
436 // using _Base::max_load_factor;
437 using _Base::max_size;
438 using _Base::rehash;
439 using _Base::reserve;
440 using _Base::size;
441 void swap(TfHashMultiMap& other) { _Base::swap(other); }
442 mapped_type& operator[](const key_type& k) { return _Base::operator[](k); }
443
444 template<class Key2, class Mapped2, class HashFn2, class EqualKey2, class Alloc2>
445 friend bool
446 operator==(const TfHashMap<Key2, Mapped2, HashFn2, EqualKey2, Alloc2>&,
447 const TfHashMap<Key2, Mapped2, HashFn2, EqualKey2, Alloc2>&);
448};
449
450#endif // ARCH_HAS_GNU_STL_EXTENSIONS
451
452template<class Key, class Mapped, class HashFn, class EqualKey, class Alloc>
453inline void
454swap(TfHashMap<Key, Mapped, HashFn, EqualKey, Alloc>& lhs,
455 TfHashMap<Key, Mapped, HashFn, EqualKey, Alloc>& rhs)
456{
457 lhs.swap(rhs);
458}
459
460template<class Key, class Mapped, class HashFn, class EqualKey, class Alloc>
461inline bool
462operator==(const TfHashMap<Key, Mapped, HashFn, EqualKey, Alloc>& lhs,
463 const TfHashMap<Key, Mapped, HashFn, EqualKey, Alloc>& rhs)
464{
465 typedef typename TfHashMap<Key, Mapped, HashFn, EqualKey, Alloc>::_Base _Base;
466 return static_cast<const _Base&>(lhs) == static_cast<const _Base&>(rhs);
467}
468
469template<class Key, class Mapped, class HashFn, class EqualKey, class Alloc>
470inline bool
471operator!=(const TfHashMap<Key, Mapped, HashFn, EqualKey, Alloc>& lhs,
472 const TfHashMap<Key, Mapped, HashFn, EqualKey, Alloc>& rhs)
473{
474 return !(lhs == rhs);
475}
476
477template<class Key, class Mapped, class HashFn, class EqualKey, class Alloc>
478inline void
479swap(TfHashMultiMap<Key, Mapped, HashFn, EqualKey, Alloc>& lhs,
480 TfHashMultiMap<Key, Mapped, HashFn, EqualKey, Alloc>& rhs)
481{
482 lhs.swap(rhs);
483}
484
485template<class Key, class Mapped, class HashFn, class EqualKey, class Alloc>
486inline bool
487operator==(const TfHashMultiMap<Key, Mapped, HashFn, EqualKey, Alloc>& lhs,
488 const TfHashMultiMap<Key, Mapped, HashFn, EqualKey, Alloc>& rhs)
489{
490 typedef typename TfHashMultiMap<Key, Mapped, HashFn, EqualKey, Alloc>::_Base _Base;
491 return static_cast<const _Base&>(lhs) == static_cast<const _Base&>(rhs);
492}
493
494template<class Key, class Mapped, class HashFn, class EqualKey, class Alloc>
495inline bool
496operator!=(const TfHashMultiMap<Key, Mapped, HashFn, EqualKey, Alloc>& lhs,
497 const TfHashMultiMap<Key, Mapped, HashFn, EqualKey, Alloc>& rhs)
498{
499 return !(lhs == rhs);
500}
501
502PXR_NAMESPACE_CLOSE_SCOPE
503
504#endif // PXR_BASE_TF_HASHMAP_H