libstdc++
debug_map_base.hpp
Go to the documentation of this file.
1 // -*- C++ -*-
2 
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the terms
8 // of the GNU General Public License as published by the Free Software
9 // Foundation; either version 3, or (at your option) any later
10 // version.
11 
12 // This library is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
16 
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
20 
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 // <http://www.gnu.org/licenses/>.
25 
26 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
27 
28 // Permission to use, copy, modify, sell, and distribute this software
29 // is hereby granted without fee, provided that the above copyright
30 // notice appears in all copies, and that both that copyright notice
31 // and this permission notice appear in supporting documentation. None
32 // of the above authors, nor IBM Haifa Research Laboratories, make any
33 // representation about the suitability of this software for any
34 // purpose. It is provided "as is" without express or implied
35 // warranty.
36 
37 /**
38  * @file debug_map_base.hpp
39  * Contains a debug-mode base for all maps.
40  */
41 
42 #ifndef PB_DS_DEBUG_MAP_BASE_HPP
43 #define PB_DS_DEBUG_MAP_BASE_HPP
44 
45 #ifdef _GLIBCXX_DEBUG
46 
47 #include <list>
48 #include <utility>
49 #include <cstdlib>
50 #include <iostream>
51 #include <ext/throw_allocator.h>
52 #include <debug/debug.h>
53 
54 namespace __gnu_pbds
55 {
56  namespace detail
57  {
58  // Need std::pair ostream extractor.
59  template<typename _CharT, typename _Traits, typename _Tp1, typename _Tp2>
61  operator<<(std::basic_ostream<_CharT, _Traits>& __out,
62  const std::pair<_Tp1, _Tp2>& p)
63  { return (__out << '(' << p.first << ',' << p.second << ')'); }
64 
65 #define PB_DS_CLASS_T_DEC \
66  template<typename Key, class Eq_Fn, typename Const_Key_Reference>
67 
68 #define PB_DS_CLASS_C_DEC \
69  debug_map_base<Key, Eq_Fn, Const_Key_Reference>
70 
71  template<typename Key, class Eq_Fn, typename Const_Key_Reference>
72  class debug_map_base
73  {
74  private:
75  typedef typename std::allocator<Key> key_allocator;
76  typedef typename key_allocator::size_type size_type;
77  typedef Const_Key_Reference const_key_reference;
78  typedef std::_GLIBCXX_STD_C::list<Key> key_set;
79  typedef typename key_set::iterator key_set_iterator;
80  typedef typename key_set::const_iterator const_key_set_iterator;
81  typedef __gnu_cxx::throw_allocator_random<Key> key_db_allocator;
82  typedef typename key_db_allocator::never_adjustor never_adjustor;
83 
84  protected:
85  debug_map_base();
86 
87  debug_map_base(const PB_DS_CLASS_C_DEC& other);
88 
89  ~debug_map_base();
90 
91  inline void
92  insert_new(const_key_reference r_key);
93 
94  inline void
95  erase_existing(const_key_reference r_key);
96 
97  void
98  clear();
99 
100  inline void
101  check_key_exists(const_key_reference r_key) const;
102 
103  inline void
104  check_key_does_not_exist(const_key_reference r_key) const;
105 
106  inline void
107  check_size(size_type size) const;
108 
109  void
110  swap(PB_DS_CLASS_C_DEC& other);
111 
112  template<typename Cmp_Fn>
113  void
114  split(const_key_reference, Cmp_Fn, PB_DS_CLASS_C_DEC&);
115 
116  void
117  join(PB_DS_CLASS_C_DEC& other);
118 
119  private:
120  void
121  assert_valid() const;
122 
123  const_key_set_iterator
124  find(const_key_reference r_key) const;
125 
126  key_set_iterator
127  find(const_key_reference r_key);
128 
129  key_set m_key_set;
130  Eq_Fn m_eq;
131  };
132 
133  PB_DS_CLASS_T_DEC
134  PB_DS_CLASS_C_DEC::
135  debug_map_base()
136  { _GLIBCXX_DEBUG_ONLY(assert_valid();) }
137 
138  PB_DS_CLASS_T_DEC
139  PB_DS_CLASS_C_DEC::
140  debug_map_base(const PB_DS_CLASS_C_DEC& other) : m_key_set(other.m_key_set)
141  { _GLIBCXX_DEBUG_ONLY(assert_valid();) }
142 
143  PB_DS_CLASS_T_DEC
144  PB_DS_CLASS_C_DEC::
145  ~debug_map_base()
146  { _GLIBCXX_DEBUG_ONLY(assert_valid();) }
147 
148  PB_DS_CLASS_T_DEC
149  inline void
150  PB_DS_CLASS_C_DEC::
151  insert_new(const_key_reference r_key)
152  {
153  _GLIBCXX_DEBUG_ONLY(assert_valid();)
154 
155  if (find(r_key) != m_key_set.end())
156  {
157  std::cerr << "insert_new key already present " << r_key << std::endl;
158  std::abort;
159  }
160 
161  never_adjustor never;
162  __try
163  {
164  m_key_set.push_back(r_key);
165  }
166  __catch(...)
167  {
168  std::cerr << "insert_new " << r_key << std::endl;
169  std::abort();
170  }
171 
172  _GLIBCXX_DEBUG_ONLY(assert_valid();)
173  }
174 
175  PB_DS_CLASS_T_DEC
176  inline void
177  PB_DS_CLASS_C_DEC::
178  erase_existing(const_key_reference r_key)
179  {
180  _GLIBCXX_DEBUG_ONLY(assert_valid();)
181  key_set_iterator it = find(r_key);
182  if (it == m_key_set.end())
183  {
184  std::cerr << "erase_existing" << r_key << std::endl;
185  std::abort();
186  }
187  m_key_set.erase(it);
188  _GLIBCXX_DEBUG_ONLY(assert_valid();)
189  }
190 
191  PB_DS_CLASS_T_DEC
192  void
193  PB_DS_CLASS_C_DEC::
194  clear()
195  {
196  _GLIBCXX_DEBUG_ONLY(assert_valid();)
197  m_key_set.clear();
198  _GLIBCXX_DEBUG_ONLY(assert_valid();)
199  }
200 
201  PB_DS_CLASS_T_DEC
202  inline void
203  PB_DS_CLASS_C_DEC::
204  check_key_exists(const_key_reference r_key) const
205  {
206  _GLIBCXX_DEBUG_ONLY(assert_valid();)
207  if (find(r_key) == m_key_set.end())
208  {
209  std::cerr << "check_key_exists " << r_key << std::endl;
210  std::abort();
211  }
212  _GLIBCXX_DEBUG_ONLY(assert_valid();)
213  }
214 
215  PB_DS_CLASS_T_DEC
216  inline void
217  PB_DS_CLASS_C_DEC::
218  check_key_does_not_exist(const_key_reference r_key) const
219  {
220  _GLIBCXX_DEBUG_ONLY(assert_valid();)
221  if (find(r_key) != m_key_set.end())
222  {
223  using std::cerr;
224  using std::endl;
225  cerr << "check_key_does_not_exist " << r_key << endl;
226  std::abort();
227  }
228  }
229 
230  PB_DS_CLASS_T_DEC
231  inline void
232  PB_DS_CLASS_C_DEC::
233  check_size(size_type size) const
234  {
235  _GLIBCXX_DEBUG_ONLY(assert_valid();)
236  const size_type key_set_size = m_key_set.size();
237  if (size != key_set_size)
238  {
239  std::cerr << "check_size " << size
240  << " " << key_set_size << std::endl;
241  std::abort();
242  }
243  _GLIBCXX_DEBUG_ONLY(assert_valid();)
244  }
245 
246  PB_DS_CLASS_T_DEC
247  void
248  PB_DS_CLASS_C_DEC::
249  swap(PB_DS_CLASS_C_DEC& other)
250  {
251  _GLIBCXX_DEBUG_ONLY(assert_valid();)
252  m_key_set.swap(other.m_key_set);
253  _GLIBCXX_DEBUG_ONLY(assert_valid();)
254  }
255 
256  PB_DS_CLASS_T_DEC
257  typename PB_DS_CLASS_C_DEC::const_key_set_iterator
258  PB_DS_CLASS_C_DEC::
259  find(const_key_reference r_key) const
260  {
261  _GLIBCXX_DEBUG_ONLY(assert_valid();)
262  typedef const_key_set_iterator iterator_type;
263  for (iterator_type it = m_key_set.begin(); it != m_key_set.end(); ++it)
264  if (m_eq(*it, r_key))
265  return it;
266  return m_key_set.end();
267  }
268 
269  PB_DS_CLASS_T_DEC
270  typename PB_DS_CLASS_C_DEC::key_set_iterator
271  PB_DS_CLASS_C_DEC::
272  find(const_key_reference r_key)
273  {
274  _GLIBCXX_DEBUG_ONLY(assert_valid();)
275  key_set_iterator it = m_key_set.begin();
276  while (it != m_key_set.end())
277  {
278  if (m_eq(*it, r_key))
279  return it;
280  ++it;
281  }
282  return it;
283  _GLIBCXX_DEBUG_ONLY(assert_valid();)
284  }
285 
286  PB_DS_CLASS_T_DEC
287  void
288  PB_DS_CLASS_C_DEC::
289  assert_valid() const
290  {
291  const_key_set_iterator prime_it = m_key_set.begin();
292  while (prime_it != m_key_set.end())
293  {
294  const_key_set_iterator sec_it = prime_it;
295  ++sec_it;
296  while (sec_it != m_key_set.end())
297  {
298  _GLIBCXX_DEBUG_ASSERT(!m_eq(*sec_it, *prime_it));
299  _GLIBCXX_DEBUG_ASSERT(!m_eq(*prime_it, *sec_it));
300  ++sec_it;
301  }
302  ++prime_it;
303  }
304  }
305 
306  PB_DS_CLASS_T_DEC
307  template<typename Cmp_Fn>
308  void
309  PB_DS_CLASS_C_DEC::
310  split(const_key_reference r_key, Cmp_Fn cmp_fn, PB_DS_CLASS_C_DEC& other)
311  {
312  other.clear();
313  key_set_iterator it = m_key_set.begin();
314  while (it != m_key_set.end())
315  if (cmp_fn(r_key, * it))
316  {
317  other.insert_new(*it);
318  it = m_key_set.erase(it);
319  }
320  else
321  ++it;
322  }
323 
324  PB_DS_CLASS_T_DEC
325  void
326  PB_DS_CLASS_C_DEC::
327  join(PB_DS_CLASS_C_DEC& other)
328  {
329  key_set_iterator it = other.m_key_set.begin();
330  while (it != other.m_key_set.end())
331  {
332  insert_new(*it);
333  it = other.m_key_set.erase(it);
334  }
335  _GLIBCXX_DEBUG_ASSERT(other.m_key_set.empty());
336  }
337 
338 #undef PB_DS_CLASS_T_DEC
339 #undef PB_DS_CLASS_C_DEC
340 
341 } // namespace detail
342 } // namespace __gnu_pbds
343 
344 #endif
345 
346 #endif