1169691Skan// -*- C++ -*-
2169691Skan
3169691Skan// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
4169691Skan//
5169691Skan// This file is part of the GNU ISO C++ Library.  This library is free
6169691Skan// software; you can redistribute it and/or modify it under the terms
7169691Skan// of the GNU General Public License as published by the Free Software
8169691Skan// Foundation; either version 2, or (at your option) any later
9169691Skan// version.
10169691Skan
11169691Skan// This library is distributed in the hope that it will be useful, but
12169691Skan// WITHOUT ANY WARRANTY; without even the implied warranty of
13169691Skan// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14169691Skan// General Public License for more details.
15169691Skan
16169691Skan// You should have received a copy of the GNU General Public License
17169691Skan// along with this library; see the file COPYING.  If not, write to
18169691Skan// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
19169691Skan// MA 02111-1307, USA.
20169691Skan
21169691Skan// As a special exception, you may use this file as part of a free
22169691Skan// software library without restriction.  Specifically, if other files
23169691Skan// instantiate templates or use macros or inline functions from this
24169691Skan// file, or you compile this file and link it with other files to
25169691Skan// produce an executable, this file does not by itself cause the
26169691Skan// resulting executable to be covered by the GNU General Public
27169691Skan// License.  This exception does not however invalidate any other
28169691Skan// reasons why the executable file might be covered by the GNU General
29169691Skan// Public License.
30169691Skan
31169691Skan// Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
32169691Skan
33169691Skan// Permission to use, copy, modify, sell, and distribute this software
34169691Skan// is hereby granted without fee, provided that the above copyright
35169691Skan// notice appears in all copies, and that both that copyright notice
36169691Skan// and this permission notice appear in supporting documentation. None
37169691Skan// of the above authors, nor IBM Haifa Research Laboratories, make any
38169691Skan// representation about the suitability of this software for any
39169691Skan// purpose. It is provided "as is" without express or implied
40169691Skan// warranty.
41169691Skan
42169691Skan/**
43169691Skan * @file ranged_probe_fn.hpp
44169691Skan * Contains a unified ranged probe functor, allowing the probe tables to deal with
45169691Skan *    a single class for ranged probeing.
46169691Skan */
47169691Skan
48169691Skan#ifndef PB_DS_RANGED_PROBE_FN_HPP
49169691Skan#define PB_DS_RANGED_PROBE_FN_HPP
50169691Skan
51169691Skan#include <ext/pb_ds/detail/basic_types.hpp>
52169691Skan#include <utility>
53169691Skan#include <debug/debug.h>
54169691Skan
55169691Skannamespace pb_ds
56169691Skan{
57169691Skan  namespace detail
58169691Skan  {
59169691Skan    template<typename Key, typename Hash_Fn, typename Allocator,
60169691Skan	     typename Comb_Probe_Fn, typename Probe_Fn, bool Store_Hash>
61169691Skan    class ranged_probe_fn;
62169691Skan
63169691Skan#define PB_DS_CLASS_T_DEC \
64169691Skan    template<typename Key, typename Hash_Fn, typename Allocator, \
65169691Skan	     typename Comb_Probe_Fn, typename Probe_Fn>
66169691Skan
67169691Skan#define PB_DS_CLASS_C_DEC \
68169691Skan    ranged_probe_fn<Key, Hash_Fn, Allocator, Comb_Probe_Fn, Probe_Fn, false>
69169691Skan
70169691Skan    /**
71169691Skan     * Specialization 1
72169691Skan     * The client supplies a probe function and a ranged probe
73169691Skan     * function, and requests that hash values not be stored.
74169691Skan     **/
75169691Skan    template<typename Key, typename Hash_Fn, typename Allocator,
76169691Skan	     typename Comb_Probe_Fn, typename Probe_Fn>
77169691Skan    class ranged_probe_fn<Key, Hash_Fn, Allocator, Comb_Probe_Fn,
78169691Skan			  Probe_Fn, false>
79169691Skan    : public Hash_Fn, public Comb_Probe_Fn, public Probe_Fn
80169691Skan    {
81169691Skan    protected:
82169691Skan      typedef typename Allocator::size_type size_type;
83169691Skan      typedef Comb_Probe_Fn comb_probe_fn_base;
84169691Skan      typedef Hash_Fn hash_fn_base;
85169691Skan      typedef Probe_Fn probe_fn_base;
86169691Skan      typedef typename Allocator::template rebind<Key>::other key_allocator;
87169691Skan      typedef typename key_allocator::const_reference const_key_reference;
88169691Skan
89169691Skan      ranged_probe_fn(size_type);
90169691Skan
91169691Skan      ranged_probe_fn(size_type, const Hash_Fn&);
92169691Skan
93169691Skan      ranged_probe_fn(size_type, const Hash_Fn&, const Comb_Probe_Fn&);
94169691Skan
95169691Skan      ranged_probe_fn(size_type, const Hash_Fn&, const Comb_Probe_Fn&,
96169691Skan		      const Probe_Fn&);
97169691Skan
98169691Skan      void
99169691Skan      swap(PB_DS_CLASS_C_DEC&);
100169691Skan
101169691Skan      void
102169691Skan      notify_resized(size_type);
103169691Skan
104169691Skan      inline size_type
105169691Skan      operator()(const_key_reference) const;
106169691Skan
107169691Skan      inline size_type
108169691Skan      operator()(const_key_reference, size_type, size_type) const;
109169691Skan    };
110169691Skan
111169691Skan    PB_DS_CLASS_T_DEC
112169691Skan    PB_DS_CLASS_C_DEC::
113169691Skan    ranged_probe_fn(size_type size)
114169691Skan    { Comb_Probe_Fn::notify_resized(size); }
115169691Skan
116169691Skan    PB_DS_CLASS_T_DEC
117169691Skan    PB_DS_CLASS_C_DEC::
118169691Skan    ranged_probe_fn(size_type size, const Hash_Fn& r_hash_fn)
119169691Skan    : Hash_Fn(r_hash_fn)
120169691Skan    { Comb_Probe_Fn::notify_resized(size); }
121169691Skan
122169691Skan    PB_DS_CLASS_T_DEC
123169691Skan    PB_DS_CLASS_C_DEC::
124169691Skan    ranged_probe_fn(size_type size, const Hash_Fn& r_hash_fn,
125169691Skan		    const Comb_Probe_Fn& r_comb_probe_fn)
126169691Skan    : Hash_Fn(r_hash_fn), Comb_Probe_Fn(r_comb_probe_fn)
127169691Skan    { comb_probe_fn_base::notify_resized(size); }
128169691Skan
129169691Skan    PB_DS_CLASS_T_DEC
130169691Skan    PB_DS_CLASS_C_DEC::
131169691Skan    ranged_probe_fn(size_type size, const Hash_Fn& r_hash_fn,
132169691Skan		    const Comb_Probe_Fn& r_comb_probe_fn,
133169691Skan		    const Probe_Fn& r_probe_fn)
134169691Skan    : Hash_Fn(r_hash_fn), Comb_Probe_Fn(r_comb_probe_fn), Probe_Fn(r_probe_fn)
135169691Skan    { comb_probe_fn_base::notify_resized(size); }
136169691Skan
137169691Skan    PB_DS_CLASS_T_DEC
138169691Skan    void
139169691Skan    PB_DS_CLASS_C_DEC::
140169691Skan    swap(PB_DS_CLASS_C_DEC& other)
141169691Skan    {
142169691Skan      comb_probe_fn_base::swap(other);
143169691Skan      std::swap((Hash_Fn& )(*this), (Hash_Fn&)other);
144169691Skan    }
145169691Skan
146169691Skan    PB_DS_CLASS_T_DEC
147169691Skan    void
148169691Skan    PB_DS_CLASS_C_DEC::
149169691Skan    notify_resized(size_type size)
150169691Skan    { comb_probe_fn_base::notify_resized(size); }
151169691Skan
152169691Skan    PB_DS_CLASS_T_DEC
153169691Skan    inline typename PB_DS_CLASS_C_DEC::size_type
154169691Skan    PB_DS_CLASS_C_DEC::
155169691Skan    operator()(const_key_reference r_key) const
156169691Skan    { return comb_probe_fn_base::operator()(hash_fn_base::operator()(r_key)); }
157169691Skan
158169691Skan    PB_DS_CLASS_T_DEC
159169691Skan    inline typename PB_DS_CLASS_C_DEC::size_type
160169691Skan    PB_DS_CLASS_C_DEC::
161169691Skan    operator()(const_key_reference, size_type hash, size_type i) const
162169691Skan    {
163169691Skan      return comb_probe_fn_base::operator()(hash + probe_fn_base::operator()(i));
164169691Skan    }
165169691Skan
166169691Skan#undef PB_DS_CLASS_T_DEC
167169691Skan#undef PB_DS_CLASS_C_DEC
168169691Skan
169169691Skan#define PB_DS_CLASS_T_DEC \
170169691Skan    template<typename Key, typename Hash_Fn, typename Allocator, \
171169691Skan	     typename Comb_Probe_Fn, typename Probe_Fn>
172169691Skan
173169691Skan#define PB_DS_CLASS_C_DEC \
174169691Skan    ranged_probe_fn<Key, Hash_Fn, Allocator, Comb_Probe_Fn, Probe_Fn, true>
175169691Skan
176169691Skan    /**
177169691Skan     * Specialization 2- The client supplies a probe function and a ranged
178169691Skan     *    probe function, and requests that hash values not be stored.
179169691Skan     **/
180169691Skan    template<typename Key, typename Hash_Fn, typename Allocator,
181169691Skan	     typename Comb_Probe_Fn, typename Probe_Fn>
182169691Skan    class ranged_probe_fn<Key, Hash_Fn, Allocator, Comb_Probe_Fn,
183169691Skan			  Probe_Fn, true>
184169691Skan    : public Hash_Fn, public Comb_Probe_Fn, public Probe_Fn
185169691Skan    {
186169691Skan    protected:
187169691Skan      typedef typename Allocator::size_type size_type;
188169691Skan      typedef std::pair<size_type, size_type> comp_hash;
189169691Skan      typedef Comb_Probe_Fn comb_probe_fn_base;
190169691Skan      typedef Hash_Fn hash_fn_base;
191169691Skan      typedef Probe_Fn probe_fn_base;
192169691Skan      typedef typename Allocator::template rebind<Key>::other key_allocator;
193169691Skan      typedef typename key_allocator::const_reference const_key_reference;
194169691Skan
195169691Skan      ranged_probe_fn(size_type);
196169691Skan
197169691Skan      ranged_probe_fn(size_type, const Hash_Fn&);
198169691Skan
199169691Skan      ranged_probe_fn(size_type, const Hash_Fn&,
200169691Skan		      const Comb_Probe_Fn&);
201169691Skan
202169691Skan      ranged_probe_fn(size_type, const Hash_Fn&, const Comb_Probe_Fn&,
203169691Skan		      const Probe_Fn&);
204169691Skan
205169691Skan      void
206169691Skan      swap(PB_DS_CLASS_C_DEC&);
207169691Skan
208169691Skan      void
209169691Skan      notify_resized(size_type);
210169691Skan
211169691Skan      inline comp_hash
212169691Skan      operator()(const_key_reference) const;
213169691Skan
214169691Skan      inline size_type
215169691Skan      operator()(const_key_reference, size_type, size_type) const;
216169691Skan
217169691Skan      inline size_type
218169691Skan      operator()(const_key_reference, size_type) const;
219169691Skan    };
220169691Skan
221169691Skan    PB_DS_CLASS_T_DEC
222169691Skan    PB_DS_CLASS_C_DEC::
223169691Skan    ranged_probe_fn(size_type size)
224169691Skan    { Comb_Probe_Fn::notify_resized(size); }
225169691Skan
226169691Skan    PB_DS_CLASS_T_DEC
227169691Skan    PB_DS_CLASS_C_DEC::
228169691Skan    ranged_probe_fn(size_type size, const Hash_Fn& r_hash_fn)
229169691Skan    : Hash_Fn(r_hash_fn)
230169691Skan    { Comb_Probe_Fn::notify_resized(size); }
231169691Skan
232169691Skan    PB_DS_CLASS_T_DEC
233169691Skan    PB_DS_CLASS_C_DEC::
234169691Skan    ranged_probe_fn(size_type size, const Hash_Fn& r_hash_fn,
235169691Skan		    const Comb_Probe_Fn& r_comb_probe_fn)
236169691Skan    : Hash_Fn(r_hash_fn), Comb_Probe_Fn(r_comb_probe_fn)
237169691Skan    { comb_probe_fn_base::notify_resized(size); }
238169691Skan
239169691Skan    PB_DS_CLASS_T_DEC
240169691Skan    PB_DS_CLASS_C_DEC::
241169691Skan    ranged_probe_fn(size_type size, const Hash_Fn& r_hash_fn,
242169691Skan		    const Comb_Probe_Fn& r_comb_probe_fn,
243169691Skan		    const Probe_Fn& r_probe_fn)
244169691Skan    : Hash_Fn(r_hash_fn), Comb_Probe_Fn(r_comb_probe_fn), Probe_Fn(r_probe_fn)
245169691Skan    { comb_probe_fn_base::notify_resized(size); }
246169691Skan
247169691Skan    PB_DS_CLASS_T_DEC
248169691Skan    void
249169691Skan    PB_DS_CLASS_C_DEC::
250169691Skan    swap(PB_DS_CLASS_C_DEC& other)
251169691Skan    {
252169691Skan      comb_probe_fn_base::swap(other);
253169691Skan      std::swap((Hash_Fn& )(*this), (Hash_Fn& )other);
254169691Skan    }
255169691Skan
256169691Skan    PB_DS_CLASS_T_DEC
257169691Skan    void
258169691Skan    PB_DS_CLASS_C_DEC::
259169691Skan    notify_resized(size_type size)
260169691Skan    { comb_probe_fn_base::notify_resized(size); }
261169691Skan
262169691Skan    PB_DS_CLASS_T_DEC
263169691Skan    inline typename PB_DS_CLASS_C_DEC::comp_hash
264169691Skan    PB_DS_CLASS_C_DEC::
265169691Skan    operator()(const_key_reference r_key) const
266169691Skan    {
267169691Skan      const size_type hash = hash_fn_base::operator()(r_key);
268169691Skan      return std::make_pair(comb_probe_fn_base::operator()(hash), hash);
269169691Skan    }
270169691Skan
271169691Skan    PB_DS_CLASS_T_DEC
272169691Skan    inline typename PB_DS_CLASS_C_DEC::size_type
273169691Skan    PB_DS_CLASS_C_DEC::
274169691Skan    operator()(const_key_reference, size_type hash, size_type i) const
275169691Skan    {
276169691Skan      return comb_probe_fn_base::operator()(hash + probe_fn_base::operator()(i));
277169691Skan    }
278169691Skan
279169691Skan    PB_DS_CLASS_T_DEC
280169691Skan    inline typename PB_DS_CLASS_C_DEC::size_type
281169691Skan    PB_DS_CLASS_C_DEC::
282169691Skan    operator()
283169691Skan#ifdef _GLIBCXX_DEBUG
284169691Skan      (const_key_reference r_key, size_type hash) const
285169691Skan#else
286169691Skan      (const_key_reference /*r_key*/, size_type hash) const
287169691Skan#endif
288169691Skan    {
289169691Skan      _GLIBCXX_DEBUG_ASSERT(hash == hash_fn_base::operator()(r_key));
290169691Skan      return hash;
291169691Skan    }
292169691Skan
293169691Skan#undef PB_DS_CLASS_T_DEC
294169691Skan#undef PB_DS_CLASS_C_DEC
295169691Skan
296169691Skan    /**
297169691Skan     * Specialization 3 and 4
298169691Skan     * The client does not supply a hash function or probe function,
299169691Skan     * and requests that hash values not be stored.
300169691Skan     **/
301169691Skan    template<typename Key, typename Allocator, typename Comb_Probe_Fn>
302169691Skan    class ranged_probe_fn<Key, null_hash_fn, Allocator, Comb_Probe_Fn,
303169691Skan			  null_probe_fn, false>
304169691Skan    : public Comb_Probe_Fn, public null_hash_fn, public null_probe_fn
305169691Skan    {
306169691Skan    protected:
307169691Skan      typedef typename Allocator::size_type size_type;
308169691Skan      typedef Comb_Probe_Fn comb_probe_fn_base;
309169691Skan      typedef typename Allocator::template rebind<Key>::other key_allocator;
310169691Skan      typedef typename key_allocator::const_reference const_key_reference;
311169691Skan
312169691Skan      ranged_probe_fn(size_type size)
313169691Skan      { Comb_Probe_Fn::notify_resized(size); }
314169691Skan
315169691Skan      ranged_probe_fn(size_type, const Comb_Probe_Fn& r_comb_probe_fn)
316169691Skan      : Comb_Probe_Fn(r_comb_probe_fn)
317169691Skan      { }
318169691Skan
319169691Skan      ranged_probe_fn(size_type, const null_hash_fn&,
320169691Skan		      const Comb_Probe_Fn& r_comb_probe_fn,
321169691Skan		      const null_probe_fn&)
322169691Skan      : Comb_Probe_Fn(r_comb_probe_fn)
323169691Skan      { }
324169691Skan
325169691Skan      void
326169691Skan      swap(ranged_probe_fn& other)
327169691Skan      { comb_probe_fn_base::swap(other); }
328169691Skan    };
329169691Skan  } // namespace detail
330169691Skan} // namespace pb_ds
331169691Skan
332169691Skan#endif
333169691Skan
334