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