Visual Studio 2012 Support
[xy_vsfilter.git] / src / thirdparty / VirtualDub / h / vd2 / system / vdstl_hashmap.h
blobe891e4d8d598f881d06307c2bc29038ed9e3e002
1 // VirtualDub - Video processing and capture application
2 // System library component
3 // Copyright (C) 1998-2010 Avery Lee, All Rights Reserved.
4 //
5 // Beginning with 1.6.0, the VirtualDub system library is licensed
6 // differently than the remainder of VirtualDub. This particular file is
7 // thus licensed as follows (the "zlib" license):
8 //
9 // This software is provided 'as-is', without any express or implied
10 // warranty. In no event will the authors be held liable for any
11 // damages arising from the use of this software.
13 // Permission is granted to anyone to use this software for any purpose,
14 // including commercial applications, and to alter it and redistribute it
15 // freely, subject to the following restrictions:
17 // 1. The origin of this software must not be misrepresented; you must
18 // not claim that you wrote the original software. If you use this
19 // software in a product, an acknowledgment in the product
20 // documentation would be appreciated but is not required.
21 // 2. Altered source versions must be plainly marked as such, and must
22 // not be misrepresented as being the original software.
23 // 3. This notice may not be removed or altered from any source
24 // distribution.
26 #ifndef f_VD2_SYSTEM_VDSTL_HASHMAP_H
27 #define f_VD2_SYSTEM_VDSTL_HASHMAP_H
29 #include <vd2/system/vdstl_hash.h>
30 #include <vd2/system/vdstl_hashtable.h>
31 #include <functional>
33 template<class K, class V, class Hash = vdhash<K>, class Pred = std::equal_to<K>, class A = std::allocator<vdhashtable_node<std::pair<K, V> > > >
34 class vdhashmap : public vdhashtable<std::pair<K, V> > {
35 protected:
36 using vdhashtable<std::pair<K, V> >::mpBucketStart;
37 using vdhashtable<std::pair<K, V> >::mpBucketEnd;
38 using vdhashtable<std::pair<K, V> >::mBucketCount;
39 using vdhashtable<std::pair<K, V> >::mElementCount;
40 using vdhashtable<std::pair<K, V> >::sEmptyBucket;
42 public:
43 typedef typename vdhashtable<std::pair<K, V> >::node_type node_type;
44 typedef typename vdhashtable<std::pair<K, V> >::value_type value_type;
45 typedef typename vdhashtable<std::pair<K, V> >::size_type size_type;
46 typedef typename vdhashtable<std::pair<K, V> >::difference_type difference_type;
47 typedef typename vdhashtable<std::pair<K, V> >::pointer pointer;
48 typedef typename vdhashtable<std::pair<K, V> >::const_pointer const_pointer;
49 typedef typename vdhashtable<std::pair<K, V> >::reference reference;
50 typedef typename vdhashtable<std::pair<K, V> >::const_reference const_reference;
51 typedef typename vdhashtable<std::pair<K, V> >::iterator iterator;
52 typedef typename vdhashtable<std::pair<K, V> >::const_iterator const_iterator;
53 typedef typename vdhashtable<std::pair<K, V> >::local_iterator local_iterator;
54 typedef typename vdhashtable<std::pair<K, V> >::const_local_iterator const_local_iterator;
55 typedef K key_type;
56 typedef V mapped_type;
57 typedef Hash hasher;
58 typedef Pred key_equal;
59 typedef A allocator_type;
60 typedef std::pair<iterator, bool> insert_return_type;
62 vdhashmap();
63 vdhashmap(const vdhashmap&);
64 ~vdhashmap();
66 vdhashmap& operator=(const vdhashmap&);
68 mapped_type& operator[](const K& key);
70 allocator_type get_allocator() const;
72 // iterators
73 using vdhashtable<value_type>::begin;
74 using vdhashtable<value_type>::end;
75 // iterator begin(); Inherited.
76 // const_iterator begin() const; Inherited.
77 // iterator end(); Inherited.
78 // const_iterator end() const; Inherited.
80 // modifiers
81 insert_return_type insert(const key_type& key);
82 insert_return_type insert(const std::pair<K, V>& obj);
83 // iterator insert(iterator hint, const value_type& obj); // TODO
84 // const_iterator insert(const_iterator hint, const value_type& obj); // TODO
86 template<class U>
87 insert_return_type insert_as(const U& k); // extension
89 iterator erase(iterator position);
90 const_iterator erase(const_iterator position);
91 size_type erase(const key_type& k);
92 // iterator erase(iterator first, iterator last); // TODO
93 // const_iterator erase(const_iterator first, const_iterator last); // TODO
94 void clear();
96 // observers
97 hasher hash_function() const;
98 key_equal key_eq() const;
100 // lookup
101 iterator find(const key_type& k);
102 const_iterator find(const key_type& k) const;
103 size_type count(const key_type& k) const;
104 std::pair<iterator, iterator> equal_range(const key_type& k);
105 std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
107 // lookup (extensions)
108 template<class U>
109 iterator find_as(const U& k);
111 template<class U>
112 const_iterator find_as(const U& k) const;
114 // bucket interface
115 // size_type bucket_count() const; Inherited.
116 // size_type max_bucket_count() const; Inherited.
117 // size_type bucket_size(size_type n) const; Inherited.
118 size_type bucket(const key_type& k) const;
119 local_iterator begin(size_type n);
120 const_local_iterator begin(size_type n) const;
121 local_iterator end(size_type n);
122 const_local_iterator end(size_type n) const;
124 // hash policy
125 // float load_factor() const; // TODO
126 // float max_load_factor() const; // TODO
127 // void max_load_factor(float z); // TODO
128 void rehash(size_type n);
130 protected:
131 void rehash_to_size(size_type n);
132 void reset();
134 A mAllocator;
135 typename A::template rebind<vdhashtable_base_node *>::other mBucketAllocator;
136 Hash mHasher;
137 Pred mPred;
140 template<class K, class V, class Hash, class Pred, class A>
141 vdhashmap<K, V, Hash, Pred, A>::vdhashmap() {
144 template<class K, class V, class Hash, class Pred, class A>
145 vdhashmap<K, V, Hash, Pred, A>::vdhashmap(const vdhashmap& src)
146 : mHasher(src.mHasher)
147 , mPred(src.mPred)
149 rehash_to_size(src.mElementCount);
151 try {
152 for(vdhashtable_base_node **bucket = mpBucketStart; bucket != mpBucketEnd; ++bucket) {
153 vdhashtable_base_node *p = *bucket;
155 while(p) {
156 vdhashtable_base_node *next = p->mpHashNext;
157 node_type *node = static_cast<node_type *>(p);
159 insert(node->mData);
161 p = next;
164 *bucket = NULL;
166 } catch(...) {
167 reset();
168 throw;
172 template<class K, class V, class Hash, class Pred, class A>
173 vdhashmap<K, V, Hash, Pred, A>::~vdhashmap() {
174 reset();
177 template<class K, class V, class Hash, class Pred, class A>
178 vdhashmap<K, V, Hash, Pred, A>& vdhashmap<K, V, Hash, Pred, A>::operator=(const vdhashmap& src) {
179 if (&src != this) {
180 clear();
182 mHasher = src.mHasher;
183 mPred = src.mPred;
185 for(vdhashtable_base_node **bucket = src.mpBucketStart; bucket != src.mpBucketEnd; ++bucket) {
186 vdhashtable_base_node *p = *bucket;
188 while(p) {
189 vdhashtable_base_node *next = p->mpHashNext;
190 node_type *node = static_cast<node_type *>(p);
192 insert(node->mData);
194 p = next;
197 *bucket = NULL;
201 return *this;
204 template<class K, class V, class Hash, class Pred, class A>
205 typename vdhashmap<K, V, Hash, Pred, A>::mapped_type& vdhashmap<K, V, Hash, Pred, A>::operator[](const K& key) {
206 return insert(key).first->second;
209 template<class K, class V, class Hash, class Pred, class A>
210 typename vdhashmap<K, V, Hash, Pred, A>::allocator_type vdhashmap<K, V, Hash, Pred, A>::get_allocator() const {
211 return A();
214 // modifiers
215 template<class K, class V, class Hash, class Pred, class A>
216 typename vdhashmap<K, V, Hash, Pred, A>::insert_return_type vdhashmap<K, V, Hash, Pred, A>::insert(const key_type& key) {
217 if (mElementCount >= mBucketCount)
218 rehash_to_size(mElementCount + 1);
220 size_type bucket = mHasher(key) % mBucketCount;
222 for(node_type *p = static_cast<node_type *>(mpBucketStart[bucket]); p; p = static_cast<node_type *>(p->mpHashNext)) {
223 if (mPred(p->mData.first, key))
224 return std::pair<iterator, bool>(iterator(p, &mpBucketStart[bucket], mpBucketEnd), false);
227 node_type *node = mAllocator.allocate(1);
228 try {
229 new(node) node_type(static_cast<node_type *>(mpBucketStart[bucket]), value_type(key, V()));
230 } catch(...) {
231 mAllocator.deallocate(node, 1);
232 throw;
235 mpBucketStart[bucket] = node;
236 ++mElementCount;
238 return std::pair<iterator, bool>(iterator(node, &mpBucketStart[bucket], mpBucketEnd), true);
241 template<class K, class V, class Hash, class Pred, class A>
242 typename vdhashmap<K, V, Hash, Pred, A>::insert_return_type vdhashmap<K, V, Hash, Pred, A>::insert(const std::pair<K, V>& obj) {
243 if (mElementCount >= mBucketCount)
244 rehash_to_size(mElementCount + 1);
246 size_type bucket = mHasher(obj.first) % mBucketCount;
248 for(node_type *p = static_cast<node_type *>(mpBucketStart[bucket]); p; p = static_cast<node_type *>(p->mpHashNext)) {
249 if (mPred(p->mData.first, obj.first))
250 return std::pair<iterator, bool>(iterator(p, &mpBucketStart[bucket], mpBucketEnd), false);
253 node_type *node = mAllocator.allocate(1);
254 try {
255 new(node) node_type(static_cast<node_type *>(mpBucketStart[bucket]), obj);
256 } catch(...) {
257 mAllocator.deallocate(node, 1);
258 throw;
261 mpBucketStart[bucket] = node;
262 ++mElementCount;
264 return std::pair<iterator, bool>(iterator(node, &mpBucketStart[bucket], mpBucketEnd), true);
267 template<class K, class V, class Hash, class Pred, class A>
268 template<class U>
269 typename vdhashmap<K, V, Hash, Pred, A>::insert_return_type vdhashmap<K, V, Hash, Pred, A>::insert_as(const U& key) {
270 if (mElementCount >= mBucketCount)
271 rehash_to_size(mElementCount + 1);
273 size_type bucket = mHasher(key) % mBucketCount;
275 for(node_type *p = static_cast<node_type *>(mpBucketStart[bucket]); p; p = static_cast<node_type *>(p->mpHashNext)) {
276 if (mPred(p->mData.first, key))
277 return std::pair<iterator, bool>(iterator(p, &mpBucketStart[bucket], mpBucketEnd), false);
280 node_type *node = mAllocator.allocate(1);
281 try {
282 new(node) node_type(static_cast<node_type *>(mpBucketStart[bucket]));
284 try {
285 node->mData.first = key;
286 } catch(...) {
287 node->~node_type();
290 } catch(...) {
291 mAllocator.deallocate(node, 1);
292 throw;
295 mpBucketStart[bucket] = node;
296 ++mElementCount;
298 return std::pair<iterator, bool>(iterator(node, &mpBucketStart[bucket], mpBucketEnd), true);
301 template<class K, class V, class Hash, class Pred, class A>
302 typename vdhashmap<K, V, Hash, Pred, A>::iterator vdhashmap<K, V, Hash, Pred, A>::erase(iterator position) {
303 size_type bucket = mHasher(position->first) % mBucketCount;
304 vdhashtable_base_node *prev = NULL;
305 vdhashtable_base_node *p = mpBucketStart[bucket];
307 while(&static_cast<node_type *>(p)->mData != &*position) {
308 prev = p;
309 p = p->mpHashNext;
312 vdhashtable_base_node *next = p->mpHashNext;
313 if (prev)
314 prev->mpHashNext = next;
315 else
316 mpBucketStart[bucket] = next;
318 node_type *node = static_cast<node_type *>(p);
319 node->~node_type();
320 mAllocator.deallocate(node, 1);
321 --mElementCount;
323 return iterator(next, &mpBucketStart[bucket], mpBucketEnd);
326 template<class K, class V, class Hash, class Pred, class A>
327 typename vdhashmap<K, V, Hash, Pred, A>::const_iterator vdhashmap<K, V, Hash, Pred, A>::erase(const_iterator position) {
328 size_type bucket = mHasher(position->first) % mBucketCount;
329 vdhashtable_base_node *prev = NULL;
330 vdhashtable_base_node *p = mpBucketStart[bucket];
332 while(&static_cast<const node_type *>(p)->mData != &*position) {
333 prev = p;
334 p = p->mpHashNext;
337 vdhashtable_base_node *next = p->mpHashNext;
338 if (prev)
339 prev->mpHashNext = next;
340 else
341 mpBucketStart[bucket] = next;
343 node_type *node = static_cast<node_type *>(p);
344 node->~node_type();
345 mAllocator.deallocate(node, 1);
346 --mElementCount;
348 return const_iterator(next, &mpBucketStart[bucket], mpBucketEnd);
351 template<class K, class V, class Hash, class Pred, class A>
352 typename vdhashmap<K, V, Hash, Pred, A>::size_type vdhashmap<K, V, Hash, Pred, A>::erase(const key_type& k) {
353 if (!mBucketCount)
354 return 0;
356 size_type bucket = mHasher(k) % mBucketCount;
357 vdhashtable_base_node *prev = NULL;
358 vdhashtable_base_node *p = mpBucketStart[bucket];
360 while(p) {
361 node_type *node = static_cast<node_type *>(p);
363 if (mPred(node->mData.first, k)) {
364 vdhashtable_base_node *next = p->mpHashNext;
366 if (prev)
367 prev->mpHashNext = next;
368 else
369 mpBucketStart[bucket] = next;
371 node->~node_type();
372 mAllocator.deallocate(node, 1);
373 --mElementCount;
374 return 1;
377 prev = p;
378 p = p->mpHashNext;
381 return 0;
384 template<class K, class V, class Hash, class Pred, class A>
385 void vdhashmap<K, V, Hash, Pred, A>::clear() {
386 for(vdhashtable_base_node **bucket = mpBucketStart; bucket != mpBucketEnd; ++bucket) {
387 vdhashtable_base_node *p = *bucket;
389 while(p) {
390 vdhashtable_base_node *next = p->mpHashNext;
391 node_type *node = static_cast<node_type *>(p);
393 node->~node_type();
395 mAllocator.deallocate(node, 1);
397 p = next;
400 *bucket = NULL;
403 mElementCount = 0;
406 // observers
407 template<class K, class V, class Hash, class Pred, class A>
408 typename vdhashmap<K, V, Hash, Pred, A>::hasher vdhashmap<K, V, Hash, Pred, A>::hash_function() const {
409 return mHasher;
412 template<class K, class V, class Hash, class Pred, class A>
413 typename vdhashmap<K, V, Hash, Pred, A>::key_equal vdhashmap<K, V, Hash, Pred, A>::key_eq() const {
414 return mPred;
417 // lookup
418 template<class K, class V, class Hash, class Pred, class A>
419 typename vdhashmap<K, V, Hash, Pred, A>::iterator vdhashmap<K, V, Hash, Pred, A>::find(const key_type& k) {
420 if (!mBucketCount)
421 return iterator();
423 size_type bucket = mHasher(k) % mBucketCount;
425 for(vdhashtable_base_node *p = mpBucketStart[bucket]; p; p = p->mpHashNext) {
426 node_type *node = static_cast<node_type *>(p);
428 if (mPred(node->mData.first, k))
429 return iterator(node, &mpBucketStart[bucket], mpBucketEnd);
432 return iterator();
435 template<class K, class V, class Hash, class Pred, class A>
436 typename vdhashmap<K, V, Hash, Pred, A>::const_iterator vdhashmap<K, V, Hash, Pred, A>::find(const key_type& k) const {
437 if (!mBucketCount)
438 return iterator();
440 size_type bucket = mHasher(k) % mBucketCount;
442 for(const vdhashtable_base_node *p = mpBucketStart[bucket]; p; p = p->mpHashNext) {
443 const node_type *node = static_cast<const node_type *>(p);
445 if (mPred(node->mData.first, k))
446 return const_iterator(const_cast<vdhashtable_base_node *>(static_cast<const vdhashtable_base_node *>(node)), &mpBucketStart[bucket], mpBucketEnd);
449 return iterator();
452 template<class K, class V, class Hash, class Pred, class A>
453 typename vdhashmap<K, V, Hash, Pred, A>::size_type vdhashmap<K, V, Hash, Pred, A>::count(const key_type& k) const {
454 return find(k) != end() ? 1 : 0;
457 template<class K, class V, class Hash, class Pred, class A>
458 std::pair<typename vdhashmap<K, V, Hash, Pred, A>::iterator, typename vdhashmap<K, V, Hash, Pred, A>::iterator> vdhashmap<K, V, Hash, Pred, A>::equal_range(const key_type& k) {
459 iterator it = find(k);
460 iterator itEnd;
462 if (it == itEnd)
463 return std::make_pair(itEnd, itEnd);
465 itEnd = it;
466 ++itEnd;
468 return std::make_pair<it, itEnd>();
471 template<class K, class V, class Hash, class Pred, class A>
472 std::pair<typename vdhashmap<K, V, Hash, Pred, A>::const_iterator, typename vdhashmap<K, V, Hash, Pred, A>::const_iterator> vdhashmap<K, V, Hash, Pred, A>::equal_range(const key_type& k) const {
473 const_iterator it = find(k);
474 const_iterator itEnd;
476 if (it == itEnd)
477 return std::make_pair(itEnd, itEnd);
479 itEnd = it;
480 ++itEnd;
482 return std::make_pair(it, itEnd);
485 template<class K, class V, class Hash, class Pred, class A>
486 template<class U>
487 typename vdhashmap<K, V, Hash, Pred, A>::iterator vdhashmap<K, V, Hash, Pred, A>::find_as(const U& k) {
488 if (!mBucketCount)
489 return iterator();
491 size_type bucket = mHasher(k) % mBucketCount;
493 for(vdhashtable_base_node *p = mpBucketStart[bucket]; p; p = p->mpHashNext) {
494 node_type *node = static_cast<node_type *>(p);
496 if (mPred(node->mData.first, k))
497 return iterator(node, &mpBucketStart[bucket], mpBucketEnd);
500 return iterator();
503 template<class K, class V, class Hash, class Pred, class A>
504 template<class U>
505 typename vdhashmap<K, V, Hash, Pred, A>::const_iterator vdhashmap<K, V, Hash, Pred, A>::find_as(const U& k) const {
506 if (!mBucketCount)
507 return iterator();
509 size_type bucket = mHasher(k) % mBucketCount;
511 for(const vdhashtable_base_node *p = mpBucketStart[bucket]; p; p = p->mpHashNext) {
512 const node_type *node = static_cast<const node_type *>(p);
514 if (mPred(node->mData.first, k))
515 return const_iterator(const_cast<vdhashtable_base_node *>(static_cast<const vdhashtable_base_node *>(node)), &mpBucketStart[bucket], mpBucketEnd);
518 return iterator();
521 // bucket interface
522 template<class K, class V, class Hash, class Pred, class A>
523 typename vdhashmap<K, V, Hash, Pred, A>::size_type vdhashmap<K, V, Hash, Pred, A>::bucket(const key_type& k) const {
524 size_type bucket = 0;
526 if (mBucketCount)
527 bucket = mHasher(k) % mBucketCount;
529 return bucket;
532 template<class K, class V, class Hash, class Pred, class A>
533 typename vdhashmap<K, V, Hash, Pred, A>::local_iterator vdhashmap<K, V, Hash, Pred, A>::begin(size_type n) {
534 return local_iterator(mpBucketStart[n]);
537 template<class K, class V, class Hash, class Pred, class A>
538 typename vdhashmap<K, V, Hash, Pred, A>::const_local_iterator vdhashmap<K, V, Hash, Pred, A>::begin(size_type n) const {
539 return const_local_iterator(mpBucketStart[n]);
542 template<class K, class V, class Hash, class Pred, class A>
543 typename vdhashmap<K, V, Hash, Pred, A>::local_iterator vdhashmap<K, V, Hash, Pred, A>::end(size_type n) {
544 return local_iterator(NULL);
547 template<class K, class V, class Hash, class Pred, class A>
548 typename vdhashmap<K, V, Hash, Pred, A>::const_local_iterator vdhashmap<K, V, Hash, Pred, A>::end(size_type n) const {
549 return const_local_iterator(NULL);
552 // hash policy
553 template<class K, class V, class Hash, class Pred, class A>
554 void vdhashmap<K, V, Hash, Pred, A>::rehash(size_type n) {
555 if (!n)
556 n = 1;
558 if (mBucketCount == n)
559 return;
561 vdhashtable_base_node **newBuckets = mBucketAllocator.allocate(n + 1);
563 for(size_type i=0; i<=n; ++i)
564 newBuckets[i] = NULL;
566 const size_type m = mBucketCount;
567 for(size_type i=0; i<m; ++i) {
568 for(vdhashtable_base_node *p = mpBucketStart[i]; p;) {
569 vdhashtable_base_node *next = p->mpHashNext;
570 const value_type& vt = static_cast<vdhashtable_node<value_type> *>(p)->mData;
571 size_t bucket = mHasher(vt.first) % n;
573 vdhashtable_base_node *head = newBuckets[bucket];
575 p->mpHashNext = head;
576 newBuckets[bucket] = p;
578 p = next;
582 if (mpBucketStart != &sEmptyBucket)
583 mBucketAllocator.deallocate(mpBucketStart, (mpBucketEnd - mpBucketStart) + 1);
585 mpBucketStart = newBuckets;
586 mpBucketEnd = newBuckets + n;
587 mBucketCount = n;
590 template<class K, class V, class Hash, class Pred, class A>
591 void vdhashmap<K, V, Hash, Pred, A>::rehash_to_size(size_type n) {
592 size_type buckets = compute_bucket_count(n);
593 rehash(buckets);
596 template<class K, class V, class Hash, class Pred, class A>
597 void vdhashmap<K, V, Hash, Pred, A>::reset() {
598 clear();
600 if (mpBucketStart != &sEmptyBucket)
601 mBucketAllocator.deallocate(mpBucketStart, (mpBucketEnd - mpBucketStart) + 1);
604 #endif // f_VD2_SYSTEM_VDSTL_HASHMAP_H