1  // Hashtable implementation used by containers -*- C++ -*-
       2  
       3  // Copyright (C) 2001-2023 Free Software Foundation, Inc.
       4  //
       5  // This file is part of the GNU ISO C++ Library.  This library is free
       6  // software; you can redistribute it and/or modify it under the
       7  // terms of the GNU General Public License as published by the
       8  // Free Software Foundation; either version 3, or (at your option)
       9  // any later version.
      10  
      11  // This library is distributed in the hope that it will be useful,
      12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14  // GNU General Public License for more details.
      15  
      16  // Under Section 7 of GPL version 3, you are granted additional
      17  // permissions described in the GCC Runtime Library Exception, version
      18  // 3.1, as published by the Free Software Foundation.
      19  
      20  // You should have received a copy of the GNU General Public License and
      21  // a copy of the GCC Runtime Library Exception along with this program;
      22  // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      23  // <http://www.gnu.org/licenses/>.
      24  
      25  /*
      26   * Copyright (c) 1996,1997
      27   * Silicon Graphics Computer Systems, Inc.
      28   *
      29   * Permission to use, copy, modify, distribute and sell this software
      30   * and its documentation for any purpose is hereby granted without fee,
      31   * provided that the above copyright notice appear in all copies and
      32   * that both that copyright notice and this permission notice appear
      33   * in supporting documentation.  Silicon Graphics makes no
      34   * representations about the suitability of this software for any
      35   * purpose.  It is provided "as is" without express or implied warranty.
      36   *
      37   *
      38   * Copyright (c) 1994
      39   * Hewlett-Packard Company
      40   *
      41   * Permission to use, copy, modify, distribute and sell this software
      42   * and its documentation for any purpose is hereby granted without fee,
      43   * provided that the above copyright notice appear in all copies and
      44   * that both that copyright notice and this permission notice appear
      45   * in supporting documentation.  Hewlett-Packard Company makes no
      46   * representations about the suitability of this software for any
      47   * purpose.  It is provided "as is" without express or implied warranty.
      48   *
      49   */
      50  
      51  /** @file backward/hashtable.h
      52   *  This file is a GNU extension to the Standard C++ Library (possibly
      53   *  containing extensions from the HP/SGI STL subset).
      54   */
      55  
      56  #ifndef _BACKWARD_HASHTABLE_H
      57  #define _BACKWARD_HASHTABLE_H 1
      58  
      59  // Hashtable class, used to implement the hashed associative containers
      60  // hash_set, hash_map, hash_multiset, and hash_multimap.
      61  
      62  #include <vector>
      63  #include <iterator>
      64  #include <algorithm>
      65  #include <bits/stl_function.h>
      66  #include <ext/alloc_traits.h>
      67  #include <backward/hash_fun.h>
      68  
      69  namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
      70  {
      71  _GLIBCXX_BEGIN_NAMESPACE_VERSION
      72  
      73    template<class _Val>
      74      struct _Hashtable_node
      75      {
      76        _Hashtable_node* _M_next;
      77        _Val _M_val;
      78      };
      79  
      80    template<class _Val, class _Key, class _HashFcn, class _ExtractKey, 
      81  	   class _EqualKey, class _Alloc = std::allocator<_Val> >
      82      class hashtable;
      83  
      84    template<class _Val, class _Key, class _HashFcn,
      85  	   class _ExtractKey, class _EqualKey, class _Alloc>
      86      struct _Hashtable_iterator;
      87  
      88    template<class _Val, class _Key, class _HashFcn,
      89  	   class _ExtractKey, class _EqualKey, class _Alloc>
      90      struct _Hashtable_const_iterator;
      91  
      92    template<class _Val, class _Key, class _HashFcn,
      93  	   class _ExtractKey, class _EqualKey, class _Alloc>
      94      struct _Hashtable_iterator
      95      {
      96        typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>
      97          _Hashtable;
      98        typedef _Hashtable_iterator<_Val, _Key, _HashFcn,
      99  				  _ExtractKey, _EqualKey, _Alloc>
     100          iterator;
     101        typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
     102  					_ExtractKey, _EqualKey, _Alloc>
     103          const_iterator;
     104        typedef _Hashtable_node<_Val> _Node;
     105        typedef std::forward_iterator_tag iterator_category;
     106        typedef _Val value_type;
     107        typedef std::ptrdiff_t difference_type;
     108        typedef std::size_t size_type;
     109        typedef _Val& reference;
     110        typedef _Val* pointer;
     111        
     112        _Node* _M_cur;
     113        _Hashtable* _M_ht;
     114  
     115        _Hashtable_iterator(_Node* __n, _Hashtable* __tab)
     116        : _M_cur(__n), _M_ht(__tab) { }
     117  
     118        _Hashtable_iterator() { }
     119  
     120        reference
     121        operator*() const
     122        { return _M_cur->_M_val; }
     123  
     124        pointer
     125        operator->() const
     126        { return &(operator*()); }
     127  
     128        iterator&
     129        operator++();
     130  
     131        iterator
     132        operator++(int);
     133  
     134        bool
     135        operator==(const iterator& __it) const
     136        { return _M_cur == __it._M_cur; }
     137  
     138        bool
     139        operator!=(const iterator& __it) const
     140        { return _M_cur != __it._M_cur; }
     141      };
     142  
     143    template<class _Val, class _Key, class _HashFcn,
     144  	   class _ExtractKey, class _EqualKey, class _Alloc>
     145      struct _Hashtable_const_iterator
     146      {
     147        typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>
     148          _Hashtable;
     149        typedef _Hashtable_iterator<_Val,_Key,_HashFcn,
     150  				  _ExtractKey,_EqualKey,_Alloc>
     151          iterator;
     152        typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
     153  					_ExtractKey, _EqualKey, _Alloc>
     154          const_iterator;
     155        typedef _Hashtable_node<_Val> _Node;
     156  
     157        typedef std::forward_iterator_tag iterator_category;
     158        typedef _Val value_type;
     159        typedef std::ptrdiff_t difference_type;
     160        typedef std::size_t size_type;
     161        typedef const _Val& reference;
     162        typedef const _Val* pointer;
     163        
     164        const _Node* _M_cur;
     165        const _Hashtable* _M_ht;
     166  
     167        _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab)
     168        : _M_cur(__n), _M_ht(__tab) { }
     169  
     170        _Hashtable_const_iterator() { }
     171  
     172        _Hashtable_const_iterator(const iterator& __it)
     173        : _M_cur(__it._M_cur), _M_ht(__it._M_ht) { }
     174  
     175        reference
     176        operator*() const
     177        { return _M_cur->_M_val; }
     178  
     179        pointer
     180        operator->() const
     181        { return &(operator*()); }
     182  
     183        const_iterator&
     184        operator++();
     185  
     186        const_iterator
     187        operator++(int);
     188  
     189        bool
     190        operator==(const const_iterator& __it) const
     191        { return _M_cur == __it._M_cur; }
     192  
     193        bool
     194        operator!=(const const_iterator& __it) const
     195        { return _M_cur != __it._M_cur; }
     196      };
     197  
     198    // Note: assumes long is at least 32 bits.
     199    enum { _S_num_primes = 29 };
     200  
     201    template<typename _PrimeType>
     202      struct _Hashtable_prime_list
     203      {
     204        static const _PrimeType  __stl_prime_list[_S_num_primes];
     205  
     206        static const _PrimeType*
     207        _S_get_prime_list();
     208      };
     209  
     210    template<typename _PrimeType> const _PrimeType
     211    _Hashtable_prime_list<_PrimeType>::__stl_prime_list[_S_num_primes] =
     212      {
     213        5ul,          53ul,         97ul,         193ul,       389ul,
     214        769ul,        1543ul,       3079ul,       6151ul,      12289ul,
     215        24593ul,      49157ul,      98317ul,      196613ul,    393241ul,
     216        786433ul,     1572869ul,    3145739ul,    6291469ul,   12582917ul,
     217        25165843ul,   50331653ul,   100663319ul,  201326611ul, 402653189ul,
     218        805306457ul,  1610612741ul, 3221225473ul, 4294967291ul
     219      };
     220  
     221   template<class _PrimeType> inline const _PrimeType*
     222   _Hashtable_prime_list<_PrimeType>::_S_get_prime_list()
     223   {
     224     return __stl_prime_list;
     225   }
     226  
     227    inline unsigned long
     228    __stl_next_prime(unsigned long __n)
     229    {
     230      const unsigned long* __first = _Hashtable_prime_list<unsigned long>::_S_get_prime_list();
     231      const unsigned long* __last = __first + (int)_S_num_primes;
     232      const unsigned long* pos = std::lower_bound(__first, __last, __n);
     233      return pos == __last ? *(__last - 1) : *pos;
     234    }
     235  
     236    // Forward declaration of operator==.  
     237    template<class _Val, class _Key, class _HF, class _Ex,
     238  	   class _Eq, class _All>
     239      class hashtable;
     240  
     241    template<class _Val, class _Key, class _HF, class _Ex,
     242  	   class _Eq, class _All>
     243      bool
     244      operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
     245  	       const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2);
     246  
     247    // Hashtables handle allocators a bit differently than other
     248    // containers do.  If we're using standard-conforming allocators, then
     249    // a hashtable unconditionally has a member variable to hold its
     250    // allocator, even if it so happens that all instances of the
     251    // allocator type are identical.  This is because, for hashtables,
     252    // this extra storage is negligible.  Additionally, a base class
     253    // wouldn't serve any other purposes; it wouldn't, for example,
     254    // simplify the exception-handling code.  
     255    template<class _Val, class _Key, class _HashFcn,
     256  	   class _ExtractKey, class _EqualKey, class _Alloc>
     257      class hashtable
     258      {
     259      public:
     260        typedef _Key key_type;
     261        typedef _Val value_type;
     262        typedef _HashFcn hasher;
     263        typedef _EqualKey key_equal;
     264  
     265        typedef std::size_t            size_type;
     266        typedef std::ptrdiff_t         difference_type;
     267        typedef value_type*       pointer;
     268        typedef const value_type* const_pointer;
     269        typedef value_type&       reference;
     270        typedef const value_type& const_reference;
     271  
     272        hasher
     273        hash_funct() const
     274        { return _M_hash; }
     275  
     276        key_equal
     277        key_eq() const
     278        { return _M_equals; }
     279  
     280      private:
     281        typedef _Hashtable_node<_Val> _Node;
     282  
     283      public:
     284        typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
     285  	rebind<value_type>::other allocator_type;
     286  
     287        allocator_type
     288        get_allocator() const
     289        { return _M_node_allocator; }
     290  
     291      private:
     292        typedef __gnu_cxx::__alloc_traits<allocator_type> _Alloc_traits;
     293        typedef typename _Alloc_traits::template rebind<_Node>::other
     294  	_Node_Alloc;
     295        typedef typename _Alloc_traits::template rebind<_Node*>::other
     296  	_Nodeptr_Alloc;
     297        typedef std::vector<_Node*, _Nodeptr_Alloc> _Vector_type;
     298  
     299        _Node_Alloc _M_node_allocator;
     300  
     301        _Node*
     302        _M_get_node()
     303        { return _M_node_allocator.allocate(1); }
     304  
     305        void
     306        _M_put_node(_Node* __p)
     307        { _M_node_allocator.deallocate(__p, 1); }
     308  
     309      private:
     310        hasher                _M_hash;
     311        key_equal             _M_equals;
     312        _ExtractKey           _M_get_key;
     313        _Vector_type          _M_buckets;
     314        size_type             _M_num_elements;
     315        
     316      public:
     317        typedef _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey,
     318  				  _EqualKey, _Alloc>
     319          iterator;
     320        typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey,
     321  					_EqualKey, _Alloc>
     322          const_iterator;
     323  
     324        friend struct
     325        _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>;
     326  
     327        friend struct
     328        _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey,
     329  				_EqualKey, _Alloc>;
     330  
     331      public:
     332        hashtable(size_type __n, const _HashFcn& __hf,
     333  		const _EqualKey& __eql, const _ExtractKey& __ext,
     334  		const allocator_type& __a = allocator_type())
     335        : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql),
     336  	_M_get_key(__ext), _M_buckets(__a), _M_num_elements(0)
     337        { _M_initialize_buckets(__n); }
     338  
     339        hashtable(size_type __n, const _HashFcn& __hf,
     340  		const _EqualKey& __eql,
     341  		const allocator_type& __a = allocator_type())
     342        : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql),
     343  	_M_get_key(_ExtractKey()), _M_buckets(__a), _M_num_elements(0)
     344        { _M_initialize_buckets(__n); }
     345  
     346        hashtable(const hashtable& __ht)
     347        : _M_node_allocator(__ht.get_allocator()), _M_hash(__ht._M_hash),
     348        _M_equals(__ht._M_equals), _M_get_key(__ht._M_get_key),
     349        _M_buckets(__ht.get_allocator()), _M_num_elements(0)
     350        { _M_copy_from(__ht); }
     351  
     352        hashtable&
     353        operator= (const hashtable& __ht)
     354        {
     355  	if (&__ht != this)
     356  	  {
     357  	    clear();
     358  	    _M_hash = __ht._M_hash;
     359  	    _M_equals = __ht._M_equals;
     360  	    _M_get_key = __ht._M_get_key;
     361  	    _M_copy_from(__ht);
     362  	  }
     363  	return *this;
     364        }
     365  
     366        ~hashtable()
     367        { clear(); }
     368  
     369        size_type
     370        size() const
     371        { return _M_num_elements; }
     372  
     373        size_type
     374        max_size() const
     375        { return size_type(-1); }
     376  
     377        _GLIBCXX_NODISCARD bool
     378        empty() const
     379        { return size() == 0; }
     380  
     381        void
     382        swap(hashtable& __ht)
     383        {
     384  	std::swap(_M_hash, __ht._M_hash);
     385  	std::swap(_M_equals, __ht._M_equals);
     386  	std::swap(_M_get_key, __ht._M_get_key);
     387  	_M_buckets.swap(__ht._M_buckets);
     388  	std::swap(_M_num_elements, __ht._M_num_elements);
     389        }
     390  
     391        iterator
     392        begin()
     393        {
     394  	for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
     395  	  if (_M_buckets[__n])
     396  	    return iterator(_M_buckets[__n], this);
     397  	return end();
     398        }
     399  
     400        iterator
     401        end()
     402        { return iterator(0, this); }
     403  
     404        const_iterator
     405        begin() const
     406        {
     407  	for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
     408  	  if (_M_buckets[__n])
     409  	    return const_iterator(_M_buckets[__n], this);
     410  	return end();
     411        }
     412  
     413        const_iterator
     414        end() const
     415        { return const_iterator(0, this); }
     416  
     417        template<class _Vl, class _Ky, class _HF, class _Ex, class _Eq,
     418  		class _Al>
     419          friend bool
     420          operator==(const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&,
     421  		   const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&);
     422  
     423      public:
     424        size_type
     425        bucket_count() const
     426        { return _M_buckets.size(); }
     427  
     428        size_type
     429        max_bucket_count() const
     430        { return _Hashtable_prime_list<unsigned long>::
     431                 _S_get_prime_list()[(int)_S_num_primes - 1];
     432        }
     433  
     434        size_type
     435        elems_in_bucket(size_type __bucket) const
     436        {
     437  	size_type __result = 0;
     438  	for (_Node* __n = _M_buckets[__bucket]; __n; __n = __n->_M_next)
     439  	  __result += 1;
     440  	return __result;
     441        }
     442  
     443        std::pair<iterator, bool>
     444        insert_unique(const value_type& __obj)
     445        {
     446  	resize(_M_num_elements + 1);
     447  	return insert_unique_noresize(__obj);
     448        }
     449  
     450        iterator
     451        insert_equal(const value_type& __obj)
     452        {
     453  	resize(_M_num_elements + 1);
     454  	return insert_equal_noresize(__obj);
     455        }
     456  
     457        std::pair<iterator, bool>
     458        insert_unique_noresize(const value_type& __obj);
     459  
     460        iterator
     461        insert_equal_noresize(const value_type& __obj);
     462  
     463        template<class _InputIterator>
     464          void
     465          insert_unique(_InputIterator __f, _InputIterator __l)
     466          { insert_unique(__f, __l, std::__iterator_category(__f)); }
     467  
     468        template<class _InputIterator>
     469          void
     470          insert_equal(_InputIterator __f, _InputIterator __l)
     471          { insert_equal(__f, __l, std::__iterator_category(__f)); }
     472  
     473        template<class _InputIterator>
     474          void
     475          insert_unique(_InputIterator __f, _InputIterator __l,
     476  		      std::input_iterator_tag)
     477          {
     478  	  for ( ; __f != __l; ++__f)
     479  	    insert_unique(*__f);
     480  	}
     481  
     482        template<class _InputIterator>
     483          void
     484          insert_equal(_InputIterator __f, _InputIterator __l,
     485  		     std::input_iterator_tag)
     486          {
     487  	  for ( ; __f != __l; ++__f)
     488  	    insert_equal(*__f);
     489  	}
     490  
     491        template<class _ForwardIterator>
     492          void
     493          insert_unique(_ForwardIterator __f, _ForwardIterator __l,
     494  		      std::forward_iterator_tag)
     495          {
     496  	  size_type __n = std::distance(__f, __l);
     497  	  resize(_M_num_elements + __n);
     498  	  for ( ; __n > 0; --__n, ++__f)
     499  	    insert_unique_noresize(*__f);
     500  	}
     501  
     502        template<class _ForwardIterator>
     503          void
     504          insert_equal(_ForwardIterator __f, _ForwardIterator __l,
     505  		     std::forward_iterator_tag)
     506          {
     507  	  size_type __n = std::distance(__f, __l);
     508  	  resize(_M_num_elements + __n);
     509  	  for ( ; __n > 0; --__n, ++__f)
     510  	    insert_equal_noresize(*__f);
     511  	}
     512  
     513        reference
     514        find_or_insert(const value_type& __obj);
     515  
     516        iterator
     517        find(const key_type& __key)
     518        {
     519  	size_type __n = _M_bkt_num_key(__key);
     520  	_Node* __first;
     521  	for (__first = _M_buckets[__n];
     522  	     __first && !_M_equals(_M_get_key(__first->_M_val), __key);
     523  	     __first = __first->_M_next)
     524  	  { }
     525  	return iterator(__first, this);
     526        }
     527  
     528        const_iterator
     529        find(const key_type& __key) const
     530        {
     531  	size_type __n = _M_bkt_num_key(__key);
     532  	const _Node* __first;
     533  	for (__first = _M_buckets[__n];
     534  	     __first && !_M_equals(_M_get_key(__first->_M_val), __key);
     535  	     __first = __first->_M_next)
     536  	  { }
     537  	return const_iterator(__first, this);
     538        }
     539  
     540        size_type
     541        count(const key_type& __key) const
     542        {
     543  	const size_type __n = _M_bkt_num_key(__key);
     544  	size_type __result = 0;
     545  	
     546  	for (const _Node* __cur = _M_buckets[__n]; __cur;
     547  	     __cur = __cur->_M_next)
     548  	  if (_M_equals(_M_get_key(__cur->_M_val), __key))
     549  	    ++__result;
     550  	return __result;
     551        }
     552  
     553        std::pair<iterator, iterator>
     554        equal_range(const key_type& __key);
     555  
     556        std::pair<const_iterator, const_iterator>
     557        equal_range(const key_type& __key) const;
     558  
     559        size_type
     560        erase(const key_type& __key);
     561        
     562        void
     563        erase(const iterator& __it);
     564  
     565        void
     566        erase(iterator __first, iterator __last);
     567  
     568        void
     569        erase(const const_iterator& __it);
     570  
     571        void
     572        erase(const_iterator __first, const_iterator __last);
     573  
     574        void
     575        resize(size_type __num_elements_hint);
     576  
     577        void
     578        clear();
     579  
     580      private:
     581        size_type
     582        _M_next_size(size_type __n) const
     583        { return __stl_next_prime(__n); }
     584  
     585        void
     586        _M_initialize_buckets(size_type __n)
     587        {
     588  	const size_type __n_buckets = _M_next_size(__n);
     589  	_M_buckets.reserve(__n_buckets);
     590  	_M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0);
     591  	_M_num_elements = 0;
     592        }
     593  
     594        size_type
     595        _M_bkt_num_key(const key_type& __key) const
     596        { return _M_bkt_num_key(__key, _M_buckets.size()); }
     597  
     598        size_type
     599        _M_bkt_num(const value_type& __obj) const
     600        { return _M_bkt_num_key(_M_get_key(__obj)); }
     601  
     602        size_type
     603        _M_bkt_num_key(const key_type& __key, std::size_t __n) const
     604        { return _M_hash(__key) % __n; }
     605  
     606        size_type
     607        _M_bkt_num(const value_type& __obj, std::size_t __n) const
     608        { return _M_bkt_num_key(_M_get_key(__obj), __n); }
     609  
     610        _Node*
     611        _M_new_node(const value_type& __obj)
     612        {
     613  	_Node* __n = _M_get_node();
     614  	__n->_M_next = 0;
     615  	__try
     616  	  {
     617  	    allocator_type __a = this->get_allocator();
     618  	    _Alloc_traits::construct(__a, &__n->_M_val, __obj);
     619  	    return __n;
     620  	  }
     621  	__catch(...)
     622  	  {
     623  	    _M_put_node(__n);
     624  	    __throw_exception_again;
     625  	  }
     626        }
     627  
     628        void
     629        _M_delete_node(_Node* __n)
     630        {
     631  	allocator_type __a = this->get_allocator();
     632  	_Alloc_traits::destroy(__a, &__n->_M_val);
     633  	_M_put_node(__n);
     634        }
     635        
     636        void
     637        _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last);
     638  
     639        void
     640        _M_erase_bucket(const size_type __n, _Node* __last);
     641  
     642        void
     643        _M_copy_from(const hashtable& __ht);
     644      };
     645  
     646    template<class _Val, class _Key, class _HF, class _ExK, class _EqK,
     647  	    class _All>
     648      _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>&
     649      _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
     650      operator++()
     651      {
     652        const _Node* __old = _M_cur;
     653        _M_cur = _M_cur->_M_next;
     654        if (!_M_cur)
     655  	{
     656  	  size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
     657  	  while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
     658  	    _M_cur = _M_ht->_M_buckets[__bucket];
     659  	}
     660        return *this;
     661      }
     662  
     663    template<class _Val, class _Key, class _HF, class _ExK, class _EqK,
     664  	    class _All>
     665      inline _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
     666      _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
     667      operator++(int)
     668      {
     669        iterator __tmp = *this;
     670        ++*this;
     671        return __tmp;
     672      }
     673  
     674    template<class _Val, class _Key, class _HF, class _ExK, class _EqK,
     675  	    class _All>
     676      _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>&
     677      _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
     678      operator++()
     679      {
     680        const _Node* __old = _M_cur;
     681        _M_cur = _M_cur->_M_next;
     682        if (!_M_cur)
     683  	{
     684  	  size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
     685  	  while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
     686  	    _M_cur = _M_ht->_M_buckets[__bucket];
     687  	}
     688        return *this;
     689      }
     690  
     691    template<class _Val, class _Key, class _HF, class _ExK, class _EqK,
     692  	    class _All>
     693      inline _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
     694      _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
     695      operator++(int)
     696      {
     697        const_iterator __tmp = *this;
     698        ++*this;
     699        return __tmp;
     700      }
     701  
     702    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
     703      bool
     704      operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
     705  	       const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2)
     706      {
     707        typedef typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_Node _Node;
     708  
     709        if (__ht1._M_buckets.size() != __ht2._M_buckets.size())
     710  	return false;
     711  
     712        for (std::size_t __n = 0; __n < __ht1._M_buckets.size(); ++__n)
     713  	{
     714  	  _Node* __cur1 = __ht1._M_buckets[__n];
     715  	  _Node* __cur2 = __ht2._M_buckets[__n];
     716  	  // Check same length of lists
     717  	  for (; __cur1 && __cur2;
     718  	       __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next)
     719  	    { } 
     720  	  if (__cur1 || __cur2)
     721  	    return false;
     722  	  // Now check one's elements are in the other
     723  	  for (__cur1 = __ht1._M_buckets[__n] ; __cur1;
     724  	       __cur1 = __cur1->_M_next)
     725  	    {
     726  	      bool _found__cur1 = false;
     727  	      for (__cur2 = __ht2._M_buckets[__n];
     728  		   __cur2; __cur2 = __cur2->_M_next)
     729  		{
     730  		  if (__cur1->_M_val == __cur2->_M_val)
     731  		    {
     732  		      _found__cur1 = true;
     733  		      break;
     734  		    }
     735  		}
     736  	      if (!_found__cur1)
     737  		return false;
     738  	    }
     739  	}
     740        return true;
     741      }
     742  
     743    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
     744      inline bool
     745      operator!=(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
     746  	       const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2)
     747      { return !(__ht1 == __ht2); }
     748  
     749    template<class _Val, class _Key, class _HF, class _Extract, class _EqKey,
     750  	    class _All>
     751      inline void
     752      swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1,
     753  	 hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2)
     754      { __ht1.swap(__ht2); }
     755  
     756    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
     757      std::pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator,
     758  	      bool>
     759      hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
     760      insert_unique_noresize(const value_type& __obj)
     761      {
     762        const size_type __n = _M_bkt_num(__obj);
     763        _Node* __first = _M_buckets[__n];
     764        
     765        for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
     766  	if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
     767  	  return std::pair<iterator, bool>(iterator(__cur, this), false);
     768        
     769        _Node* __tmp = _M_new_node(__obj);
     770        __tmp->_M_next = __first;
     771        _M_buckets[__n] = __tmp;
     772        ++_M_num_elements;
     773        return std::pair<iterator, bool>(iterator(__tmp, this), true);
     774      }
     775  
     776    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
     777      typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator
     778      hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
     779      insert_equal_noresize(const value_type& __obj)
     780      {
     781        const size_type __n = _M_bkt_num(__obj);
     782        _Node* __first = _M_buckets[__n];
     783        
     784        for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
     785  	if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
     786  	  {
     787  	    _Node* __tmp = _M_new_node(__obj);
     788  	    __tmp->_M_next = __cur->_M_next;
     789  	    __cur->_M_next = __tmp;
     790  	    ++_M_num_elements;
     791  	    return iterator(__tmp, this);
     792  	  }
     793  
     794        _Node* __tmp = _M_new_node(__obj);
     795        __tmp->_M_next = __first;
     796        _M_buckets[__n] = __tmp;
     797        ++_M_num_elements;
     798        return iterator(__tmp, this);
     799      }
     800  
     801    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
     802      typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::reference
     803      hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
     804      find_or_insert(const value_type& __obj)
     805      {
     806        resize(_M_num_elements + 1);
     807  
     808        size_type __n = _M_bkt_num(__obj);
     809        _Node* __first = _M_buckets[__n];
     810        
     811        for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
     812  	if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
     813  	  return __cur->_M_val;
     814        
     815        _Node* __tmp = _M_new_node(__obj);
     816        __tmp->_M_next = __first;
     817        _M_buckets[__n] = __tmp;
     818        ++_M_num_elements;
     819        return __tmp->_M_val;
     820      }
     821  
     822    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
     823      std::pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator,
     824  	      typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator>
     825      hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
     826      equal_range(const key_type& __key)
     827      {
     828        typedef std::pair<iterator, iterator> _Pii;
     829        const size_type __n = _M_bkt_num_key(__key);
     830  
     831        for (_Node* __first = _M_buckets[__n]; __first;
     832  	   __first = __first->_M_next)
     833  	if (_M_equals(_M_get_key(__first->_M_val), __key))
     834  	  {
     835  	    for (_Node* __cur = __first->_M_next; __cur;
     836  		 __cur = __cur->_M_next)
     837  	      if (!_M_equals(_M_get_key(__cur->_M_val), __key))
     838  		return _Pii(iterator(__first, this), iterator(__cur, this));
     839  	    for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
     840  	      if (_M_buckets[__m])
     841  		return _Pii(iterator(__first, this),
     842  			    iterator(_M_buckets[__m], this));
     843  	    return _Pii(iterator(__first, this), end());
     844  	  }
     845        return _Pii(end(), end());
     846      }
     847  
     848    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
     849      std::pair<
     850  	typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator,
     851  	typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator>
     852      hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
     853      equal_range(const key_type& __key) const
     854      {
     855        typedef std::pair<const_iterator, const_iterator> _Pii;
     856        const size_type __n = _M_bkt_num_key(__key);
     857  
     858        for (const _Node* __first = _M_buckets[__n]; __first;
     859  	   __first = __first->_M_next)
     860  	{
     861  	  if (_M_equals(_M_get_key(__first->_M_val), __key))
     862  	    {
     863  	      for (const _Node* __cur = __first->_M_next; __cur;
     864  		   __cur = __cur->_M_next)
     865  		if (!_M_equals(_M_get_key(__cur->_M_val), __key))
     866  		  return _Pii(const_iterator(__first, this),
     867  			      const_iterator(__cur, this));
     868  	      for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
     869  		if (_M_buckets[__m])
     870  		  return _Pii(const_iterator(__first, this),
     871  			      const_iterator(_M_buckets[__m], this));
     872  	      return _Pii(const_iterator(__first, this), end());
     873  	    }
     874  	}
     875        return _Pii(end(), end());
     876      }
     877  
     878    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
     879      typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::size_type
     880      hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
     881      erase(const key_type& __key)
     882      {
     883        const size_type __n = _M_bkt_num_key(__key);
     884        _Node* __first = _M_buckets[__n];
     885        _Node* __saved_slot = 0;
     886        size_type __erased = 0;
     887  
     888        if (__first)
     889  	{
     890  	  _Node* __cur = __first;
     891  	  _Node* __next = __cur->_M_next;
     892  	  while (__next)
     893  	    {
     894  	      if (_M_equals(_M_get_key(__next->_M_val), __key))
     895  		{
     896  		  if (&_M_get_key(__next->_M_val) != &__key)
     897  		    {
     898  		      __cur->_M_next = __next->_M_next;
     899  		      _M_delete_node(__next);
     900  		      __next = __cur->_M_next;
     901  		      ++__erased;
     902  		      --_M_num_elements;
     903  		    }
     904  		  else
     905  		    {
     906  		      __saved_slot = __cur;
     907  		      __cur = __next;
     908  		      __next = __cur->_M_next;
     909  		    }
     910  		}
     911  	      else
     912  		{
     913  		  __cur = __next;
     914  		  __next = __cur->_M_next;
     915  		}
     916  	    }
     917  	  bool __delete_first = _M_equals(_M_get_key(__first->_M_val), __key);
     918  	  if (__saved_slot)
     919  	    {
     920  	      __next = __saved_slot->_M_next;
     921  	      __saved_slot->_M_next = __next->_M_next;
     922  	      _M_delete_node(__next);
     923  	      ++__erased;
     924  	      --_M_num_elements;
     925  	    }
     926  	  if (__delete_first)
     927  	    {
     928  	      _M_buckets[__n] = __first->_M_next;
     929  	      _M_delete_node(__first);
     930  	      ++__erased;
     931  	      --_M_num_elements;
     932  	    }
     933  	}
     934        return __erased;
     935      }
     936  
     937    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
     938      void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
     939      erase(const iterator& __it)
     940      {
     941        _Node* __p = __it._M_cur;
     942        if (__p)
     943  	{
     944  	  const size_type __n = _M_bkt_num(__p->_M_val);
     945  	  _Node* __cur = _M_buckets[__n];
     946  	  
     947  	  if (__cur == __p)
     948  	    {
     949  	      _M_buckets[__n] = __cur->_M_next;
     950  	      _M_delete_node(__cur);
     951  	      --_M_num_elements;
     952  	    }
     953  	  else
     954  	    {
     955  	      _Node* __next = __cur->_M_next;
     956  	      while (__next)
     957  		{
     958  		  if (__next == __p)
     959  		    {
     960  		      __cur->_M_next = __next->_M_next;
     961  		      _M_delete_node(__next);
     962  		      --_M_num_elements;
     963  		      break;
     964  		    }
     965  		  else
     966  		    {
     967  		      __cur = __next;
     968  		      __next = __cur->_M_next;
     969  		    }
     970  		}
     971  	    }
     972  	}
     973      }
     974  
     975    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
     976      void
     977      hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
     978      erase(iterator __first, iterator __last)
     979      {
     980        size_type __f_bucket = __first._M_cur ? _M_bkt_num(__first._M_cur->_M_val)
     981  	                                    : _M_buckets.size();
     982  
     983        size_type __l_bucket = __last._M_cur ? _M_bkt_num(__last._M_cur->_M_val)
     984  	                                   : _M_buckets.size();
     985  
     986        if (__first._M_cur == __last._M_cur)
     987  	return;
     988        else if (__f_bucket == __l_bucket)
     989  	_M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur);
     990        else
     991  	{
     992  	  _M_erase_bucket(__f_bucket, __first._M_cur, 0);
     993  	  for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n)
     994  	    _M_erase_bucket(__n, 0);
     995  	  if (__l_bucket != _M_buckets.size())
     996  	    _M_erase_bucket(__l_bucket, __last._M_cur);
     997  	}
     998      }
     999  
    1000    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    1001      inline void
    1002      hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
    1003      erase(const_iterator __first, const_iterator __last)
    1004      {
    1005        erase(iterator(const_cast<_Node*>(__first._M_cur),
    1006  		     const_cast<hashtable*>(__first._M_ht)),
    1007  	    iterator(const_cast<_Node*>(__last._M_cur),
    1008  		     const_cast<hashtable*>(__last._M_ht)));
    1009      }
    1010  
    1011    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    1012      inline void
    1013      hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
    1014      erase(const const_iterator& __it)
    1015      { erase(iterator(const_cast<_Node*>(__it._M_cur),
    1016  		     const_cast<hashtable*>(__it._M_ht))); }
    1017  
    1018    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    1019      void
    1020      hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
    1021      resize(size_type __num_elements_hint)
    1022      {
    1023        const size_type __old_n = _M_buckets.size();
    1024        if (__num_elements_hint > __old_n)
    1025  	{
    1026  	  const size_type __n = _M_next_size(__num_elements_hint);
    1027  	  if (__n > __old_n)
    1028  	    {
    1029  	      _Vector_type __tmp(__n, (_Node*)(0), _M_buckets.get_allocator());
    1030  	      __try
    1031  		{
    1032  		  for (size_type __bucket = 0; __bucket < __old_n; ++__bucket)
    1033  		    {
    1034  		      _Node* __first = _M_buckets[__bucket];
    1035  		      while (__first)
    1036  			{
    1037  			  size_type __new_bucket = _M_bkt_num(__first->_M_val,
    1038  							      __n);
    1039  			  _M_buckets[__bucket] = __first->_M_next;
    1040  			  __first->_M_next = __tmp[__new_bucket];
    1041  			  __tmp[__new_bucket] = __first;
    1042  			  __first = _M_buckets[__bucket];
    1043  			}
    1044  		    }
    1045  		  _M_buckets.swap(__tmp);
    1046  		}
    1047  	      __catch(...)
    1048  		{
    1049  		  for (size_type __bucket = 0; __bucket < __tmp.size();
    1050  		       ++__bucket)
    1051  		    {
    1052  		      while (__tmp[__bucket])
    1053  			{
    1054  			  _Node* __next = __tmp[__bucket]->_M_next;
    1055  			  _M_delete_node(__tmp[__bucket]);
    1056  			  __tmp[__bucket] = __next;
    1057  			}
    1058  		    }
    1059  		  __throw_exception_again;
    1060  		}
    1061  	    }
    1062  	}
    1063      }
    1064  
    1065    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    1066      void
    1067      hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
    1068      _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last)
    1069      {
    1070        _Node* __cur = _M_buckets[__n];
    1071        if (__cur == __first)
    1072  	_M_erase_bucket(__n, __last);
    1073        else
    1074  	{
    1075  	  _Node* __next;
    1076  	  for (__next = __cur->_M_next;
    1077  	       __next != __first;
    1078  	       __cur = __next, __next = __cur->_M_next)
    1079  	    ;
    1080  	  while (__next != __last)
    1081  	    {
    1082  	      __cur->_M_next = __next->_M_next;
    1083  	      _M_delete_node(__next);
    1084  	      __next = __cur->_M_next;
    1085  	      --_M_num_elements;
    1086  	    }
    1087  	}
    1088      }
    1089  
    1090    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    1091      void
    1092      hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
    1093      _M_erase_bucket(const size_type __n, _Node* __last)
    1094      {
    1095        _Node* __cur = _M_buckets[__n];
    1096        while (__cur != __last)
    1097  	{
    1098  	  _Node* __next = __cur->_M_next;
    1099  	  _M_delete_node(__cur);
    1100  	  __cur = __next;
    1101  	  _M_buckets[__n] = __cur;
    1102  	  --_M_num_elements;
    1103  	}
    1104      }
    1105  
    1106    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    1107      void
    1108      hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
    1109      clear()
    1110      {
    1111        if (_M_num_elements == 0)
    1112  	return;
    1113  
    1114        for (size_type __i = 0; __i < _M_buckets.size(); ++__i)
    1115  	{
    1116  	  _Node* __cur = _M_buckets[__i];
    1117  	  while (__cur != 0)
    1118  	    {
    1119  	      _Node* __next = __cur->_M_next;
    1120  	      _M_delete_node(__cur);
    1121  	      __cur = __next;
    1122  	    }
    1123  	  _M_buckets[__i] = 0;
    1124  	}
    1125        _M_num_elements = 0;
    1126      }
    1127  
    1128    template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    1129      void
    1130      hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
    1131      _M_copy_from(const hashtable& __ht)
    1132      {
    1133        _M_buckets.clear();
    1134        _M_buckets.reserve(__ht._M_buckets.size());
    1135        _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0);
    1136        __try
    1137  	{
    1138  	  for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) {
    1139  	    const _Node* __cur = __ht._M_buckets[__i];
    1140  	    if (__cur)
    1141  	      {
    1142  		_Node* __local_copy = _M_new_node(__cur->_M_val);
    1143  		_M_buckets[__i] = __local_copy;
    1144  		
    1145  		for (_Node* __next = __cur->_M_next;
    1146  		     __next;
    1147  		     __cur = __next, __next = __cur->_M_next)
    1148  		  {
    1149  		    __local_copy->_M_next = _M_new_node(__next->_M_val);
    1150  		    __local_copy = __local_copy->_M_next;
    1151  		  }
    1152  	      }
    1153  	  }
    1154  	  _M_num_elements = __ht._M_num_elements;
    1155  	}
    1156        __catch(...)
    1157  	{
    1158  	  clear();
    1159  	  __throw_exception_again;
    1160  	}
    1161      }
    1162  
    1163  _GLIBCXX_END_NAMESPACE_VERSION
    1164  } // namespace
    1165  
    1166  #endif