1 #ifndef LINKEDSET__HPP 2 #define LINKEDSET__HPP 3 4 /* $Id: linkedset.hpp 354590 2012-02-28 16:30:13Z ucko $ 5 * =========================================================================== 6 * 7 * PUBLIC DOMAIN NOTICE 8 * National Center for Biotechnology Information 9 * 10 * This software/database is a "United States Government Work" under the 11 * terms of the United States Copyright Act. It was written as part of 12 * the author's official duties as a United States Government employee and 13 * thus cannot be copyrighted. This software/database is freely available 14 * to the public for use. The National Library of Medicine and the U.S. 15 * Government have not placed any restriction on its use or reproduction. 16 * 17 * Although all reasonable efforts have been taken to ensure the accuracy 18 * and reliability of the software and data, the NLM and the U.S. 19 * Government do not and cannot warrant the performance or results that 20 * may be obtained by using this software or data. The NLM and the U.S. 21 * Government disclaim all warranties, express or implied, including 22 * warranties of performance, merchantability or fitness for any particular 23 * purpose. 24 * 25 * Please cite the author in any work or product based on this material. 26 * 27 * =========================================================================== 28 * 29 * Author: Eugene Vasilchenko 30 * 31 * File Description: 32 * !!! PUT YOUR DESCRIPTION HERE !!! 33 */ 34 35 #include <corelib/ncbistd.hpp> 36 #include <set> 37 38 39 /** @addtogroup LinkedSet 40 * 41 * @{ 42 */ 43 44 45 BEGIN_NCBI_SCOPE 46 47 template<typename Key> struct SLinkedSetValue; 48 template<typename Key> class CLinkedMultisetBase; 49 50 template<typename Key> 51 struct SLinkedSetValue 52 { 53 typedef Key key_type; 54 typedef SLinkedSetValue<Key> value_type; 55 SLinkedSetValueSLinkedSetValue56 SLinkedSetValue(const key_type& key, value_type* next = 0) 57 : m_Key(key), m_Next(next) 58 { 59 } 60 GetKeySLinkedSetValue61 const key_type& GetKey(void) const 62 { 63 return m_Key; 64 } GetNextSLinkedSetValue65 value_type* GetNext(void) 66 { 67 return m_Next; 68 } GetNextSLinkedSetValue69 const value_type* GetNext(void) const 70 { 71 return m_Next; 72 } 73 operator <SLinkedSetValue74 bool operator<(const value_type& value) const 75 { 76 return GetKey() < value.GetKey(); 77 } 78 private: 79 friend class CLinkedMultisetBase<key_type>; 80 81 const key_type m_Key; 82 value_type* m_Next; 83 }; 84 85 #if 0 86 template<typename Value, typename Compare> 87 class CLinkedSetBase 88 { 89 public: 90 struct SValue 91 { 92 typedef Value value_type; 93 94 Value value; 95 96 SValue* Next(void) const 97 { 98 return m_Next; 99 } 100 private: 101 friend class CLinkedSetBase<Value, Compare>; 102 103 SValue* m_Next; 104 }; 105 typedef set<Value, Compare> TSet; 106 107 typedef typename TSet::iterator iterator; 108 typedef typename TSet::const_iterator const_iterator; 109 typedef SValue* TForwardIterator; 110 111 CLinkedSetBase(void) 112 : m_Start(0) 113 { 114 } 115 CLinkedSetBase(Compare comp) 116 : m_Set(comp), m_Start(0) 117 { 118 } 119 120 bool empty(void) const 121 { 122 return m_Start == 0; 123 } 124 125 TForwardIterator ForwardBegin(void) const 126 { 127 return m_Start; 128 } 129 TForwardIterator ForwardEnd(void) const 130 { 131 return 0; 132 } 133 134 iterator begin(void) 135 { 136 return m_Set.begin(); 137 } 138 iterator end(void) 139 { 140 return m_Set.end(); 141 } 142 iterator find(const Value& value) 143 { 144 return m_Set.find(value); 145 } 146 iterator lower_bound(const Value& value) 147 { 148 return m_Set.lower_bound(value); 149 } 150 151 const_iterator begin(void) const 152 { 153 return m_Set.begin(); 154 } 155 const_iterator end(void) const 156 { 157 return m_Set.end(); 158 } 159 const_iterator find(const Value& value) const 160 { 161 return m_Set.find(value); 162 } 163 const_iterator lower_bound(const Value& value) const 164 { 165 return m_Set.lower_bound(value); 166 } 167 168 protected: 169 void clear(void) 170 { 171 m_Start = 0; 172 } 173 174 void insertAfter(const SValue& prevValue, const SValue& newValue) 175 { 176 _ASSERT(!newValue.m_Next); 177 newValue.m_Next = prevValue.m_Next; 178 prevValue.m_Next = &newValue; 179 } 180 void insertToStart(const SValue& newValue) 181 { 182 _ASSERT(!newValue.m_Next); 183 newValue.m_Next = m_Start; 184 m_Start = &newValue; 185 } 186 187 void removeAfter(const SValue& prevValue, const SValue& value) 188 { 189 prevValue.m_Next = value.m_Next; 190 191 } 192 void removeFromStart(const SValue& value) 193 { 194 m_Start = value.m_Next; 195 } 196 197 private: 198 TSet m_Set; 199 SValue* m_Start; 200 }; 201 202 template<typename Mapped> 203 class CLinkedSet : public CLinkedSetBase<typename Mapped::key_type> 204 { 205 typedef CLinkedSetBase<typename Mapped::key_type> TParent; 206 public: 207 typedef set<Mapped> TContainer; 208 typedef typename TContainer::size_type size_type; 209 typedef typename TContainer::value_type value_type; 210 typedef typename TContainer::iterator iterator; 211 typedef typename TContainer::const_iterator const_iterator; 212 213 size_type size(void) const 214 { 215 return m_Container.size(); 216 } 217 218 void clear(void) 219 { 220 m_Container.clear(); 221 TParent::clear(); 222 } 223 224 const_iterator begin(void) const 225 { 226 return m_Container.begin(); 227 } 228 const_iterator end(void) const 229 { 230 return m_Container.end(); 231 } 232 const_iterator find(const value_type& value) const 233 { 234 return m_Container.find(value); 235 } 236 const_iterator lower_bound(const value_type& value) const 237 { 238 return m_Container.lower_bound(value); 239 } 240 const_iterator upper_bound(const value_type& value) const 241 { 242 return m_Container.upper_bound(value); 243 } 244 245 iterator begin(void) 246 { 247 return m_Container.begin(); 248 } 249 iterator end(void) 250 { 251 return m_Container.end(); 252 } 253 iterator find(const value_type& value) 254 { 255 return m_Container.find(value); 256 } 257 iterator lower_bound(const value_type& value) 258 { 259 return m_Container.lower_bound(value); 260 } 261 iterator upper_bound(const value_type& value) 262 { 263 return m_Container.upper_bound(value); 264 } 265 266 pair<iterator, bool> insert(const value_type& value) 267 { 268 pair<iterator, bool> ins = m_Container.insert(value); 269 if ( ins.second ) { 270 if ( ins.first == begin() ) 271 this->insertToStart(*ins.first); 272 else { 273 iterator prev = ins.first; 274 this->insertAfter(*--prev, *ins.first); 275 } 276 } 277 return ins; 278 } 279 280 void erase(iterator iter) 281 { 282 if ( iter == begin() ) 283 this->removeFromStart(*iter); 284 else { 285 iterator prev = iter; 286 this->removeAfter(*--prev, *iter); 287 } 288 m_Container.erase(iter); 289 } 290 291 private: 292 TContainer m_Container; 293 }; 294 #endif 295 296 template<typename Key> 297 class CLinkedMultisetBase 298 { 299 public: 300 typedef Key key_type; 301 typedef SLinkedSetValue<key_type> value_type; 302 CLinkedMultisetBase(void)303 CLinkedMultisetBase(void) 304 : m_Start(0) 305 { 306 } 307 empty(void) const308 bool empty(void) const 309 { 310 return m_Start == 0; 311 } GetStart(void)312 value_type* GetStart(void) 313 { 314 return m_Start; 315 } GetStart(void) const316 const value_type* GetStart(void) const 317 { 318 return m_Start; 319 } 320 321 protected: clear(void)322 void clear(void) 323 { 324 m_Start = 0; 325 } 326 insertAfter(value_type & prevValue,value_type & newValue)327 void insertAfter(value_type& prevValue, value_type& newValue) 328 { 329 _ASSERT(!newValue.m_Next); 330 newValue.m_Next = prevValue.m_Next; 331 prevValue.m_Next = &newValue; 332 } insertToStart(value_type & newValue)333 void insertToStart(value_type& newValue) 334 { 335 _ASSERT(!newValue.m_Next); 336 newValue.m_Next = m_Start; 337 m_Start = &newValue; 338 } 339 removeAfter(value_type & prevValue,value_type & value)340 void removeAfter(value_type& prevValue, value_type& value) 341 { 342 _ASSERT(prevValue.m_Next == &value); 343 prevValue.m_Next = value.m_Next; 344 value.m_Next = 0; 345 } removeFromStart(value_type & value)346 void removeFromStart(value_type& value) 347 { 348 _ASSERT(m_Start == &value); 349 m_Start = value.m_Next; 350 value.m_Next = 0; 351 } 352 353 private: 354 value_type* m_Start; 355 }; 356 357 template<typename Mapped> 358 class CLinkedMultiset : public CLinkedMultisetBase<typename Mapped::key_type> 359 { 360 typedef CLinkedMultisetBase<typename Mapped::key_type> TParent; 361 public: 362 typedef multiset<Mapped> TContainer; 363 typedef typename TContainer::size_type size_type; 364 typedef typename TContainer::value_type value_type; 365 typedef typename TContainer::iterator iterator; 366 typedef typename TContainer::const_iterator const_iterator; 367 size(void) const368 size_type size(void) const 369 { 370 return m_Container.size(); 371 } 372 clear(void)373 void clear(void) 374 { 375 m_Container.clear(); 376 TParent::clear(); 377 } 378 begin(void) const379 const_iterator begin(void) const 380 { 381 return m_Container.begin(); 382 } end(void) const383 const_iterator end(void) const 384 { 385 return m_Container.end(); 386 } find(const value_type & value) const387 const_iterator find(const value_type& value) const 388 { 389 return m_Container.find(value); 390 } lower_bound(const value_type & value) const391 const_iterator lower_bound(const value_type& value) const 392 { 393 return m_Container.lower_bound(value); 394 } upper_bound(const value_type & value) const395 const_iterator upper_bound(const value_type& value) const 396 { 397 return m_Container.upper_bound(value); 398 } 399 begin(void)400 iterator begin(void) 401 { 402 return m_Container.begin(); 403 } end(void)404 iterator end(void) 405 { 406 return m_Container.end(); 407 } find(const value_type & value)408 iterator find(const value_type& value) 409 { 410 return m_Container.find(value); 411 } lower_bound(const value_type & value)412 iterator lower_bound(const value_type& value) 413 { 414 return m_Container.lower_bound(value); 415 } upper_bound(const value_type & value)416 iterator upper_bound(const value_type& value) 417 { 418 return m_Container.upper_bound(value); 419 } 420 insert(const value_type & value)421 iterator insert(const value_type& value) 422 { 423 iterator iter = m_Container.insert(value); 424 if ( iter == begin() ) 425 this->insertToStart(get(iter)); 426 else { 427 iterator prev = iter; 428 this->insertAfter(get(--prev), get(iter)); 429 } 430 return iter; 431 } 432 erase(iterator iter)433 void erase(iterator iter) 434 { 435 if ( iter == begin() ) 436 this->removeFromStart(get(iter)); 437 else { 438 iterator prev = iter; 439 this->removeAfter(get(--prev), get(iter)); 440 } 441 m_Container.erase(iter); 442 } 443 get(iterator iter)444 static value_type& get(iterator iter) 445 { 446 return const_cast<value_type&>(*iter); 447 } 448 449 #if defined(_RWSTD_VER) && !defined(_RWSTD_STRICT_ANSI) allocation_size(size_type buffer_size)450 size_type allocation_size(size_type buffer_size) 451 { 452 return m_Container.allocation_size(buffer_size); 453 } 454 #endif 455 456 private: 457 TContainer m_Container; 458 }; 459 460 461 /* @} */ 462 463 464 //#include <util/linkedset.inl> 465 466 END_NCBI_SCOPE 467 468 #endif /* LINKEDSET__HPP */ 469