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 map_debug_base.hpp
44169691Skan * Contains a debug-mode base for all maps.
45169691Skan */
46169691Skan
47169691Skan#ifndef PB_DS_MAP_DEBUG_BASE_HPP
48169691Skan#define PB_DS_MAP_DEBUG_BASE_HPP
49169691Skan
50169691Skan#ifdef _GLIBCXX_DEBUG
51169691Skan
52169691Skan#include <list>
53169691Skan#include <utility>
54169691Skan#include <ext/throw_allocator.h>
55169691Skan#include <debug/debug.h>
56169691Skan
57169691Skannamespace pb_ds
58169691Skan{
59169691Skan  namespace detail
60169691Skan  {
61169691Skan
62169691Skan#define PB_DS_CLASS_T_DEC \
63169691Skan    template<typename Key, class Eq_Fn, typename Const_Key_Reference>
64169691Skan
65169691Skan#define PB_DS_CLASS_C_DEC \
66169691Skan    map_debug_base<Key, Eq_Fn, Const_Key_Reference>
67169691Skan
68169691Skan    template<typename Key, class Eq_Fn, typename Const_Key_Reference>
69169691Skan    class map_debug_base
70169691Skan    {
71169691Skan    private:
72169691Skan      typedef typename std::allocator< Key> key_allocator;
73169691Skan
74169691Skan      typedef typename key_allocator::size_type size_type;
75169691Skan
76169691Skan      typedef Const_Key_Reference const_key_reference;
77169691Skan
78169691Skan    protected:
79169691Skan      map_debug_base();
80169691Skan
81169691Skan      map_debug_base(const PB_DS_CLASS_C_DEC& other);
82169691Skan
83169691Skan      ~map_debug_base();
84169691Skan
85169691Skan      inline void
86169691Skan      insert_new(const_key_reference r_key);
87169691Skan
88169691Skan      inline void
89169691Skan      erase_existing(const_key_reference r_key);
90169691Skan
91169691Skan      void
92169691Skan      clear();
93169691Skan
94169691Skan      inline void
95169691Skan      check_key_exists(const_key_reference r_key) const;
96169691Skan
97169691Skan      inline void
98169691Skan      check_key_does_not_exist(const_key_reference r_key) const;
99169691Skan
100169691Skan      inline void
101169691Skan      check_size(size_type size) const;
102169691Skan
103169691Skan      void
104169691Skan      swap(PB_DS_CLASS_C_DEC& other);
105169691Skan
106169691Skan      template<typename Cmp_Fn>
107169691Skan      void
108169691Skan      split(const_key_reference, Cmp_Fn, PB_DS_CLASS_C_DEC&);
109169691Skan
110169691Skan      void
111169691Skan      join(PB_DS_CLASS_C_DEC& other);
112169691Skan
113169691Skan    private:
114169691Skan      typedef std::list< Key> 			key_set;
115169691Skan      typedef typename key_set::iterator 	key_set_iterator;
116169691Skan      typedef typename key_set::const_iterator 	const_key_set_iterator;
117169691Skan
118169691Skan#ifdef _GLIBCXX_DEBUG
119169691Skan      void
120169691Skan      assert_valid() const;
121169691Skan#endif
122169691Skan
123169691Skan      const_key_set_iterator
124169691Skan      find(const_key_reference r_key) const;
125169691Skan
126169691Skan      key_set_iterator
127169691Skan      find(const_key_reference r_key);
128169691Skan
129169691Skan      key_set 	m_key_set;
130169691Skan      Eq_Fn 	m_eq;
131169691Skan    };
132169691Skan
133169691Skan    PB_DS_CLASS_T_DEC
134169691Skan    PB_DS_CLASS_C_DEC::
135169691Skan    map_debug_base()
136169691Skan    { _GLIBCXX_DEBUG_ONLY(assert_valid();) }
137169691Skan
138169691Skan    PB_DS_CLASS_T_DEC
139169691Skan    PB_DS_CLASS_C_DEC::
140169691Skan    map_debug_base(const PB_DS_CLASS_C_DEC& other) : m_key_set(other.m_key_set)
141169691Skan    { _GLIBCXX_DEBUG_ONLY(assert_valid();) }
142169691Skan
143169691Skan    PB_DS_CLASS_T_DEC
144169691Skan    PB_DS_CLASS_C_DEC::
145169691Skan    ~map_debug_base()
146169691Skan    { _GLIBCXX_DEBUG_ONLY(assert_valid();) }
147169691Skan
148169691Skan    PB_DS_CLASS_T_DEC
149169691Skan    inline void
150169691Skan    PB_DS_CLASS_C_DEC::
151169691Skan    insert_new(const_key_reference r_key)
152169691Skan    {
153169691Skan      _GLIBCXX_DEBUG_ONLY(assert_valid();)
154169691Skan      __gnu_cxx::throw_allocator<char> alloc;
155169691Skan      const double orig_throw_prob = alloc.get_throw_prob();
156169691Skan      alloc.set_throw_prob(0);
157169691Skan      if (find(r_key) != m_key_set.end())
158169691Skan	{
159169691Skan	  std::cerr << "insert_new " << r_key << std::endl;
160169691Skan	  abort();
161169691Skan	}
162169691Skan
163169691Skan      try
164169691Skan	{
165169691Skan	  m_key_set.push_back(r_key);
166169691Skan	}
167169691Skan      catch(...)
168169691Skan	{
169169691Skan	  std::cerr << "insert_new 1" << r_key << std::endl;
170169691Skan	  abort();
171169691Skan	}
172169691Skan      alloc.set_throw_prob(orig_throw_prob);
173169691Skan      _GLIBCXX_DEBUG_ONLY(assert_valid();)
174169691Skan    }
175169691Skan
176169691Skan    PB_DS_CLASS_T_DEC
177169691Skan    inline void
178169691Skan    PB_DS_CLASS_C_DEC::
179169691Skan    erase_existing(const_key_reference r_key)
180169691Skan    {
181169691Skan      _GLIBCXX_DEBUG_ONLY(assert_valid();)
182169691Skan      key_set_iterator it = find(r_key);
183169691Skan      if (it == m_key_set.end())
184169691Skan	{
185169691Skan	  std::cerr << "erase_existing " << r_key << std::endl;
186169691Skan	  abort();
187169691Skan	}
188169691Skan      m_key_set.erase(it);
189169691Skan      _GLIBCXX_DEBUG_ONLY(assert_valid();)
190169691Skan    }
191169691Skan
192169691Skan    PB_DS_CLASS_T_DEC
193169691Skan    void
194169691Skan    PB_DS_CLASS_C_DEC::
195169691Skan    clear()
196169691Skan    {
197169691Skan      _GLIBCXX_DEBUG_ONLY(assert_valid();)
198169691Skan      m_key_set.clear();
199169691Skan      _GLIBCXX_DEBUG_ONLY(assert_valid();)
200169691Skan    }
201169691Skan
202169691Skan    PB_DS_CLASS_T_DEC
203169691Skan    inline void
204169691Skan    PB_DS_CLASS_C_DEC::
205169691Skan    check_key_exists(const_key_reference r_key) const
206169691Skan    {
207169691Skan      _GLIBCXX_DEBUG_ONLY(assert_valid();)
208169691Skan      if (find(r_key) == m_key_set.end())
209169691Skan        {
210169691Skan          std::cerr << "check_key_exists " << r_key << std::endl;
211169691Skan          abort();
212169691Skan        }
213169691Skan      _GLIBCXX_DEBUG_ONLY(assert_valid();)
214169691Skan    }
215169691Skan
216169691Skan    PB_DS_CLASS_T_DEC
217169691Skan    inline void
218169691Skan    PB_DS_CLASS_C_DEC::
219169691Skan    check_key_does_not_exist(const_key_reference r_key) const
220169691Skan    {
221169691Skan      _GLIBCXX_DEBUG_ONLY(assert_valid();)
222169691Skan      if (find(r_key) != m_key_set.end())
223169691Skan        {
224169691Skan	  std::cerr << "check_key_does_not_exist " << r_key << std::endl;
225169691Skan          abort();
226169691Skan        }
227169691Skan    }
228169691Skan
229169691Skan    PB_DS_CLASS_T_DEC
230169691Skan    inline void
231169691Skan    PB_DS_CLASS_C_DEC::
232169691Skan    check_size(size_type size) const
233169691Skan    {
234169691Skan      _GLIBCXX_DEBUG_ONLY(assert_valid();)
235169691Skan      const size_type key_set_size = m_key_set.size();
236169691Skan      if (size != key_set_size)
237169691Skan	{
238169691Skan	  std::cerr << "check_size " << size
239169691Skan		    << " " << key_set_size << std::endl;
240169691Skan	  abort();
241169691Skan	}
242169691Skan      _GLIBCXX_DEBUG_ONLY(assert_valid();)
243169691Skan     }
244169691Skan
245169691Skan    PB_DS_CLASS_T_DEC
246169691Skan    void
247169691Skan    PB_DS_CLASS_C_DEC::
248169691Skan    swap(PB_DS_CLASS_C_DEC& other)
249169691Skan    {
250169691Skan      _GLIBCXX_DEBUG_ONLY(assert_valid();)
251169691Skan      m_key_set.swap(other.m_key_set);
252169691Skan      _GLIBCXX_DEBUG_ONLY(assert_valid();)
253169691Skan    }
254169691Skan
255169691Skan    PB_DS_CLASS_T_DEC
256169691Skan    typename PB_DS_CLASS_C_DEC::const_key_set_iterator
257169691Skan    PB_DS_CLASS_C_DEC::
258169691Skan    find(const_key_reference r_key) const
259169691Skan    {
260169691Skan      _GLIBCXX_DEBUG_ONLY(assert_valid();)
261169691Skan      typedef const_key_set_iterator iterator_type;
262169691Skan      for (iterator_type it = m_key_set.begin(); it != m_key_set.end(); ++it)
263169691Skan	if (m_eq(*it, r_key))
264169691Skan          return it;
265169691Skan      return m_key_set.end();
266169691Skan    }
267169691Skan
268169691Skan    PB_DS_CLASS_T_DEC
269169691Skan    typename PB_DS_CLASS_C_DEC::key_set_iterator
270169691Skan    PB_DS_CLASS_C_DEC::
271169691Skan    find(const_key_reference r_key)
272169691Skan    {
273169691Skan      _GLIBCXX_DEBUG_ONLY(assert_valid();)
274169691Skan      key_set_iterator it = m_key_set.begin();
275169691Skan      while (it != m_key_set.end())
276169691Skan	{
277169691Skan	  if (m_eq(*it, r_key))
278169691Skan            return it;
279169691Skan	  ++it;
280169691Skan	}
281169691Skan      return it;
282169691Skan      _GLIBCXX_DEBUG_ONLY(assert_valid();)
283169691Skan     }
284169691Skan
285169691Skan#ifdef _GLIBCXX_DEBUG
286169691Skan    PB_DS_CLASS_T_DEC
287169691Skan    void
288169691Skan    PB_DS_CLASS_C_DEC::
289169691Skan    assert_valid() const
290169691Skan    {
291169691Skan      const_key_set_iterator prime_it = m_key_set.begin();
292169691Skan      while (prime_it != m_key_set.end())
293169691Skan	{
294169691Skan	  const_key_set_iterator sec_it = prime_it;
295169691Skan	  ++sec_it;
296169691Skan	  while (sec_it != m_key_set.end())
297169691Skan	    {
298169691Skan	      _GLIBCXX_DEBUG_ASSERT(!m_eq(*sec_it, *prime_it));
299169691Skan	      _GLIBCXX_DEBUG_ASSERT(!m_eq(*prime_it, *sec_it));
300169691Skan	      ++sec_it;
301169691Skan	    }
302169691Skan	  ++prime_it;
303169691Skan	}
304169691Skan    }
305169691Skan#endif
306169691Skan
307169691Skan    PB_DS_CLASS_T_DEC
308169691Skan    template<typename Cmp_Fn>
309169691Skan    void
310169691Skan    PB_DS_CLASS_C_DEC::
311169691Skan    split(const_key_reference r_key, Cmp_Fn cmp_fn, PB_DS_CLASS_C_DEC& other)
312169691Skan    {
313169691Skan      __gnu_cxx::throw_allocator<char> alloc;
314169691Skan      const double orig_throw_prob = alloc.get_throw_prob();
315169691Skan      alloc.set_throw_prob(0);
316169691Skan      other.clear();
317169691Skan      key_set_iterator it = m_key_set.begin();
318169691Skan      while (it != m_key_set.end())
319169691Skan        if (cmp_fn(r_key, * it))
320169691Skan	  {
321169691Skan            other.insert_new(*it);
322169691Skan            it = m_key_set.erase(it);
323169691Skan	  }
324169691Skan        else
325169691Skan	  ++it;
326169691Skan      alloc.set_throw_prob(orig_throw_prob);
327169691Skan    }
328169691Skan
329169691Skan    PB_DS_CLASS_T_DEC
330169691Skan    void
331169691Skan    PB_DS_CLASS_C_DEC::
332169691Skan    join(PB_DS_CLASS_C_DEC& other)
333169691Skan    {
334169691Skan      __gnu_cxx::throw_allocator<char> alloc;
335169691Skan      const double orig_throw_prob = alloc.get_throw_prob();
336169691Skan      alloc.set_throw_prob(0);
337169691Skan      key_set_iterator it = other.m_key_set.begin();
338169691Skan      while (it != other.m_key_set.end())
339169691Skan	{
340169691Skan	  insert_new(*it);
341169691Skan	  it = other.m_key_set.erase(it);
342169691Skan	}
343169691Skan      _GLIBCXX_DEBUG_ASSERT(other.m_key_set.empty());
344169691Skan      alloc.set_throw_prob(orig_throw_prob);
345169691Skan    }
346169691Skan
347169691Skan#undef PB_DS_CLASS_T_DEC
348169691Skan#undef PB_DS_CLASS_C_DEC
349169691Skan
350169691Skan} // namespace detail
351169691Skan} // namespace pb_ds
352169691Skan
353169691Skan#endif
354169691Skan
355169691Skan#endif
356169691Skan
357