00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #ifndef itk_emulation_hashtable_h
00069 #define itk_emulation_hashtable_h
00070
00071 #if (defined(__GNUC__) && (((__GNUC__==3) && (__GNUC_MINOR__>=1) || (__GNUC__>3) ) || ( (__GNUC__==4) && defined(__INTEL_COMPILER) ) )) || (defined(__IBMCPP__) && __IBMCPP__ >= 600)
00072
00073
00074 #else
00075
00078 #include "itkMacro.h"
00079 #include <iostream>
00080 #include "itk_alloc.h"
00081 #include <vector>
00082 #include <utility>
00083 #include <memory>
00084 #include "vcl_compiler.h"
00085 #include <functional>
00086 #include <algorithm>
00087 #include <iterator>
00088
00089
00090 namespace itk
00091 {
00092 template <class Key> struct hash { };
00093
00094 inline size_t hash_string(const char* s)
00095 {
00096 unsigned long h = 0;
00097 for ( ; *s; ++s)
00098 h = 5*h + *s;
00099
00100 return size_t(h);
00101 }
00102
00103 template<>
00104 struct hash<char*>
00105 {
00106 size_t operator()(const char* s) const { return hash_string(s); }
00107 };
00108
00109 template<>
00110 struct hash<const char*>
00111 {
00112 size_t operator()(const char* s) const { return hash_string(s); }
00113 };
00114
00115 template<>
00116 struct hash<char> {
00117 size_t operator()(char x) const { return x; }
00118 };
00119
00120 template<>
00121 struct hash<unsigned char> {
00122 size_t operator()(unsigned char x) const { return x; }
00123 };
00124
00125 template<>
00126 struct hash<signed char> {
00127 size_t operator()(unsigned char x) const { return x; }
00128 };
00129
00130 template<>
00131 struct hash<short> {
00132 size_t operator()(short x) const { return x; }
00133 };
00134
00135 template<>
00136 struct hash<unsigned short> {
00137 size_t operator()(unsigned short x) const { return x; }
00138 };
00139
00140 template<>
00141 struct hash<int> {
00142 size_t operator()(int x) const { return x; }
00143 };
00144
00145 template<>
00146 struct hash<unsigned int> {
00147 size_t operator()(unsigned int x) const { return x; }
00148 };
00149
00150 template<>
00151 struct hash<long> {
00152 size_t operator()(long x) const { return x; }
00153 };
00154
00155 template<>
00156 struct hash<unsigned long> {
00157 size_t operator()(unsigned long x) const { return x; }
00158 };
00159
00160 template <class Value>
00161 struct hashtable_node
00162 {
00163 typedef hashtable_node<Value> self;
00164 self* next;
00165 Value val;
00166 };
00167
00168 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey , VCL_DFL_TYPE_PARAM_STLDECL(Alloc,std::allocator<char>)>
00169 class hashtable;
00170
00171 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00172 struct hashtable_iterator;
00173
00174 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00175 struct hashtable_const_iterator;
00176
00177 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00178 struct hashtable_iterator
00179 {
00180 typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>
00181 hash_table;
00182 typedef hashtable_iterator<Value, Key, HashFcn,
00183 ExtractKey, EqualKey, Alloc>
00184 iterator;
00185 typedef hashtable_const_iterator<Value, Key, HashFcn,
00186 ExtractKey, EqualKey, Alloc>
00187 const_iterator;
00188 typedef hashtable_node<Value> node;
00189 typedef size_t size_type;
00190 typedef Value& reference;
00191 typedef Value* pointer;
00192 typedef const Value& const_reference;
00193
00194 node* cur;
00195 hash_table* ht;
00196
00197 hashtable_iterator(node* n, hash_table* tab) : cur(n), ht(tab) {}
00198 hashtable_iterator() {}
00199 reference operator*() const {
00200 return cur->val;
00201 }
00202 pointer operator->() const { return &(operator*()); }
00203
00204 IUEi_STL_INLINE iterator& operator++();
00205 IUEi_STL_INLINE iterator operator++(int);
00206 bool operator==(const iterator& it) const {
00207 return cur == it.cur;
00208 }
00209 bool operator!=(const iterator& it) const {
00210 return cur != it.cur;
00211 }
00212 };
00213
00214
00215 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00216 struct hashtable_const_iterator
00217 {
00218 typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>
00219 hash_table;
00220 typedef hashtable_iterator<Value, Key, HashFcn,
00221 ExtractKey, EqualKey, Alloc> iterator;
00222 typedef hashtable_const_iterator<Value, Key, HashFcn,
00223 ExtractKey, EqualKey, Alloc> const_iterator;
00224 typedef hashtable_node<Value> node;
00225 typedef size_t size_type;
00226 typedef Value& reference;
00227 typedef const Value& const_reference;
00228 typedef const Value* pointer;
00229
00230 const node* cur;
00231 const hash_table* ht;
00232
00233 hashtable_const_iterator(const node* n, const hash_table* tab) : cur(n), ht(tab) {}
00234 hashtable_const_iterator() {}
00235 hashtable_const_iterator(const iterator& it) : cur(it.cur), ht(it.ht) {}
00236
00237 const_reference operator*() const {
00238 return cur->val;
00239 }
00240 pointer operator->() const { return &(operator*()); }
00241 IUEi_STL_INLINE const_iterator& operator++();
00242 IUEi_STL_INLINE const_iterator operator++(int);
00243 bool operator==(const const_iterator& it) const {
00244 return cur == it.cur;
00245 }
00246 bool operator!=(const const_iterator& it) const {
00247 return cur != it.cur;
00248 }
00249 };
00250
00251
00252
00253 enum { num_primes = 28 };
00254
00255 #if ( __STL_STATIC_TEMPLATE_DATA > 0 ) && ! defined (WIN32)
00256 # define prime_list prime<false>::list_
00257 template <bool dummy>
00258 struct prime {
00259 public:
00260 static const unsigned long list_[];
00261 };
00262 static const unsigned long prime_list_dummy[num_primes] =
00263 # else
00264 # if ( __STL_WEAK_ATTRIBUTE > 0 )
00265 extern const unsigned long prime_list[num_primes] __attribute__((weak)) =
00266 # else
00267
00268 static const unsigned long prime_list[num_primes] =
00269 # endif
00270 #endif
00271 {
00272 53, 97, 193, 389, 769,
00273 1543, 3079, 6151, 12289, 24593,
00274 49157, 98317, 196613, 393241, 786433,
00275 1572869, 3145739, 6291469, 12582917, 25165843,
00276 50331653, 100663319, 201326611, 402653189, 805306457,
00277 1610612741, 3221225473U, 4294967291U
00278 };
00279
00280 inline unsigned long next_prime(unsigned long n)
00281 {
00282 const unsigned long* first = prime_list;
00283 const unsigned long* last = prime_list;
00284 last += num_primes;
00285 const unsigned long* pos = std::lower_bound(first, last, n);
00286 return pos == last ? *(last - 1) : *pos;
00287 }
00288
00289 template <class Value, class Alloc>
00290 class hashtable_base
00291 {
00292 private:
00293 typedef Value value_type;
00294 typedef size_t size_type;
00295 typedef hashtable_node<Value> node;
00296 typedef itk_simple_alloc<node, Alloc> node_allocator;
00297 public:
00298 typedef std::vector<VCL_SUNPRO_ALLOCATOR_HACK(node*) > buckets_type ;
00299 buckets_type buckets;
00300 size_type num_elements;
00301 protected:
00302 IUEi_STL_INLINE void clear();
00303
00304 node* new_node(const value_type& obj)
00305 {
00306 node* n = node_allocator::allocate();
00307 try {
00308 new (&(n->val)) value_type(obj);
00309 }
00310 catch (...) {
00311 node_allocator::deallocate(n);
00312 throw "";
00313 }
00314 n->next = 0;
00315 return n;
00316 }
00317
00318 void delete_node(node* n)
00319 {
00320 #define vcli_destroy(T, p) ((T*)p)->~T()
00321 vcli_destroy(Value, &(n->val));
00322 #undef vcli_destroy
00323 node_allocator::deallocate(n);
00324 }
00325
00326 IUEi_STL_INLINE void copy_from(const hashtable_base<Value,Alloc>& ht);
00327
00328 public:
00329 hashtable_base() : num_elements(0) { }
00330
00331 ~hashtable_base() { clear(); }
00332 };
00333
00334
00335
00336 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc> class hashtable;
00337 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00338 bool operator== (hashtable<Value,Key,HashFcn,ExtractKey,EqualKey,Alloc>const&,hashtable<Value,Key,HashFcn,ExtractKey,EqualKey,Alloc>const&);
00339
00340 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00341 class hashtable : protected hashtable_base<Value, Alloc>
00342 {
00343 typedef hashtable_base<Value, Alloc> super;
00344 typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> self;
00345 public:
00346 typedef Key key_type;
00347 typedef Value value_type;
00348 typedef HashFcn hasher;
00349 typedef EqualKey key_equal;
00350
00351 typedef size_t size_type;
00352 typedef ptrdiff_t difference_type;
00353 typedef value_type* pointer;
00354 typedef const value_type* const_pointer;
00355 typedef value_type& reference;
00356 typedef const value_type& const_reference;
00357
00358 hasher hash_funct() const { return hashfun; }
00359 key_equal key_eq() const { return equals; }
00360
00361 private:
00362 hasher hashfun;
00363 key_equal equals;
00364 ExtractKey get_key;
00365
00366 typedef hashtable_node<Value> node;
00367 typedef itk_simple_alloc<node, Alloc> node_allocator;
00368
00369 public:
00370 typedef hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> iterator;
00371 typedef hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey,Alloc> const_iterator;
00372 friend struct
00373 hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>;
00374 friend struct
00375 hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>;
00376
00377 public:
00378 hashtable(size_type n,
00379 const HashFcn& hf,
00380 const EqualKey& eql,
00381 const ExtractKey& ext)
00382 : hashfun(hf), equals(eql), get_key(ext) {
00383 initialize_buckets(n);
00384 }
00385
00386 hashtable(size_type n,
00387 const HashFcn& hf,
00388 const EqualKey& eql)
00389 : hashfun(hf), equals(eql), get_key(ExtractKey()) {
00390 initialize_buckets(n);
00391 }
00392
00393 hashtable(const self& ht)
00394 : hashfun(ht.hashfun), equals(ht.equals), get_key(ht.get_key) {
00395 copy_from(ht);
00396 }
00397
00398 self& operator= (const self& ht)
00399 {
00400 if (&ht != this) {
00401 hashfun = ht.hashfun;
00402 equals = ht.equals;
00403 get_key = ht.get_key;
00404 clear();
00405 this->buckets.clear();
00406 copy_from(ht);
00407 }
00408 return *this;
00409 }
00410
00411 ~hashtable() {}
00412
00413 size_type size() const { return this->num_elements; }
00414 size_type max_size() const { return size_type(-1); }
00415 bool empty() const { return size() == 0; }
00416
00417 void swap(self& ht)
00418 {
00419 std::swap(hashfun, ht.hashfun);
00420 std::swap(equals, ht.equals);
00421 std::swap(get_key, ht.get_key);
00422 this->buckets.swap(ht.buckets);
00423 std::swap(this->num_elements, ht.num_elements);
00424 }
00425
00426 iterator begin()
00427 {
00428 for (size_type n = 0; n < this->buckets.size(); ++n)
00429 if (this->buckets[n])
00430 return iterator(this->buckets[n], this);
00431 return end();
00432 }
00433
00434 iterator end() { return iterator((node*)0, this); }
00435
00436 const_iterator begin() const
00437 {
00438 for (size_type n = 0; n < this->buckets.size(); ++n)
00439 if (this->buckets[n])
00440 return const_iterator(this->buckets[n], this);
00441 return end();
00442 }
00443
00444 const_iterator end() const { return const_iterator((node*)0, this); }
00445
00446
00447
00448 friend bool operator== VCL_NULL_TMPL_ARGS (const self&,const self&);
00449 public:
00450
00451 size_type bucket_count() const { return this->buckets.size(); }
00452
00453 size_type max_bucket_count() const
00454 { return prime_list[num_primes - 1]; }
00455
00456 size_type elems_in_bucket(size_type bucket) const
00457 {
00458 size_type result = 0;
00459 for (node* cur = this->buckets[bucket]; cur; cur = cur->next)
00460 result += 1;
00461 return result;
00462 }
00463
00464 std::pair<iterator, bool> insert_unique(const value_type& obj)
00465 {
00466 resize(this->num_elements + 1);
00467 return insert_unique_noresize(obj);
00468 }
00469
00470 iterator insert_equal(const value_type& obj)
00471 {
00472 resize(this->num_elements + 1);
00473 return insert_equal_noresize(obj);
00474 }
00475
00476 IUEi_STL_INLINE std::pair<iterator, bool> insert_unique_noresize(const value_type& obj);
00477 IUEi_STL_INLINE iterator insert_equal_noresize(const value_type& obj);
00478
00479 void insert_unique(const value_type* f, const value_type* l)
00480 {
00481 size_type n = l - f;
00482 resize(this->num_elements + n);
00483 for ( ; n > 0; --n)
00484 insert_unique_noresize(*f++);
00485 }
00486
00487 void insert_equal(const value_type* f, const value_type* l)
00488 {
00489 size_type n = l - f;
00490 resize(this->num_elements + n);
00491 for ( ; n > 0; --n)
00492 insert_equal_noresize(*f++);
00493 }
00494
00495 void insert_unique(const_iterator f, const_iterator l)
00496 {
00497 size_type n = 0;
00498 std::distance(f, l, n);
00499 resize(this->num_elements + n);
00500 for ( ; n > 0; --n)
00501 insert_unique_noresize(*f++);
00502 }
00503
00504 void insert_equal(const_iterator f, const_iterator l)
00505 {
00506 size_type n = 0;
00507 std::distance(f, l, n);
00508 resize(this->num_elements + n);
00509 for ( ; n > 0; --n)
00510 insert_equal_noresize(*f++);
00511 }
00512
00513 IUEi_STL_INLINE reference find_or_insert(const value_type& obj);
00514
00515 iterator find(const key_type& key)
00516 {
00517 size_type n = bkt_num_key(key);
00518 node* first;
00519 for ( first = this->buckets[n];
00520 first && !equals(get_key(first->val), key);
00521 first = first->next)
00522 {}
00523 return iterator(first, this);
00524 }
00525
00526 const_iterator find(const key_type& key) const
00527 {
00528 size_type n = bkt_num_key(key);
00529 const node* first;
00530 for ( first = this->buckets[n];
00531 first && !equals(get_key(first->val), key);
00532 first = first->next)
00533 {}
00534 return const_iterator(first, this);
00535 }
00536
00537 size_type count(const key_type& key) const
00538 {
00539 const size_type n = bkt_num_key(key);
00540 size_type result = 0;
00541
00542 for (const node* cur = this->buckets[n]; cur; cur = cur->next)
00543 if (equals(get_key(cur->val), key))
00544 ++result;
00545 return result;
00546 }
00547
00548 IUEi_STL_INLINE std::pair<iterator, iterator> equal_range(const key_type& key);
00549 IUEi_STL_INLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const;
00550
00551 IUEi_STL_INLINE size_type erase(const key_type& key);
00552 IUEi_STL_INLINE void erase(const iterator& it);
00553 IUEi_STL_INLINE void erase(iterator first, iterator last);
00554
00555 IUEi_STL_INLINE void erase(const const_iterator& it);
00556 IUEi_STL_INLINE void erase(const_iterator first, const_iterator last);
00557
00558 IUEi_STL_INLINE void resize(size_type num_elements_hint);
00559 void clear() { super::clear(); }
00560 private:
00561 size_type next_size(size_type n) const {
00562 return static_cast<size_type>(
00563 next_prime( static_cast<unsigned long>(n) ) ); }
00564
00565 void initialize_buckets(size_type n)
00566 {
00567 const size_type n_buckets = next_size(n);
00568 this->buckets.reserve(n_buckets);
00569 this->buckets.insert(this->buckets.end(), n_buckets, (node*) 0);
00570 this->num_elements = 0;
00571 }
00572 size_type bkt_num_key(const key_type& key) const{
00573 return bkt_num_key(key, this->buckets.size());
00574 }
00575
00576 size_type bkt_num(const value_type& obj) const {
00577 return bkt_num_key(get_key(obj));
00578 }
00579
00580 size_type bkt_num_key(const key_type& key, size_t n) const {
00581 return hashfun(key) % n;
00582 }
00583
00584 size_type bkt_num(const value_type& obj, size_t n) const {
00585 return bkt_num_key(get_key(obj), n);
00586 }
00587 IUEi_STL_INLINE void erase_bucket(const size_type n, node* first, node* last);
00588 IUEi_STL_INLINE void erase_bucket(const size_type n, node* last);
00589 };
00590
00591
00592
00593
00594 # if defined ( __STL_NESTED_TYPE_PARAM_BUG )
00595 # define __difference_type__ ptrdiff_t
00596 # define __size_type__ size_t
00597 # define __value_type__ Value
00598 # define __key_type__ Key
00599 # define __node__ hashtable_node<Value>
00600 # define __reference__ Value&
00601 # else
00602 # define __difference_type__ typename hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::difference_type
00603 # define __size_type__ typename hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::size_type
00604 # define __value_type__ typename hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::value_type
00605 # define __key_type__ typename hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::key_type
00606 # define __node__ typename hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::node
00607 # define __reference__ typename hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::reference
00608 # endif
00609
00610 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00611 inline hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>&
00612 hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::operator++()
00613 {
00614 const node* old = cur;
00615 cur = cur->next;
00616 if (!cur) {
00617 size_type bucket = ht->bkt_num(old->val);
00618 while (!cur && ++bucket < ht->buckets.size())
00619 cur = ht->buckets[bucket];
00620 }
00621 return *this;
00622 }
00623
00624 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00625 inline hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>
00626 hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::operator++(int)
00627 {
00628 iterator tmp = *this;
00629 ++*this;
00630 return tmp;
00631 }
00632
00633 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00634 inline hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>&
00635 hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::operator++()
00636 {
00637 const node* old = cur;
00638 cur = cur->next;
00639 if (!cur) {
00640 size_type bucket = ht->bkt_num(old->val);
00641 while (!cur && ++bucket < ht->buckets.size())
00642 cur = ht->buckets[bucket];
00643 }
00644 return *this;
00645 }
00646
00647 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00648 inline hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>
00649 hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::operator++(int)
00650 {
00651 const_iterator tmp = *this;
00652 ++*this;
00653 return tmp;
00654 }
00655
00656 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00657 inline std::forward_iterator_tag
00658 iterator_category (const hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>&)
00659 {
00660 return std::forward_iterator_tag();
00661 }
00662
00663 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00664 inline Value*
00665 value_type(const hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>&)
00666 {
00667 return (Value*) 0;
00668 }
00669
00670 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00671 inline ptrdiff_t*
00672 distance_type(const hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>&)
00673 {
00674 return (ptrdiff_t*) 0;
00675 }
00676
00677 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00678 inline std::forward_iterator_tag
00679 iterator_category (const hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>&)
00680 {
00681 return std::forward_iterator_tag();
00682 }
00683
00684 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00685 inline Value*
00686 value_type(const hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>&)
00687 {
00688 return (Value*) 0;
00689 }
00690
00691 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00692 inline ptrdiff_t*
00693 distance_type(const hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>&)
00694 {
00695 return (ptrdiff_t*) 0;
00696 }
00697
00698
00699
00700 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00701 IUEi_STL_INLINE
00702 bool operator==(const hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>& ht1,
00703 const hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>& ht2)
00704 {
00705 typedef typename hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::node node;
00706 if (ht1.buckets.size() != ht2.buckets.size())
00707 return false;
00708 for (int n = 0; n < ht1.buckets.size(); ++n) {
00709 node* cur1 = ht1.buckets[n];
00710 node* cur2 = ht2.buckets[n];
00711 for ( ; cur1 && cur2 && cur1->val == cur2->val;
00712 cur1 = cur1->next, cur2 = cur2->next)
00713 {}
00714 if (cur1 || cur2)
00715 return false;
00716 }
00717 return true;
00718 }
00719
00720 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00721 std::pair<hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>, bool>
00722 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::insert_unique_noresize(const __value_type__& obj)
00723 {
00724 const size_type n = bkt_num(obj);
00725 node* first = this->buckets[n];
00726
00727 for (node* cur = first; cur; cur = cur->next)
00728 if (equals(get_key(cur->val), get_key(obj)))
00729 return std::pair<iterator, bool>(iterator(cur, this), false);
00730
00731 node* tmp = new_node(obj);
00732 tmp->next = first;
00733 this->buckets[n] = tmp;
00734 ++this->num_elements;
00735 return std::pair<iterator, bool>(iterator(tmp, this), true);
00736 }
00737
00738 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00739 hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>
00740 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::insert_equal_noresize(const __value_type__& obj)
00741 {
00742 const size_type n = bkt_num(obj);
00743 node* first = buckets[n];
00744
00745 for (node* cur = first; cur; cur = cur->next)
00746 if (equals(get_key(cur->val), get_key(obj))) {
00747 node* tmp = new_node(obj);
00748 tmp->next = cur->next;
00749 cur->next = tmp;
00750 ++num_elements;
00751 return iterator(tmp, this);
00752 }
00753
00754 node* tmp = new_node(obj);
00755 tmp->next = first;
00756 buckets[n] = tmp;
00757 ++num_elements;
00758 return iterator(tmp, this);
00759 }
00760
00761 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00762 __reference__
00763 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::find_or_insert(const __value_type__& obj)
00764 {
00765 resize(this->num_elements + 1);
00766
00767 size_type n = bkt_num(obj);
00768 node* first = this->buckets[n];
00769
00770 for (node* cur = first; cur; cur = cur->next)
00771 if (equals(get_key(cur->val), get_key(obj)))
00772 return cur->val;
00773
00774 node* tmp = new_node(obj);
00775 tmp->next = first;
00776 this->buckets[n] = tmp;
00777 ++this->num_elements;
00778 return tmp->val;
00779 }
00780
00781 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00782 std::pair<hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>,
00783 hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> >
00784 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::equal_range(const __key_type__& key)
00785 {
00786 typedef std::pair<iterator, iterator> pii;
00787 const size_type n = bkt_num_key(key);
00788
00789 for (node* first = buckets[n]; first; first = first->next) {
00790 if (equals(get_key(first->val), key)) {
00791 for (node* cur = first->next; cur; cur = cur->next)
00792 if (!equals(get_key(cur->val), key))
00793 return pii(iterator(first, this), iterator(cur, this));
00794 for (size_type m = n + 1; m < buckets.size(); ++m)
00795 if (buckets[m])
00796 return pii(iterator(first, this),
00797 iterator(buckets[m], this));
00798 return pii(iterator(first, this), end());
00799 }
00800 }
00801 return pii(end(), end());
00802 }
00803
00804 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00805 std::pair<hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>,
00806 hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> >
00807 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::equal_range(const __key_type__& key) const
00808 {
00809 typedef std::pair<const_iterator, const_iterator> pii;
00810 const size_type n = bkt_num_key(key);
00811
00812 for (const node* first = buckets[n] ; first; first = first->next) {
00813 if (equals(get_key(first->val), key)) {
00814 for (const node* cur = first->next; cur; cur = cur->next)
00815 if (!equals(get_key(cur->val), key))
00816 return pii(const_iterator(first, this),
00817 const_iterator(cur, this));
00818 for (size_type m = n + 1; m < buckets.size(); ++m)
00819 if (buckets[m])
00820 return pii(const_iterator(first, this),
00821 const_iterator(buckets[m], this));
00822 return pii(const_iterator(first, this), end());
00823 }
00824 }
00825 return pii(end(), end());
00826 }
00827
00828 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00829 __size_type__
00830 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::erase(const __key_type__& key)
00831 {
00832 const size_type n = bkt_num_key(key);
00833 node* first = this->buckets[n];
00834 size_type erased = 0;
00835
00836 if (first) {
00837 node* cur = first;
00838 node* next = cur->next;
00839 while (next) {
00840 if (equals(get_key(next->val), key)) {
00841 cur->next = next->next;
00842 delete_node(next);
00843 next = cur->next;
00844 ++erased;
00845 }
00846 else {
00847 cur = next;
00848 next = cur->next;
00849 }
00850 }
00851 if (equals(get_key(first->val), key)) {
00852 this->buckets[n] = first->next;
00853 delete_node(first);
00854 ++erased;
00855 }
00856 }
00857 this->num_elements -= erased;
00858 return erased;
00859 }
00860
00861 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00862 void
00863 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::erase(const hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>& it)
00864 {
00865 node* const p = it.cur;
00866 if (p) {
00867 const size_type n = bkt_num(p->val);
00868 node* cur = this->buckets[n];
00869
00870 if (cur == p) {
00871 this->buckets[n] = cur->next;
00872 delete_node(cur);
00873 --this->num_elements;
00874 }
00875 else {
00876 node* next = cur->next;
00877 while (next) {
00878 if (next == p) {
00879 cur->next = next->next;
00880 delete_node(next);
00881 --this->num_elements;
00882 break;
00883 }
00884 else {
00885 cur = next;
00886 next = cur->next;
00887 }
00888 }
00889 }
00890 }
00891 }
00892
00893 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00894 void
00895 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::erase(hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> first,
00896 hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> last)
00897 {
00898 size_type f_bucket = first.cur ? bkt_num(first.cur->val) : buckets.size();
00899 size_type l_bucket = last.cur ? bkt_num(last.cur->val) : buckets.size();
00900 if (first.cur == last.cur)
00901 return;
00902 else if (f_bucket == l_bucket)
00903 erase_bucket(f_bucket, first.cur, last.cur);
00904 else {
00905 erase_bucket(f_bucket, first.cur, 0);
00906 for (size_type n = f_bucket + 1; n < l_bucket; ++n)
00907 erase_bucket(n, 0);
00908 if (l_bucket != buckets.size())
00909 erase_bucket(l_bucket, last.cur);
00910 }
00911 }
00912
00913 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00914 inline void
00915 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::erase(hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> first,
00916 hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> last)
00917 {
00918 erase(iterator(const_cast<node*>(first.cur),
00919 const_cast<self*>(first.ht)),
00920 iterator(const_cast<node*>(last.cur),
00921 const_cast<self*>(last.ht)));
00922 }
00923
00924 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00925 inline void
00926 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::erase(const hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>& it)
00927 {
00928 erase(iterator(const_cast<node*>(it.cur),
00929 const_cast<self*>(it.ht)));
00930 }
00931
00932 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00933 void
00934 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::resize(__size_type__ num_elements_hint)
00935 {
00936 const size_type old_n = this->buckets.size();
00937 if (num_elements_hint > old_n) {
00938 const size_type n = next_size(num_elements_hint);
00939 if (n > old_n) {
00940 typename hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::buckets_type tmp(n, (node*)0);
00941 for (size_type bucket = 0; bucket < old_n; ++bucket) {
00942 node* first = this->buckets[bucket];
00943 while (first) {
00944 size_type new_bucket = bkt_num(first->val, n);
00945 this->buckets[bucket] = first->next;
00946 first->next = tmp[new_bucket];
00947 tmp[new_bucket] = first;
00948 first = this->buckets[bucket];
00949 }
00950 }
00951 this->buckets.clear();
00952 this->buckets.swap(tmp);
00953 }
00954 }
00955 }
00956
00957
00958 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00959 void
00960 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::erase_bucket(const size_t n,
00961 hashtable_node<Value>* first,
00962 hashtable_node<Value>* last)
00963 {
00964 node* cur = buckets[n];
00965 if (cur == first)
00966 erase_bucket(n, last);
00967 else {
00968 node* next;
00969 for (next = cur->next; next != first; cur = next, next = cur->next)
00970 ;
00971 while (next) {
00972 cur->next = next->next;
00973 delete_node(next);
00974 next = cur->next;
00975 --num_elements;
00976 }
00977 }
00978 }
00979
00980 template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
00981 void
00982 hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::erase_bucket(const size_t n,
00983 hashtable_node<Value>* last)
00984 {
00985 node* cur = buckets[n];
00986 while (cur != last) {
00987 node* next = cur->next;
00988 delete_node(cur);
00989 cur = next;
00990 buckets[n] = cur;
00991 --num_elements;
00992 }
00993 }
00994
00995 template <class Value, class Alloc>
00996 void hashtable_base<Value, Alloc>::clear()
00997 {
00998 for (size_type i = 0; i < buckets.size(); ++i) {
00999 node* cur = buckets[i];
01000 while (cur != 0) {
01001 node* next = cur->next;
01002 delete_node(cur);
01003 cur = next;
01004 }
01005 buckets[i] = 0;
01006 }
01007 num_elements = 0;
01008 }
01009
01010
01011 template <class Value, class Alloc>
01012 void hashtable_base<Value, Alloc>::copy_from(const hashtable_base<Value, Alloc>& ht)
01013 {
01014 buckets.reserve(ht.buckets.size());
01015 buckets.insert(buckets.end(), ht.buckets.size(), (node*) 0);
01016 for (size_type i = 0; i < ht.buckets.size(); ++i) {
01017 const node* cur = ht.buckets[i];
01018 if (cur) {
01019 node* copy = new_node(cur->val);
01020 buckets[i] = copy;
01021 ++num_elements;
01022
01023 for (node* next = cur->next; next; cur = next, next = cur->next) {
01024 copy->next = new_node(next->val);
01025 ++num_elements;
01026 copy = copy->next;
01027 }
01028 }
01029 }
01030 }
01031
01032 }
01033
01034
01035 # undef __difference_type__
01036 # undef __size_type__
01037 # undef __value_type__
01038 # undef __key_type__
01039 # undef __node__
01040
01041
01042
01043
01044
01045
01046
01047 # if defined(VCL_SUNPRO_CC) || defined (_MSC_VER) || defined(__BORLANDC__) || ((defined(__ICC)||defined(__ECC)) && defined(linux))
01048 namespace std
01049 {
01050 template <class T>
01051 struct identity : public std::unary_function<T, T> {
01052 public:
01053 const T& operator()(const T& x) const { return x; }
01054 };
01055 }
01056
01057 template <class _Pair>
01058 struct itk_Select1st : public std::unary_function<_Pair, typename _Pair::first_type> {
01059 typename _Pair::first_type const & operator()(_Pair const & __x) const {
01060 return __x.first;
01061 }
01062 };
01063
01064 template <class _Pair>
01065 struct itk_Select2nd : public std::unary_function<_Pair, typename _Pair::second_type> {
01066 typename _Pair::second_type const & operator()(_Pair const & __x) const {
01067 return __x.second;
01068 }
01069 };
01070
01071
01072 namespace std {
01073 template <class _Pair>
01074 struct select1st : public itk_Select1st<_Pair> { };
01075 template <class _Pair> struct select2nd : public itk_Select2nd<_Pair> { };
01076 };
01077
01078 #endif
01079
01080 #endif
01081
01082 #endif // itk_emulation_hashtable_h
01083