Orfeo Toolbox  3.16
itk_hashtable.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itk_hashtable.h,v $
5  Language: C++
6  Date: $Date: 2010-04-26 14:31:25 $
7  Version: $Revision: 1.35 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
68 #ifndef __itk_hashtable_h
69 #define __itk_hashtable_h
70 
71 #if defined(_MSC_VER)
72 // unreachable code
73 #pragma warning ( disable : 4702 )
74 // assignment operator could not be generated
75 #pragma warning ( disable : 4512 )
76 #endif
77 
78 #if (defined(__GNUC__) && (((__GNUC__==3) && (__GNUC_MINOR__>=1) || (__GNUC__>3) ) || ( (__GNUC__==4) && defined(__INTEL_COMPILER) ) )) || (defined(__IBMCPP__) && __IBMCPP__ >= 600)
79 // Use this hashtable that is already define for GNU_C versions >= 3.1, IBMCPP >=600, or Intel compilers with GCCv4
80 
81 #else
82 
85 #include "itkMacro.h"
86 #include <iostream>
87 #include "itk_alloc.h"
88 #include <vector>
89 #include <utility>
90 #include <memory>
91 #include "vcl_compiler.h"
92 #include <functional>
93 #include <algorithm>
94 #include <iterator>
95 
96 
97 namespace itk
98 {
99 template <class Key> struct hash { };
100 
101 inline size_t hash_string(const char* s)
102 {
103  unsigned long h = 0;
104  for (; *s; ++s)
105  {
106  h = 5*h + *s;
107  }
108  return size_t(h);
109 }
110 
111 template<>
112 struct hash<char*>
113 {
114  size_t operator()(const char* s) const { return hash_string(s); }
115 };
116 
117 template<>
118 struct hash<const char*>
119 {
120  size_t operator()(const char* s) const { return hash_string(s); }
121 };
122 
123 template<>
124 struct hash<char>
125 {
126  size_t operator()(char x) const { return x; }
127 };
128 
129 template<>
130 struct hash<unsigned char>
131 {
132  size_t operator()(unsigned char x) const { return x; }
133 };
134 
135 template<>
136 struct hash<signed char>
137 {
138  size_t operator()(unsigned char x) const { return x; }
139 };
140 
141 template<>
142 struct hash<short>
143 {
144  size_t operator()(short x) const { return x; }
145 };
146 
147 template<>
148 struct hash<unsigned short>
149 {
150  size_t operator()(unsigned short x) const { return x; }
151 };
152 
153 template<>
154 struct hash<int>
155 {
156  size_t operator()(int x) const { return x; }
157 };
158 
159 template<>
160 struct hash<unsigned int>
161 {
162  size_t operator()(unsigned int x) const { return x; }
163 };
164 
165 template<>
166 struct hash<long>
167 {
168  size_t operator()(long x) const { return x; }
169 };
170 
171 template<>
172 struct hash<unsigned long>
173 {
174  size_t operator()(unsigned long x) const { return x; }
175 };
176 
177 #ifdef _WIN64
178 template<>
179 struct hash<size_t>
180 {
181  size_t operator()(size_t x) const { return x; }
182 };
183 #endif
184 
185 template <class Value>
187 {
188  typedef hashtable_node<Value> self;
189  self* next;
190  Value val;
191 };
192 
193 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey , VCL_DFL_TYPE_PARAM_STLDECL(Alloc,std::allocator<char>)>
194 class hashtable;
195 
196 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
197 struct hashtable_iterator;
198 
199 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
201 
202 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
204 {
206  typedef hashtable_iterator<Value, Key, HashFcn,
207  ExtractKey, EqualKey, Alloc> iterator;
208  typedef hashtable_const_iterator<Value, Key, HashFcn,
209  ExtractKey, EqualKey, Alloc>
212  typedef size_t size_type;
213  typedef Value& reference;
214  typedef Value* pointer;
215  typedef const Value& const_reference;
216 
219 
220  hashtable_iterator(node* n, hash_table* tab) : cur(n), ht(tab) {}
223  {
224  return cur->val;
225  }
226  pointer operator->() const { return &(operator*()); }
227 
228  IUEi_STL_INLINE iterator& operator++();
229  IUEi_STL_INLINE iterator operator++(int);
230  bool operator==(const iterator& it) const { return cur == it.cur; }
231  bool operator!=(const iterator& it) const { return cur != it.cur; }
232 };
233 
234 
235 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
237 {
240  typedef hashtable_iterator<Value, Key, HashFcn,
241  ExtractKey, EqualKey, Alloc> iterator;
242  typedef hashtable_const_iterator<Value, Key, HashFcn,
243  ExtractKey, EqualKey, Alloc> const_iterator;
245  typedef size_t size_type;
246  typedef Value& reference;
247  typedef const Value& const_reference;
248  typedef const Value* pointer;
249 
250  const node* cur;
251  const hash_table* ht;
252 
253  hashtable_const_iterator(const node* n, const hash_table* tab) : cur(n), ht(tab) {}
255  hashtable_const_iterator(const iterator& it) : cur(it.cur), ht(it.ht) {}
256 
257  const_reference operator*() const { return cur->val; }
258  pointer operator->() const { return &(operator*()); }
259  IUEi_STL_INLINE const_iterator& operator++();
260  IUEi_STL_INLINE const_iterator operator++(int);
261  bool operator==(const const_iterator& it) const { return cur == it.cur; }
262  bool operator!=(const const_iterator& it) const { return cur != it.cur; }
263 };
264 
265 // Note: assumes long is at least 32 bits.
266 // fbp: try to avoid intances in every module
267 enum { num_primes = 28 };
268 
269 #if ( __STL_STATIC_TEMPLATE_DATA > 0 ) && ! defined (WIN32)
270 # define prime_list prime<false>::list_
271 template <bool dummy>
272 struct prime {
273 public:
274  static const unsigned long list_[];
275 };
276 static const unsigned long prime_list_dummy[num_primes] =
277 # else
278 # if ( __STL_WEAK_ATTRIBUTE > 0 )
279  extern const unsigned long prime_list[num_primes] __attribute__((weak)) =
280 # else
281  // give up
282  static const unsigned long prime_list[num_primes] =
283 # endif /* __STL_WEAK_ATTRIBUTE */
284 #endif /* __STL_STATIC_TEMPLATE_DATA */
285 {
286  53, 97, 193, 389, 769,
287  1543, 3079, 6151, 12289, 24593,
288  49157, 98317, 196613, 393241, 786433,
289  1572869, 3145739, 6291469, 12582917, 25165843,
290  50331653, 100663319, 201326611, 402653189, 805306457,
291  1610612741, 3221225473U, 4294967291U
292 };
293 
294 inline unsigned long next_prime(unsigned long n)
295 {
296  const unsigned long* first = prime_list;
297  const unsigned long* last = prime_list;
298  last += num_primes;
299  const unsigned long* pos = std::lower_bound(first, last, n);
300  return pos == last ? *(last - 1) : *pos;
301 }
302 
303 template <class Value, class Alloc>
305 {
306 private:
307  typedef Value value_type;
308  typedef size_t size_type;
311 public: // These are public to get around restriction on protected access
312  typedef std::vector<VCL_SUNPRO_ALLOCATOR_HACK(node*) > buckets_type;
313  buckets_type buckets; // awf killed optional allocator
315 protected:
316  IUEi_STL_INLINE void clear();
317 
318  node* new_node(const value_type& obj)
319  {
321  try
322  {
323  new (&(n->val)) value_type(obj);
324  }
325  catch (...)
326  {
328  throw "";
329  }
330  n->next = 0;
331  return n;
332  }
333 
334  void delete_node(node* n)
335  {
336 #define vcli_destroy(T, p) ((T*)p)->~T()
337  vcli_destroy(Value, &(n->val));
338 #undef vcli_destroy
340  }
341 
342  IUEi_STL_INLINE void copy_from(const hashtable_base<Value,Alloc>& ht);
343 
344 public: // These are public to get around restriction on protected access
346 // hashtable_base(size_type n) : num_elements(0) {}
348 };
349 
350 
351 // forward declarations
352 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc> class hashtable;
353 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
354  bool operator== (hashtable<Value,Key,HashFcn,ExtractKey,EqualKey,Alloc>const&,hashtable<Value,Key,HashFcn,ExtractKey,EqualKey,Alloc>const&);
355 
356 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
357 class hashtable : protected hashtable_base<Value, Alloc>
358 {
361 public:
362  typedef Key key_type;
363  typedef Value value_type;
364  typedef HashFcn hasher;
365  typedef EqualKey key_equal;
366 
367  typedef size_t size_type;
368  typedef ptrdiff_t difference_type;
369  typedef value_type* pointer;
370  typedef const value_type* const_pointer;
372  typedef const value_type& const_reference;
373 
374  hasher hash_funct() const { return hashfun; }
375  key_equal key_eq() const { return equals; }
376 
377 private:
380  ExtractKey get_key;
381 
384 
385 public:
388  friend struct
390  friend struct
393 public:
395  const HashFcn& hf,
396  const EqualKey& eql,
397  const ExtractKey& ext)
398  : hashfun(hf), equals(eql), get_key(ext)
399  {
401  }
402 
404  const HashFcn& hf,
405  const EqualKey& eql)
406  : hashfun(hf), equals(eql), get_key(ExtractKey())
407  {
409  }
410 
411  hashtable(const self& ht)
412  : hashfun(ht.hashfun), equals(ht.equals), get_key(ht.get_key)
413  {
414  copy_from(ht);
415  }
416 
417  self& operator= (const self& ht)
418  {
419  if (&ht != this)
420  {
421  hashfun = ht.hashfun;
422  equals = ht.equals;
423  get_key = ht.get_key;
424  clear();
425  this->buckets.clear();
426  copy_from(ht);
427  }
428  return *this;
429  }
430 
433  size_type size() const { return this->num_elements; }
434  size_type max_size() const { return size_type(-1); }
435  bool empty() const { return size() == 0; }
436 
437  void swap(self& ht)
438  {
439  std::swap(hashfun, ht.hashfun);
440  std::swap(equals, ht.equals);
441  std::swap(get_key, ht.get_key);
442  this->buckets.swap(ht.buckets);
443  std::swap(this->num_elements, ht.num_elements);
444  }
445 
446  iterator begin()
447  {
448  for (size_type n = 0; n < this->buckets.size(); ++n)
449  {
450  if (this->buckets[n])
451  {
452  return iterator(this->buckets[n], this);
453  }
454  }
455  return end();
456  }
457 
458  iterator end() { return iterator((node*)0, this); }
459 
460  const_iterator begin() const
461  {
462  for (size_type n = 0; n < this->buckets.size(); ++n)
463  {
464  if (this->buckets[n])
465  {
466  return const_iterator(this->buckets[n], this);
467  }
468  }
469  return end();
470  }
471 
472  const_iterator end() const { return const_iterator((node*)0, this); }
473 
474 #if _MSC_VER != 1600
475  friend bool operator==ITK_FRIEND_TEMPLATE_FUNCTION_ARGUMENT(self)(const self&,const self&);
476 #endif
477 
478 public:
479 
480  size_type bucket_count() const { return this->buckets.size(); }
481 
483  { return prime_list[num_primes - 1]; }
484 
485  size_type elems_in_bucket(size_type bucket) const
486  {
487  size_type result = 0;
488  for (node* cur = this->buckets[bucket]; cur; cur = cur->next)
489  {
490  result += 1;
491  }
492  return result;
493  }
494 
495  std::pair<iterator, bool> insert_unique(const value_type& obj)
496  {
497  resize(this->num_elements + 1);
498  return insert_unique_noresize(obj);
499  }
500 
501  iterator insert_equal(const value_type& obj)
502  {
503  resize(this->num_elements + 1);
504  return insert_equal_noresize(obj);
505  }
506 
507  IUEi_STL_INLINE std::pair<iterator, bool> insert_unique_noresize(const value_type& obj);
508  IUEi_STL_INLINE iterator insert_equal_noresize(const value_type& obj);
509 
510  void insert_unique(const value_type* f, const value_type* l)
511  {
512  size_type n = l - f;
513  resize(this->num_elements + n);
514  for (; n > 0; --n)
515  {
517  }
518  }
519 
520  void insert_equal(const value_type* f, const value_type* l)
521  {
522  size_type n = l - f;
523  resize(this->num_elements + n);
524  for (; n > 0; --n)
525  {
526  insert_equal_noresize(*f++);
527  }
528  }
529 
531  {
532  size_type n = 0;
533  std::distance(f, l, n);
534  resize(this->num_elements + n);
535  for (; n > 0; --n)
536  {
538  }
539  }
540 
542  {
543  size_type n = 0;
544  std::distance(f, l, n);
545  resize(this->num_elements + n);
546  for (; n > 0; --n)
547  {
548  insert_equal_noresize(*f++);
549  }
550  }
551 
552  IUEi_STL_INLINE reference find_or_insert(const value_type& obj);
553 
554  iterator find(const key_type& key)
555  {
556  size_type n = bkt_num_key(key);
557  node* first;
558  for ( first = this->buckets[n];
559  first && !equals(get_key(first->val), key);
560  first = first->next)
561  {}
562  return iterator(first, this);
563  }
564 
565  const_iterator find(const key_type& key) const
566  {
567  size_type n = bkt_num_key(key);
568  const node* first;
569  for ( first = this->buckets[n];
570  first && !equals(get_key(first->val), key);
571  first = first->next)
572  {}
573  return const_iterator(first, this);
574  }
575 
576  size_type count(const key_type& key) const
577  {
578  const size_type n = bkt_num_key(key);
579  size_type result = 0;
580 
581  for (const node* cur = this->buckets[n]; cur; cur = cur->next)
582  {
583  if (equals(get_key(cur->val), key))
584  {
585  ++result;
586  }
587  }
588  return result;
589  }
590 
591  IUEi_STL_INLINE std::pair<iterator, iterator> equal_range(const key_type& key);
592  IUEi_STL_INLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const;
593 
594  IUEi_STL_INLINE size_type erase(const key_type& key);
595  IUEi_STL_INLINE void erase(const iterator& it);
596  IUEi_STL_INLINE void erase(iterator first, iterator last);
597 
598  IUEi_STL_INLINE void erase(const const_iterator& it);
599  IUEi_STL_INLINE void erase(const_iterator first, const_iterator last);
601  IUEi_STL_INLINE void resize(size_type num_elements_hint);
602  void clear() { super::clear(); }
603 private:
604  size_type next_size(size_type n) const
605  {
606  return static_cast<size_type>(
607  next_prime( static_cast<unsigned long>(n) ) );
608  }
609 
611  {
612  const size_type n_buckets = next_size(n);
613  this->buckets.reserve(n_buckets);
614  this->buckets.insert(this->buckets.end(), n_buckets, (node*) 0);
615  this->num_elements = 0;
616  }
617  size_type bkt_num_key(const key_type& key) const
618  {
619  return bkt_num_key(key, this->buckets.size());
620  }
621 
622  size_type bkt_num(const value_type& obj) const
623  {
624  return bkt_num_key(get_key(obj));
625  }
626 
627  size_type bkt_num_key(const key_type& key, size_t n) const
628  {
629  return hashfun(key) % n;
630  }
631 
632  size_type bkt_num(const value_type& obj, size_t n) const
633  {
634  return bkt_num_key(get_key(obj), n);
635  }
636  IUEi_STL_INLINE void erase_bucket(const size_type n, node* first, node* last);
637  IUEi_STL_INLINE void erase_bucket(const size_type n, node* last);
638 };
639 
640 // fbp: these defines are for outline methods definitions.
641 // needed to definitions to be portable. Should not be used in method bodies.
642 
643 # if defined ( __STL_NESTED_TYPE_PARAM_BUG )
644 # define __difference_type__ ptrdiff_t
645 # define __size_type__ size_t
646 # define __value_type__ Value
647 # define __key_type__ Key
648 # define __node__ hashtable_node<Value>
649 # define __reference__ Value&
650 # else
651 # define __difference_type__ typename hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::difference_type
652 # define __size_type__ typename hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::size_type
653 # define __value_type__ typename hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::value_type
654 # define __key_type__ typename hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::key_type
655 # define __node__ typename hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::node
656 # define __reference__ typename hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::reference
657 # endif
658 
659 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
660 inline hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>&
662 {
663  const node* old = cur;
664  cur = cur->next;
665  if (!cur)
666  {
667  size_type bucket = ht->bkt_num(old->val);
668  while (!cur && ++bucket < ht->buckets.size())
669  {
670  cur = ht->buckets[bucket];
671  }
672  }
673  return *this;
674 }
675 
676 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
679 {
680  iterator tmp = *this;
681  ++*this;
682  return tmp;
683 }
684 
685 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
688 {
689  const node* old = cur;
690  cur = cur->next;
691  if (!cur)
692  {
693  size_type bucket = ht->bkt_num(old->val);
694  while (!cur && ++bucket < ht->buckets.size())
695  {
696  cur = ht->buckets[bucket];
697  }
698  }
699  return *this;
700 }
701 
702 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
705 {
706  const_iterator tmp = *this;
707  ++*this;
708  return tmp;
709 }
710 
711 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
712 inline std::forward_iterator_tag
714 {
715  return std::forward_iterator_tag();
716 }
717 
718 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
719 inline Value*
721 {
722  return (Value*) 0;
723 }
724 
725 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
726 inline ptrdiff_t*
728 {
729  return (ptrdiff_t*) 0;
730 }
731 
732 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
733 inline std::forward_iterator_tag
735 {
736  return std::forward_iterator_tag();
737 }
738 
739 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
740 inline Value*
742 {
743  return (Value*) 0;
744 }
745 
746 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
747 inline ptrdiff_t*
749 {
750  return (ptrdiff_t*) 0;
751 }
752 
755 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
758 {
760  if (ht1.buckets.size() != ht2.buckets.size())
761  {
762  return false;
763  }
764  for (int n = 0; n < ht1.buckets.size(); ++n)
765  {
766  node* cur1 = ht1.buckets[n];
767  node* cur2 = ht2.buckets[n];
768  for (; cur1 && cur2 && cur1->val == cur2->val;
769  cur1 = cur1->next, cur2 = cur2->next)
770  {}
771  if (cur1 || cur2)
772  {
773  return false;
774  }
775  }
776  return true;
777 }
778 
779 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
780 std::pair<hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>, bool>
782 {
783  const size_type n = bkt_num(obj);
784  node* first = this->buckets[n];
785 
786  for (node* cur = first; cur; cur = cur->next)
787  if (equals(get_key(cur->val), get_key(obj)))
788  return std::pair<iterator, bool>(iterator(cur, this), false);
789 
790  node* tmp = new_node(obj);
791  tmp->next = first;
792  this->buckets[n] = tmp;
793  ++this->num_elements;
794  return std::pair<iterator, bool>(iterator(tmp, this), true);
795 }
796 
797 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
800 {
801  const size_type n = bkt_num(obj);
802  node* first = this->buckets[n];
803 
804  for (node* cur = first; cur; cur = cur->next)
805  {
806  if (equals(get_key(cur->val), get_key(obj)))
807  {
808  node* tmp = new_node(obj);
809  tmp->next = cur->next;
810  cur->next = tmp;
811  ++this->num_elements;
812  return iterator(tmp, this);
813  }
814  }
815  node* tmp = new_node(obj);
816  tmp->next = first;
817  this->buckets[n] = tmp;
818  ++this->num_elements;
819  return iterator(tmp, this);
820 }
821 
822 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
825 {
826  resize(this->num_elements + 1);
827 
828  size_type n = bkt_num(obj);
829  node* first = this->buckets[n];
830 
831  for (node* cur = first; cur; cur = cur->next)
832  if (equals(get_key(cur->val), get_key(obj)))
833  return cur->val;
834 
835  node* tmp = new_node(obj);
836  tmp->next = first;
837  this->buckets[n] = tmp;
838  ++this->num_elements;
839  return tmp->val;
840 }
841 
842 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
843 std::pair<hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>,
846 {
847  typedef std::pair<iterator, iterator> pii;
848  const size_type n = bkt_num_key(key);
849 
850  for (node* first = this->buckets[n]; first; first = first->next)
851  {
852  if (equals(get_key(first->val), key))
853  {
854  for (node* cur = first->next; cur; cur = cur->next)
855  {
856  if (!equals(get_key(cur->val), key))
857  return pii(iterator(first, this), iterator(cur, this));
858  }
859  for (size_type m = n + 1; m < this->buckets.size(); ++m)
860  {
861  if (this->buckets[m])
862  {
863  return pii(iterator(first, this),
864  iterator(this->buckets[m], this));
865  }
866  }
867  return pii(iterator(first, this), end());
868  }
869  }
870  return pii(end(), end());
871 }
872 
873 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
874 std::pair<hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>,
875  hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> >
877 {
878  typedef std::pair<const_iterator, const_iterator> pii;
879  const size_type n = bkt_num_key(key);
880 
881  for (const node* first = this->buckets[n]; first; first = first->next)
882  {
883  if (equals(get_key(first->val), key))
884  {
885  for (const node* cur = first->next; cur; cur = cur->next)
886  {
887  if (!equals(get_key(cur->val), key))
888  {
889  return pii(const_iterator(first, this),
890  const_iterator(cur, this));
891  }
892  }
893  for (size_type m = n + 1; m < this->buckets.size(); ++m)
894  {
895  if (this->buckets[m])
896  {
897  return pii(const_iterator(first, this),
898  const_iterator(this->buckets[m], this));
899  }
900  }
901  return pii(const_iterator(first, this), end());
902  }
903  }
904  return pii(end(), end());
905 }
906 
907 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
910 {
911  const size_type n = bkt_num_key(key);
912  node* first = this->buckets[n];
913  size_type erased = 0;
914 
915  if (first)
916  {
917  node* cur = first;
918  node* next = cur->next;
919  while (next)
920  {
921  if (equals(get_key(next->val), key))
922  {
923  cur->next = next->next;
924  delete_node(next);
925  next = cur->next;
926  ++erased;
927  }
928  else
929  {
930  cur = next;
931  next = cur->next;
932  }
933  }
934  if (equals(get_key(first->val), key))
935  {
936  this->buckets[n] = first->next;
937  delete_node(first);
938  ++erased;
939  }
940  }
941  this->num_elements -= erased;
942  return erased;
943 }
944 
945 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
946 void
947 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::erase(const hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>& it)
948 {
949  node* const p = it.cur;
950  if (p)
951  {
952  const size_type n = bkt_num(p->val);
953  node* cur = this->buckets[n];
954 
955  if (cur == p)
956  {
957  this->buckets[n] = cur->next;
958  delete_node(cur);
959  --this->num_elements;
960  }
961  else
962  {
963  node* next = cur->next;
964  while (next)
965  {
966  if (next == p)
967  {
968  cur->next = next->next;
969  delete_node(next);
970  --this->num_elements;
971  break;
972  }
973  else
974  {
975  cur = next;
976  next = cur->next;
977  }
978  }
979  }
980  }
981 }
982 
983 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
984 void
985 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::erase(hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> first,
986  hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> last)
987 {
988  size_type f_bucket = first.cur ? bkt_num(first.cur->val) : this->buckets.size();
989  size_type l_bucket = last.cur ? bkt_num(last.cur->val) : this->buckets.size();
990  if (first.cur == last.cur)
991  return;
992  else if (f_bucket == l_bucket)
993  erase_bucket(f_bucket, first.cur, last.cur);
994  else
995  {
996  erase_bucket(f_bucket, first.cur, 0);
997  for (size_type n = f_bucket + 1; n < l_bucket; ++n)
998  erase_bucket(n, 0);
999  if (l_bucket != this->buckets.size())
1000  erase_bucket(l_bucket, last.cur);
1001  }
1002 }
1003 
1004 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
1005 inline void
1006 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::erase(hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> first,
1007  hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> last)
1008 {
1009  erase(iterator(const_cast<node*>(first.cur),
1010  const_cast<self*>(first.ht)),
1011  iterator(const_cast<node*>(last.cur),
1012  const_cast<self*>(last.ht)));
1013 }
1014 
1015 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
1016 inline void
1017 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::erase(const hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>& it)
1018 {
1019  erase(iterator(const_cast<node*>(it.cur),
1020  const_cast<self*>(it.ht)));
1021 }
1022 
1023 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
1024 void
1026 {
1027  const size_type old_n = this->buckets.size();
1028  if (num_elements_hint > old_n)
1029  {
1030  const size_type n = next_size(num_elements_hint);
1031  if (n > old_n)
1032  {
1034  for (size_type bucket = 0; bucket < old_n; ++bucket)
1035  {
1036  node* first = this->buckets[bucket];
1037  while (first)
1038  {
1039  size_type new_bucket = bkt_num(first->val, n);
1040  this->buckets[bucket] = first->next;
1041  first->next = tmp[new_bucket];
1042  tmp[new_bucket] = first;
1043  first = this->buckets[bucket];
1044  }
1045  }
1046  this->buckets.clear();
1047  this->buckets.swap(tmp);
1048  }
1049  }
1050 }
1051 
1052 
1053 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
1054 void
1056  hashtable_node<Value>* first,
1057  hashtable_node<Value>* last)
1058 {
1059  node* cur = this->buckets[n];
1060  if (cur == first)
1061  erase_bucket(n, last);
1062  else
1063  {
1064  node* next;
1065  for (next = cur->next; next != first; cur = next, next = cur->next);
1066  while (next)
1067  {
1068  cur->next = next->next;
1069  delete_node(next);
1070  next = cur->next;
1071  --this->num_elements;
1072  }
1073  }
1074 }
1075 
1076 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
1077 void
1079  hashtable_node<Value>* last)
1080 {
1081  node* cur = this->buckets[n];
1082  while (cur != last)
1083  {
1084  node* next = cur->next;
1085  delete_node(cur);
1086  cur = next;
1087  this->buckets[n] = cur;
1088  --this->num_elements;
1089  }
1090 }
1091 
1092 template <class Value, class Alloc>
1094 {
1095  for (size_type i = 0; i < buckets.size(); ++i)
1096  {
1097  node* cur = buckets[i];
1098  while (cur != 0)
1099  {
1100  node* next = cur->next;
1101  delete_node(cur);
1102  cur = next;
1103  }
1104  buckets[i] = 0;
1105  }
1106  num_elements = 0;
1107 }
1108 
1109 
1110 template <class Value, class Alloc>
1112 {
1113  buckets.reserve(ht.buckets.size());
1114  buckets.insert(buckets.end(), ht.buckets.size(), (node*) 0);
1115  for (size_type i = 0; i < ht.buckets.size(); ++i)
1116  {
1117  const node* cur = ht.buckets[i];
1118  if (cur)
1119  {
1120  node* copy = new_node(cur->val);
1121  buckets[i] = copy;
1122  ++num_elements;
1123 
1124  for (node* next = cur->next; next; cur = next, next = cur->next)
1125  {
1126  copy->next = new_node(next->val);
1127  ++num_elements;
1128  copy = copy->next;
1129  }
1130  }
1131  }
1132 }
1133 
1134 }// end namespace itk
1135 
1136 
1137 # undef __difference_type__
1138 # undef __size_type__
1139 # undef __value_type__
1140 # undef __key_type__
1141 # undef __node__
1142 
1143 // the following is added for itk compatability:
1144 
1145 // --
1146 
1147 // A few compatability fixes. Placed here for automatic include in
1148 // both the hash_set and the hash_map sources.
1149 # if (defined (_MSC_VER)&&(_MSC_VER < 1600 )) || defined(__BORLANDC__) || ((defined(__ICC)||defined(__ECC)) && defined(linux))
1150 // This should be replaced with a try_compile that tests the availability of std::identity. FIXME
1151 namespace std
1152 {
1153 template <class T>
1154 struct identity : public std::unary_function<T, T> {
1155 public:
1156  const T& operator()(const T& x) const { return x; }
1157 };
1158 }
1159 
1160 #endif
1161 
1162 # if defined (_MSC_VER) || defined(__BORLANDC__) || ((defined(__ICC)||defined(__ECC)) && defined(linux))
1163 // This should be replaced with a try_compile that tests the availability of std::select*. FIXME
1164 
1165 template <class _Pair>
1166 struct itk_Select1st : public std::unary_function<_Pair, typename _Pair::first_type> {
1167  typename _Pair::first_type const & operator()(_Pair const & __x) const { return __x.first; }
1168 };
1169 
1170 template <class _Pair>
1171 struct itk_Select2nd : public std::unary_function<_Pair, typename _Pair::second_type> {
1172  typename _Pair::second_type const & operator()(_Pair const & __x) const { return __x.second; }
1173 };
1174 
1175 // Add select* to std.
1176 namespace std {
1177 template <class _Pair>
1178 struct select1st : public itk_Select1st<_Pair> {};
1179 template <class _Pair> struct select2nd : public itk_Select2nd<_Pair> {};
1180 }
1181 
1182 #endif
1183 
1184 #endif
1185 
1186 #endif // itk_emulation_hashtable_h

Generated at Sat Feb 2 2013 23:22:54 for Orfeo Toolbox with doxygen 1.8.1.1