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