Home | History | Annotate | Download | only in backward
      1 // Hashing map implementation -*- C++ -*-
      2 
      3 // Copyright (C) 2001, 2002, 2004, 2005, 2006, 2009 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /*
     26  * Copyright (c) 1996
     27  * Silicon Graphics Computer Systems, Inc.
     28  *
     29  * Permission to use, copy, modify, distribute and sell this software
     30  * and its documentation for any purpose is hereby granted without fee,
     31  * provided that the above copyright notice appear in all copies and
     32  * that both that copyright notice and this permission notice appear
     33  * in supporting documentation.  Silicon Graphics makes no
     34  * representations about the suitability of this software for any
     35  * purpose.  It is provided "as is" without express or implied warranty.
     36  *
     37  *
     38  * Copyright (c) 1994
     39  * Hewlett-Packard Company
     40  *
     41  * Permission to use, copy, modify, distribute and sell this software
     42  * and its documentation for any purpose is hereby granted without fee,
     43  * provided that the above copyright notice appear in all copies and
     44  * that both that copyright notice and this permission notice appear
     45  * in supporting documentation.  Hewlett-Packard Company makes no
     46  * representations about the suitability of this software for any
     47  * purpose.  It is provided "as is" without express or implied warranty.
     48  *
     49  */
     50 
     51 /** @file backward/hash_map
     52  *  This file is a GNU extension to the Standard C++ Library (possibly
     53  *  containing extensions from the HP/SGI STL subset).
     54  */
     55 
     56 #ifndef _HASH_MAP
     57 #define _HASH_MAP 1
     58 
     59 #ifndef _GLIBCXX_PERMIT_BACKWARD_HASH
     60 #include "backward_warning.h"
     61 #endif
     62 
     63 #include <bits/c++config.h>
     64 #include <backward/hashtable.h>
     65 #include <bits/concept_check.h>
     66 
     67 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
     68 
     69   using std::equal_to;
     70   using std::allocator;
     71   using std::pair;
     72   using std::_Select1st;
     73 
     74   /**
     75    *  This is an SGI extension.
     76    *  @ingroup SGIextensions
     77    *  @doctodo
     78    */
     79   template<class _Key, class _Tp, class _HashFn = hash<_Key>,
     80 	   class _EqualKey = equal_to<_Key>, class _Alloc = allocator<_Tp> >
     81     class hash_map
     82     {
     83     private:
     84       typedef hashtable<pair<const _Key, _Tp>,_Key, _HashFn,
     85 			_Select1st<pair<const _Key, _Tp> >,
     86 			_EqualKey, _Alloc> _Ht;
     87 
     88       _Ht _M_ht;
     89 
     90     public:
     91       typedef typename _Ht::key_type key_type;
     92       typedef _Tp data_type;
     93       typedef _Tp mapped_type;
     94       typedef typename _Ht::value_type value_type;
     95       typedef typename _Ht::hasher hasher;
     96       typedef typename _Ht::key_equal key_equal;
     97       
     98       typedef typename _Ht::size_type size_type;
     99       typedef typename _Ht::difference_type difference_type;
    100       typedef typename _Ht::pointer pointer;
    101       typedef typename _Ht::const_pointer const_pointer;
    102       typedef typename _Ht::reference reference;
    103       typedef typename _Ht::const_reference const_reference;
    104       
    105       typedef typename _Ht::iterator iterator;
    106       typedef typename _Ht::const_iterator const_iterator;
    107       
    108       typedef typename _Ht::allocator_type allocator_type;
    109       
    110       hasher
    111       hash_funct() const
    112       { return _M_ht.hash_funct(); }
    113 
    114       key_equal
    115       key_eq() const
    116       { return _M_ht.key_eq(); }
    117 
    118       allocator_type
    119       get_allocator() const
    120       { return _M_ht.get_allocator(); }
    121 
    122       hash_map()
    123       : _M_ht(100, hasher(), key_equal(), allocator_type()) {}
    124   
    125       explicit
    126       hash_map(size_type __n)
    127       : _M_ht(__n, hasher(), key_equal(), allocator_type()) {}
    128 
    129       hash_map(size_type __n, const hasher& __hf)
    130       : _M_ht(__n, __hf, key_equal(), allocator_type()) {}
    131 
    132       hash_map(size_type __n, const hasher& __hf, const key_equal& __eql,
    133 	       const allocator_type& __a = allocator_type())
    134       : _M_ht(__n, __hf, __eql, __a) {}
    135 
    136       template<class _InputIterator>
    137         hash_map(_InputIterator __f, _InputIterator __l)
    138 	: _M_ht(100, hasher(), key_equal(), allocator_type())
    139         { _M_ht.insert_unique(__f, __l); }
    140 
    141       template<class _InputIterator>
    142         hash_map(_InputIterator __f, _InputIterator __l, size_type __n)
    143 	: _M_ht(__n, hasher(), key_equal(), allocator_type())
    144         { _M_ht.insert_unique(__f, __l); }
    145 
    146       template<class _InputIterator>
    147         hash_map(_InputIterator __f, _InputIterator __l, size_type __n,
    148 		 const hasher& __hf)
    149 	: _M_ht(__n, __hf, key_equal(), allocator_type())
    150         { _M_ht.insert_unique(__f, __l); }
    151 
    152       template<class _InputIterator>
    153         hash_map(_InputIterator __f, _InputIterator __l, size_type __n,
    154 		 const hasher& __hf, const key_equal& __eql,
    155 		 const allocator_type& __a = allocator_type())
    156 	: _M_ht(__n, __hf, __eql, __a)
    157         { _M_ht.insert_unique(__f, __l); }
    158 
    159       size_type
    160       size() const
    161       { return _M_ht.size(); }
    162       
    163       size_type
    164       max_size() const
    165       { return _M_ht.max_size(); }
    166       
    167       bool
    168       empty() const
    169       { return _M_ht.empty(); }
    170   
    171       void
    172       swap(hash_map& __hs)
    173       { _M_ht.swap(__hs._M_ht); }
    174 
    175       template<class _K1, class _T1, class _HF, class _EqK, class _Al>
    176         friend bool
    177         operator== (const hash_map<_K1, _T1, _HF, _EqK, _Al>&,
    178 		    const hash_map<_K1, _T1, _HF, _EqK, _Al>&);
    179 
    180       iterator
    181       begin()
    182       { return _M_ht.begin(); }
    183 
    184       iterator
    185       end()
    186       { return _M_ht.end(); }
    187 
    188       const_iterator
    189       begin() const
    190       { return _M_ht.begin(); }
    191 
    192       const_iterator
    193       end() const
    194       { return _M_ht.end(); }
    195 
    196       pair<iterator, bool>
    197       insert(const value_type& __obj)
    198       { return _M_ht.insert_unique(__obj); }
    199 
    200       template<class _InputIterator>
    201         void
    202         insert(_InputIterator __f, _InputIterator __l)
    203         { _M_ht.insert_unique(__f, __l); }
    204 
    205       pair<iterator, bool>
    206       insert_noresize(const value_type& __obj)
    207       { return _M_ht.insert_unique_noresize(__obj); }
    208 
    209       iterator
    210       find(const key_type& __key)
    211       { return _M_ht.find(__key); }
    212 
    213       const_iterator
    214       find(const key_type& __key) const
    215       { return _M_ht.find(__key); }
    216 
    217       _Tp&
    218       operator[](const key_type& __key)
    219       { return _M_ht.find_or_insert(value_type(__key, _Tp())).second; }
    220 
    221       size_type
    222       count(const key_type& __key) const
    223       { return _M_ht.count(__key); }
    224 
    225       pair<iterator, iterator>
    226       equal_range(const key_type& __key)
    227       { return _M_ht.equal_range(__key); }
    228 
    229       pair<const_iterator, const_iterator>
    230       equal_range(const key_type& __key) const
    231       { return _M_ht.equal_range(__key); }
    232 
    233       size_type
    234       erase(const key_type& __key)
    235       {return _M_ht.erase(__key); }
    236 
    237       void
    238       erase(iterator __it)
    239       { _M_ht.erase(__it); }
    240 
    241       void
    242       erase(iterator __f, iterator __l)
    243       { _M_ht.erase(__f, __l); }
    244 
    245       void
    246       clear()
    247       { _M_ht.clear(); }
    248 
    249       void
    250       resize(size_type __hint)
    251       { _M_ht.resize(__hint); }
    252 
    253       size_type
    254       bucket_count() const
    255       { return _M_ht.bucket_count(); }
    256 
    257       size_type
    258       max_bucket_count() const
    259       { return _M_ht.max_bucket_count(); }
    260 
    261       size_type
    262       elems_in_bucket(size_type __n) const
    263       { return _M_ht.elems_in_bucket(__n); }
    264     };
    265 
    266   template<class _Key, class _Tp, class _HashFn, class _EqlKey, class _Alloc>
    267     inline bool
    268     operator==(const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1,
    269 	       const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2)
    270     { return __hm1._M_ht == __hm2._M_ht; }
    271 
    272   template<class _Key, class _Tp, class _HashFn, class _EqlKey, class _Alloc>
    273     inline bool
    274     operator!=(const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1,
    275 	       const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2)
    276     { return !(__hm1 == __hm2); }
    277 
    278   template<class _Key, class _Tp, class _HashFn, class _EqlKey, class _Alloc>
    279     inline void
    280     swap(hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1,
    281 	 hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2)
    282     { __hm1.swap(__hm2); }
    283 
    284 
    285   /**
    286    *  This is an SGI extension.
    287    *  @ingroup SGIextensions
    288    *  @doctodo
    289    */
    290   template<class _Key, class _Tp,
    291 	   class _HashFn = hash<_Key>,
    292 	   class _EqualKey = equal_to<_Key>,
    293 	   class _Alloc = allocator<_Tp> >
    294     class hash_multimap
    295     {
    296       // concept requirements
    297       __glibcxx_class_requires(_Key, _SGIAssignableConcept)
    298       __glibcxx_class_requires(_Tp, _SGIAssignableConcept)
    299       __glibcxx_class_requires3(_HashFn, size_t, _Key, _UnaryFunctionConcept)
    300       __glibcxx_class_requires3(_EqualKey, _Key, _Key, _BinaryPredicateConcept)
    301 	
    302     private:
    303       typedef hashtable<pair<const _Key, _Tp>, _Key, _HashFn,
    304 			_Select1st<pair<const _Key, _Tp> >, _EqualKey, _Alloc>
    305           _Ht;
    306 
    307       _Ht _M_ht;
    308 
    309     public:
    310       typedef typename _Ht::key_type key_type;
    311       typedef _Tp data_type;
    312       typedef _Tp mapped_type;
    313       typedef typename _Ht::value_type value_type;
    314       typedef typename _Ht::hasher hasher;
    315       typedef typename _Ht::key_equal key_equal;
    316       
    317       typedef typename _Ht::size_type size_type;
    318       typedef typename _Ht::difference_type difference_type;
    319       typedef typename _Ht::pointer pointer;
    320       typedef typename _Ht::const_pointer const_pointer;
    321       typedef typename _Ht::reference reference;
    322       typedef typename _Ht::const_reference const_reference;
    323       
    324       typedef typename _Ht::iterator iterator;
    325       typedef typename _Ht::const_iterator const_iterator;
    326       
    327       typedef typename _Ht::allocator_type allocator_type;
    328       
    329       hasher
    330       hash_funct() const
    331       { return _M_ht.hash_funct(); }
    332 
    333       key_equal
    334       key_eq() const
    335       { return _M_ht.key_eq(); }
    336 
    337       allocator_type
    338       get_allocator() const
    339       { return _M_ht.get_allocator(); }
    340 
    341       hash_multimap()
    342       : _M_ht(100, hasher(), key_equal(), allocator_type()) {}
    343 
    344       explicit
    345       hash_multimap(size_type __n)
    346       : _M_ht(__n, hasher(), key_equal(), allocator_type()) {}
    347 
    348       hash_multimap(size_type __n, const hasher& __hf)
    349       : _M_ht(__n, __hf, key_equal(), allocator_type()) {}
    350 
    351       hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql,
    352 		    const allocator_type& __a = allocator_type())
    353       : _M_ht(__n, __hf, __eql, __a) {}
    354 
    355       template<class _InputIterator>
    356         hash_multimap(_InputIterator __f, _InputIterator __l)
    357 	: _M_ht(100, hasher(), key_equal(), allocator_type())
    358         { _M_ht.insert_equal(__f, __l); }
    359 
    360       template<class _InputIterator>
    361         hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n)
    362 	: _M_ht(__n, hasher(), key_equal(), allocator_type())
    363         { _M_ht.insert_equal(__f, __l); }
    364 
    365       template<class _InputIterator>
    366         hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n,
    367 		      const hasher& __hf)
    368 	: _M_ht(__n, __hf, key_equal(), allocator_type())
    369         { _M_ht.insert_equal(__f, __l); }
    370 
    371       template<class _InputIterator>
    372         hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n,
    373 		      const hasher& __hf, const key_equal& __eql,
    374 		      const allocator_type& __a = allocator_type())
    375 	: _M_ht(__n, __hf, __eql, __a)
    376         { _M_ht.insert_equal(__f, __l); }
    377 
    378       size_type
    379       size() const
    380       { return _M_ht.size(); }
    381 
    382       size_type
    383       max_size() const
    384       { return _M_ht.max_size(); }
    385 
    386       bool
    387       empty() const
    388       { return _M_ht.empty(); }
    389 
    390       void
    391       swap(hash_multimap& __hs)
    392       { _M_ht.swap(__hs._M_ht); }
    393 
    394       template<class _K1, class _T1, class _HF, class _EqK, class _Al>
    395         friend bool
    396         operator==(const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&,
    397 		   const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&);
    398 
    399       iterator
    400       begin()
    401       { return _M_ht.begin(); }
    402 
    403       iterator
    404       end()
    405       { return _M_ht.end(); }
    406 
    407       const_iterator
    408       begin() const
    409       { return _M_ht.begin(); }
    410 
    411       const_iterator
    412       end() const
    413       { return _M_ht.end(); }
    414 
    415       iterator
    416       insert(const value_type& __obj)
    417       { return _M_ht.insert_equal(__obj); }
    418 
    419       template<class _InputIterator>
    420         void
    421         insert(_InputIterator __f, _InputIterator __l)
    422         { _M_ht.insert_equal(__f,__l); }
    423 
    424       iterator
    425       insert_noresize(const value_type& __obj)
    426       { return _M_ht.insert_equal_noresize(__obj); }
    427 
    428       iterator
    429       find(const key_type& __key)
    430       { return _M_ht.find(__key); }
    431 
    432       const_iterator
    433       find(const key_type& __key) const
    434       { return _M_ht.find(__key); }
    435 
    436       size_type
    437       count(const key_type& __key) const
    438       { return _M_ht.count(__key); }
    439 
    440       pair<iterator, iterator>
    441       equal_range(const key_type& __key)
    442       { return _M_ht.equal_range(__key); }
    443 
    444       pair<const_iterator, const_iterator>
    445       equal_range(const key_type& __key) const
    446       { return _M_ht.equal_range(__key); }
    447 
    448       size_type
    449       erase(const key_type& __key)
    450       { return _M_ht.erase(__key); }
    451 
    452       void
    453       erase(iterator __it)
    454       { _M_ht.erase(__it); }
    455 
    456       void
    457       erase(iterator __f, iterator __l)
    458       { _M_ht.erase(__f, __l); }
    459 
    460       void
    461       clear()
    462       { _M_ht.clear(); }
    463 
    464       void
    465       resize(size_type __hint)
    466       { _M_ht.resize(__hint); }
    467 
    468       size_type
    469       bucket_count() const
    470       { return _M_ht.bucket_count(); }
    471 
    472       size_type
    473       max_bucket_count() const
    474       { return _M_ht.max_bucket_count(); }
    475       
    476       size_type
    477       elems_in_bucket(size_type __n) const
    478       { return _M_ht.elems_in_bucket(__n); }
    479     };
    480 
    481   template<class _Key, class _Tp, class _HF, class _EqKey, class _Alloc>
    482     inline bool
    483     operator==(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1,
    484 	       const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2)
    485     { return __hm1._M_ht == __hm2._M_ht; }
    486 
    487   template<class _Key, class _Tp, class _HF, class _EqKey, class _Alloc>
    488     inline bool
    489     operator!=(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1,
    490 	       const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2)
    491     { return !(__hm1 == __hm2); }
    492 
    493   template<class _Key, class _Tp, class _HashFn, class _EqlKey, class _Alloc>
    494     inline void
    495     swap(hash_multimap<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1,
    496 	 hash_multimap<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2)
    497     { __hm1.swap(__hm2); }
    498 
    499 _GLIBCXX_END_NAMESPACE
    500 
    501 _GLIBCXX_BEGIN_NAMESPACE(std)
    502 
    503   // Specialization of insert_iterator so that it will work for hash_map
    504   // and hash_multimap.
    505   template<class _Key, class _Tp, class _HashFn,  class _EqKey, class _Alloc>
    506     class insert_iterator<__gnu_cxx::hash_map<_Key, _Tp, _HashFn, 
    507 					      _EqKey, _Alloc> >
    508     {
    509     protected:
    510       typedef __gnu_cxx::hash_map<_Key, _Tp, _HashFn, _EqKey, _Alloc>
    511         _Container;
    512       _Container* container;
    513 
    514     public:
    515       typedef _Container          container_type;
    516       typedef output_iterator_tag iterator_category;
    517       typedef void                value_type;
    518       typedef void                difference_type;
    519       typedef void                pointer;
    520       typedef void                reference;
    521       
    522       insert_iterator(_Container& __x)
    523       : container(&__x) {}
    524 
    525       insert_iterator(_Container& __x, typename _Container::iterator)
    526       : container(&__x) {}
    527 
    528       insert_iterator<_Container>&
    529       operator=(const typename _Container::value_type& __value)
    530       {
    531 	container->insert(__value);
    532 	return *this;
    533       }
    534 
    535       insert_iterator<_Container>&
    536       operator*()
    537       { return *this; }
    538 
    539       insert_iterator<_Container>&
    540       operator++() { return *this; }
    541 
    542       insert_iterator<_Container>&
    543       operator++(int)
    544       { return *this; }
    545     };
    546 
    547   template<class _Key, class _Tp, class _HashFn,  class _EqKey, class _Alloc>
    548     class insert_iterator<__gnu_cxx::hash_multimap<_Key, _Tp, _HashFn,
    549 						   _EqKey, _Alloc> >
    550     {
    551     protected:
    552       typedef __gnu_cxx::hash_multimap<_Key, _Tp, _HashFn, _EqKey, _Alloc>
    553         _Container;
    554       _Container* container;
    555       typename _Container::iterator iter;
    556 
    557     public:
    558       typedef _Container          container_type;
    559       typedef output_iterator_tag iterator_category;
    560       typedef void                value_type;
    561       typedef void                difference_type;
    562       typedef void                pointer;
    563       typedef void                reference;
    564 
    565       insert_iterator(_Container& __x)
    566       : container(&__x) {}
    567 
    568       insert_iterator(_Container& __x, typename _Container::iterator)
    569       : container(&__x) {}
    570 
    571       insert_iterator<_Container>&
    572       operator=(const typename _Container::value_type& __value)
    573       {
    574 	container->insert(__value);
    575 	return *this;
    576       }
    577 
    578       insert_iterator<_Container>&
    579       operator*()
    580       { return *this; }
    581 
    582       insert_iterator<_Container>&
    583       operator++()
    584       { return *this; }
    585 
    586       insert_iterator<_Container>&
    587       operator++(int)
    588       { return *this; }
    589     };
    590 
    591 _GLIBCXX_END_NAMESPACE
    592 
    593 #endif
    594