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