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> 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, 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 347