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