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