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