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