1 // -*- C++ -*- 2 3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 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 detail/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> 60 inline std::basic_ostream<_CharT, _Traits>& 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, typename 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 /// Debug base class. 72 template<typename Key, typename Eq_Fn, typename Const_Key_Reference> 73 class debug_map_base 74 { 75 private: 76 typedef Const_Key_Reference key_const_reference; 77 typedef std::_GLIBCXX_STD_C::list<Key> key_repository; 78 typedef typename key_repository::size_type size_type; 79 typedef typename key_repository::iterator iterator; 80 typedef typename key_repository::const_iterator const_iterator; 81 82 protected: 83 debug_map_base(); 84 85 debug_map_base(const PB_DS_CLASS_C_DEC&); 86 87 ~debug_map_base(); 88 89 inline void 90 insert_new(key_const_reference); 91 92 inline void 93 erase_existing(key_const_reference); 94 95 void 96 clear(); 97 98 inline void 99 check_key_exists(key_const_reference, const char*, int) const; 100 101 inline void 102 check_key_does_not_exist(key_const_reference, const char*, int) const; 103 104 inline void 105 check_size(size_type, const char*, int) const; 106 107 void 108 swap(PB_DS_CLASS_C_DEC&); 109 110 template<typename Cmp_Fn> 111 void 112 split(key_const_reference, Cmp_Fn, PB_DS_CLASS_C_DEC&); 113 114 void 115 join(PB_DS_CLASS_C_DEC&, bool with_cleanup = true); 116 117 private: 118 void 119 assert_valid(const char*, int) const; 120 121 const_iterator 122 find(key_const_reference) const; 123 124 iterator 125 find(key_const_reference); 126 127 key_repository m_keys; 128 Eq_Fn m_eq; 129 }; 130 131 PB_DS_CLASS_T_DEC 132 PB_DS_CLASS_C_DEC:: 133 debug_map_base() 134 { PB_DS_ASSERT_VALID((*this)) } 135 136 PB_DS_CLASS_T_DEC 137 PB_DS_CLASS_C_DEC:: 138 debug_map_base(const PB_DS_CLASS_C_DEC& other) 139 : m_keys(other.m_keys), m_eq(other.m_eq) 140 { PB_DS_ASSERT_VALID((*this)) } 141 142 PB_DS_CLASS_T_DEC 143 PB_DS_CLASS_C_DEC:: 144 ~debug_map_base() 145 { PB_DS_ASSERT_VALID((*this)) } 146 147 PB_DS_CLASS_T_DEC 148 inline void 149 PB_DS_CLASS_C_DEC:: 150 insert_new(key_const_reference r_key) 151 { 152 PB_DS_ASSERT_VALID((*this)) 153 154 if (find(r_key) != m_keys.end()) 155 { 156 std::cerr << "insert_new key already present " << r_key << std::endl; 157 std::abort(); 158 } 159 160 __try 161 { 162 m_keys.push_back(r_key); 163 } 164 __catch(...) 165 { 166 std::cerr << "insert_new " << r_key << std::endl; 167 std::abort(); 168 } 169 170 PB_DS_ASSERT_VALID((*this)) 171 } 172 173 PB_DS_CLASS_T_DEC 174 inline void 175 PB_DS_CLASS_C_DEC:: 176 erase_existing(key_const_reference r_key) 177 { 178 PB_DS_ASSERT_VALID((*this)) 179 iterator it = find(r_key); 180 if (it == m_keys.end()) 181 { 182 std::cerr << "erase_existing" << r_key << std::endl; 183 std::abort(); 184 } 185 m_keys.erase(it); 186 PB_DS_ASSERT_VALID((*this)) 187 } 188 189 PB_DS_CLASS_T_DEC 190 void 191 PB_DS_CLASS_C_DEC:: 192 clear() 193 { 194 PB_DS_ASSERT_VALID((*this)) 195 m_keys.clear(); 196 PB_DS_ASSERT_VALID((*this)) 197 } 198 199 PB_DS_CLASS_T_DEC 200 inline void 201 PB_DS_CLASS_C_DEC:: 202 check_key_exists(key_const_reference r_key, 203 const char* __file, int __line) const 204 { 205 assert_valid(__file, __line); 206 if (find(r_key) == m_keys.end()) 207 { 208 std::cerr << __file << ':' << __line << ": check_key_exists " 209 << r_key << std::endl; 210 std::abort(); 211 } 212 } 213 214 PB_DS_CLASS_T_DEC 215 inline void 216 PB_DS_CLASS_C_DEC:: 217 check_key_does_not_exist(key_const_reference r_key, 218 const char* __file, int __line) const 219 { 220 assert_valid(__file, __line); 221 if (find(r_key) != m_keys.end()) 222 { 223 using std::cerr; 224 using std::endl; 225 cerr << __file << ':' << __line << ": check_key_does_not_exist " 226 << r_key << endl; 227 std::abort(); 228 } 229 } 230 231 PB_DS_CLASS_T_DEC 232 inline void 233 PB_DS_CLASS_C_DEC:: 234 check_size(size_type size, const char* __file, int __line) const 235 { 236 assert_valid(__file, __line); 237 const size_type keys_size = m_keys.size(); 238 if (size != keys_size) 239 { 240 std::cerr << __file << ':' << __line << ": check_size " 241 << size << " != " << keys_size << std::endl; 242 std::abort(); 243 } 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 PB_DS_ASSERT_VALID((*this)) 252 m_keys.swap(other.m_keys); 253 std::swap(m_eq, other.m_eq); 254 PB_DS_ASSERT_VALID((*this)) 255 } 256 257 PB_DS_CLASS_T_DEC 258 typename PB_DS_CLASS_C_DEC::const_iterator 259 PB_DS_CLASS_C_DEC:: 260 find(key_const_reference r_key) const 261 { 262 PB_DS_ASSERT_VALID((*this)) 263 typedef const_iterator iterator_type; 264 for (iterator_type it = m_keys.begin(); it != m_keys.end(); ++it) 265 if (m_eq(*it, r_key)) 266 return it; 267 return m_keys.end(); 268 } 269 270 PB_DS_CLASS_T_DEC 271 typename PB_DS_CLASS_C_DEC::iterator 272 PB_DS_CLASS_C_DEC:: 273 find(key_const_reference r_key) 274 { 275 PB_DS_ASSERT_VALID((*this)) 276 iterator it = m_keys.begin(); 277 while (it != m_keys.end()) 278 { 279 if (m_eq(*it, r_key)) 280 return it; 281 ++it; 282 } 283 return it; 284 } 285 286 PB_DS_CLASS_T_DEC 287 void 288 PB_DS_CLASS_C_DEC:: 289 assert_valid(const char* __file, int __line) const 290 { 291 const_iterator prime_it = m_keys.begin(); 292 while (prime_it != m_keys.end()) 293 { 294 const_iterator sec_it = prime_it; 295 ++sec_it; 296 while (sec_it != m_keys.end()) 297 { 298 PB_DS_DEBUG_VERIFY(!m_eq(*sec_it, *prime_it)); 299 PB_DS_DEBUG_VERIFY(!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(key_const_reference r_key, Cmp_Fn cmp_fn, PB_DS_CLASS_C_DEC& other) 311 { 312 other.clear(); 313 iterator it = m_keys.begin(); 314 while (it != m_keys.end()) 315 if (cmp_fn(r_key, *it)) 316 { 317 other.insert_new(*it); 318 it = m_keys.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, bool with_cleanup) 328 { 329 iterator it = other.m_keys.begin(); 330 while (it != other.m_keys.end()) 331 { 332 insert_new(*it); 333 if (with_cleanup) 334 it = other.m_keys.erase(it); 335 else 336 ++it; 337 } 338 _GLIBCXX_DEBUG_ASSERT(!with_cleanup || other.m_keys.empty()); 339 } 340 341 #undef PB_DS_CLASS_T_DEC 342 #undef PB_DS_CLASS_C_DEC 343 344 } // namespace detail 345 } // namespace __gnu_pbds 346 347 348 #endif 349 350 #endif 351