1 /* 2 * RNtrack - FTN message tracker/router 3 * 4 * a_list.hpp - Alternative CONTAINER template library 5 * 6 * Copyright (c) 2003-2005 Alex Soukhotine, 2:5030/1157 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * $Id: a_list.hpp 257 2020-01-30 18:19:33Z dukelsky $ 14 */ 15 16 /* 17 Copyright (C) Andrey V. Stolyarov <croco@croco.net> 1997,98,99 18 First compiled with Borland C++ 4.52, Mar 1997 19 Ported to GNU C++ (g++) / Linux Feb 1999 20 */ 21 22 #ifndef _A_LIST_HPP_ 23 #define _A_LIST_HPP_ 24 25 #ifndef NULL 26 #define NULL 0 27 #endif 28 29 class AbstractElem 30 { 31 friend class TAbstractList; 32 AbstractElem * Prev, * Next; 33 // protected: 34 public: AbstractElem()35 AbstractElem() 36 { 37 Prev = Next = NULL; 38 } 39 ~AbstractElem()40 virtual ~AbstractElem() {} 41 operator +(int i)42 AbstractElem * operator +(int i) 43 { 44 if(i == 0) 45 { 46 return this; 47 } 48 49 AbstractElem * el = this; 50 51 if(i > 0) 52 { 53 for(int j = 0; j < i && el; j++, el = el->Next) 54 {} 55 } 56 else 57 { 58 for(int j = 0; j > i && el; j--, el = el->Prev) 59 {} 60 } 61 62 return el; 63 } 64 operator -(int i)65 AbstractElem * operator -(int i) 66 { 67 return operator +(-i); 68 } 69 }; 70 71 72 //////////////////////////////////////////////////////////////////////////////// 73 // "List Of Nothing" - the only use of this class is to derive some 74 // real lists from it. 75 class TAbstractList 76 { 77 private: 78 AbstractElem * First, * Last; 79 80 public: 81 TAbstractList()82 TAbstractList() 83 { 84 First = Last = NULL; 85 } 86 Clear()87 void Clear() 88 { 89 while(First) 90 { 91 AbstractElem * p = First; 92 UnlinkElem(First); 93 delete p; 94 } 95 } 96 UnlinkElem(AbstractElem * el)97 void UnlinkElem(AbstractElem * el) 98 { 99 if(el->Prev) 100 { 101 el->Prev->Next = el->Next; 102 } 103 else 104 { 105 First = el->Next; 106 } 107 108 if(el->Next) 109 { 110 el->Next->Prev = el->Prev; 111 } 112 else 113 { 114 Last = el->Prev; 115 } 116 } 117 LinkElemToBegin(AbstractElem * el)118 void LinkElemToBegin(AbstractElem * el) 119 { 120 el->Prev = NULL; 121 el->Next = First; 122 123 if(First) 124 { 125 First->Prev = el; 126 } 127 else 128 { 129 Last = el; 130 } 131 132 First = el; 133 } 134 LinkElemToEnd(AbstractElem * el)135 void LinkElemToEnd(AbstractElem * el) 136 { 137 el->Next = NULL; 138 el->Prev = Last; 139 140 if(Last) 141 { 142 Last->Next = el; 143 } 144 else 145 { 146 First = el; 147 } 148 149 Last = el; 150 } 151 LinkElemBefore(AbstractElem * el,AbstractElem * newEl)152 void LinkElemBefore(AbstractElem * el, AbstractElem * newEl) 153 { 154 if(!el->Prev) 155 { 156 LinkElemToBegin(newEl); 157 } 158 else 159 { 160 newEl->Prev = el->Prev; 161 newEl->Next = el; 162 el->Prev->Next = newEl; 163 el->Prev = newEl; 164 } 165 } 166 LinkElemAfter(AbstractElem * el,AbstractElem * newEl)167 void LinkElemAfter(AbstractElem * el, AbstractElem * newEl) 168 { 169 if(!el->Next) 170 { 171 LinkElemToEnd(newEl); 172 } 173 else 174 { 175 newEl->Next = el->Next; 176 newEl->Prev = el; 177 el->Next->Prev = newEl; 178 el->Next = newEl; 179 } 180 } 181 MoveElemForward(AbstractElem * el)182 int MoveElemForward(AbstractElem * el) 183 { 184 if(!el->Next) 185 { 186 return 0; 187 } 188 else 189 { 190 AbstractElem * el2 = el->Next; 191 UnlinkElem(el); 192 LinkElemAfter(el2, el); 193 return 1; 194 } 195 } 196 MoveElemBackward(AbstractElem * el)197 int MoveElemBackward(AbstractElem * el) 198 { 199 if(!el->Prev) 200 { 201 return 0; 202 } 203 else 204 { 205 AbstractElem * el2 = el->Prev; 206 UnlinkElem(el); 207 LinkElemBefore(el2, el); 208 return 1; 209 } 210 } 211 MoveElemToBegin(AbstractElem * el)212 void MoveElemToBegin(AbstractElem * el) 213 { 214 UnlinkElem(el); 215 LinkElemToBegin(el); 216 } 217 MoveElemToEnd(AbstractElem * el)218 void MoveElemToEnd(AbstractElem * el) 219 { 220 UnlinkElem(el); 221 LinkElemToEnd(el); 222 } 223 GetFirst()224 AbstractElem * GetFirst() 225 { 226 return First; 227 } 228 GetLast()229 AbstractElem * GetLast() 230 { 231 return Last; 232 } 233 ~TAbstractList()234 ~TAbstractList() 235 { 236 Clear(); 237 } 238 }; 239 240 //////////////////////////////////////////////////////////////////////////////// 241 // Direct list. Useful for classes for which it's no loose to copy them. 242 // For example, it's very good idea to use this particular template with 243 // int, long, float, char etc. 244 // Objects are stored directly in Elements of the list, so actually they are 245 // copies of objects you passed to the methods of the class. This requires T 246 // to have a COPY CONSTRUCTOR. 247 template <class T> 248 class BiList : protected TAbstractList 249 { 250 public: 251 252 class ElemPtr; 253 254 protected: 255 256 class Elem : public AbstractElem 257 { 258 friend class BiList<T>; 259 friend class BiList<T>::ElemPtr; 260 public: 261 T data; operator T&()262 operator T &() 263 { 264 return data; 265 } 266 operator +(int i)267 Elem * operator +(int i) 268 { 269 return (Elem *)((*(AbstractElem *)this) + i); 270 } 271 operator -(int i)272 Elem * operator -(int i) 273 { 274 return (Elem *)((*(AbstractElem *)this) - i); 275 } 276 277 protected: Elem(T & t)278 Elem(T & t) : data(t) {} 279 ~Elem()280 virtual ~Elem() {} 281 }; 282 GetFirstElem()283 Elem * GetFirstElem() 284 { 285 return (Elem *)TAbstractList::GetFirst(); 286 } 287 GetLastElem()288 Elem * GetLastElem() 289 { 290 return (Elem *)TAbstractList::GetLast(); 291 } 292 293 public: 294 295 class ElemPtr 296 { 297 friend class BiList<T>; 298 Elem * p; ElemPtr(Elem * e)299 ElemPtr(Elem * e) 300 { 301 p = e; 302 } 303 304 protected: GetP()305 Elem * GetP() 306 { 307 return p; 308 } 309 310 public: ElemPtr()311 ElemPtr() 312 { 313 p = NULL; 314 } 315 ElemPtr(const ElemPtr & e2)316 ElemPtr(const ElemPtr & e2) 317 { 318 p = e2.p; 319 } 320 ~ElemPtr()321 ~ElemPtr() {} 322 operator ++()323 ElemPtr operator ++() // Preincrement 324 { 325 p = p ? (*p) + 1 : 0; 326 return *this; 327 } 328 operator --()329 ElemPtr operator --() // Predecrement 330 { 331 p = p ? (*p) - 1 : 0; 332 return *this; 333 } 334 operator ++(int)335 ElemPtr operator ++(int) // Postincrement 336 { 337 Elem * p2 = p; 338 339 p = p ? (*p) + 1 : 0; 340 return ElemPtr(p2); 341 } 342 operator --(int)343 ElemPtr operator --(int) // Postdecrement 344 { 345 Elem * p2 = p; 346 347 p = p ? (*p) - 1 : 0; 348 return ElemPtr(p2); 349 } 350 operator +(int i)351 ElemPtr operator +(int i) 352 { 353 return ElemPtr((*p) + i); 354 } 355 operator -(int i)356 ElemPtr operator -(int i) 357 { 358 return ElemPtr((*p) - i); 359 } 360 operator T*()361 operator T *() 362 { 363 return p ? &(p->data) : NULL; 364 } 365 }; 366 367 public: 368 BiList()369 BiList() : TAbstractList() {} 370 ~BiList()371 ~BiList() 372 { 373 Clear(); 374 } 375 AddToBegin(T & t)376 ElemPtr AddToBegin(T & t) 377 { 378 Elem * el = new Elem(t); 379 380 LinkElemToBegin(el); 381 return ElemPtr(el); 382 } 383 AddToEnd(T & t)384 ElemPtr AddToEnd(T & t) 385 { 386 Elem * el = new Elem(t); 387 388 LinkElemToEnd(el); 389 return ElemPtr(el); 390 } 391 InsertBefore(ElemPtr & elp,T & t)392 ElemPtr InsertBefore(ElemPtr & elp, T & t) 393 { 394 Elem * el = elp.GetP(); 395 Elem * nel = new Elem(t); 396 397 LinkElemBefore(el, nel); 398 return ElemPtr(nel); 399 } 400 InsertAfter(ElemPtr & elp,T & t)401 ElemPtr InsertAfter(ElemPtr & elp, T & t) 402 { 403 Elem * el = elp.GetP(); 404 Elem * nel = new Elem(t); 405 406 LinkElemAfter(el, nel); 407 return ElemPtr(nel); 408 } 409 GetFirst()410 ElemPtr GetFirst() 411 { 412 return ElemPtr(GetFirstElem()); 413 } 414 GetLast()415 ElemPtr GetLast() 416 { 417 return ElemPtr(GetLastElem()); 418 } 419 Remove(ElemPtr & elp)420 void Remove(ElemPtr & elp) 421 { 422 Elem * el = elp.GetP(); 423 424 UnlinkElem(el); 425 delete el; 426 } 427 PlaceToBegin(ElemPtr & elp)428 void PlaceToBegin(ElemPtr & elp) 429 { 430 Elem * el = elp.GetP(); 431 432 MoveElemToBegin(el); 433 } 434 PlaceToEnd(ElemPtr & elp)435 void PlaceToEnd(ElemPtr & elp) 436 { 437 Elem * el = elp.GetP(); 438 439 MoveElemToEnd(el); 440 } 441 Clear()442 void Clear() 443 { 444 TAbstractList::Clear(); 445 } 446 IsEmpty()447 int IsEmpty() 448 { 449 return GetFirstElem() == NULL; 450 } 451 ElemCount()452 int ElemCount() 453 { 454 int c = 0; 455 ElemPtr p(GetFirstElem()); 456 457 while(p) 458 { 459 c++; 460 p++; 461 } 462 return c; 463 } 464 }; 465 466 467 #define BILIST_FOREACH(bclass, list, itname) \ 468 for(BiList<bclass>::ElemPtr itname = list->GetFirst(); itname; itname++) 469 470 471 //////////////////////////////////////////////////////////////////////////////// 472 // This template assumes that T is a (small?) structure or class or unit. 473 // The only difference from previous class is that there is operator->() 474 // for ElemPtr which makes it more like a real pointer to an object of T 475 template <class T> 476 class StrBiList : public BiList<T> 477 { 478 public: 479 class ElemPtr : public BiList<T>::ElemPtr 480 { 481 public: ElemPtr(typename BiList<T>::ElemPtr & e)482 ElemPtr(typename BiList<T>::ElemPtr & e) : BiList<T>::ElemPtr(e) {} 483 484 operator T *(); operator ->()485 T * operator ->() 486 { 487 return operator T *(); 488 } 489 }; AddToBegin(T & t)490 ElemPtr AddToBegin(T & t) 491 { 492 return (ElemPtr)BiList<T>::AddToBegin(t); 493 } 494 AddToEnd(T & t)495 ElemPtr AddToEnd(T & t) 496 { 497 return (ElemPtr)BiList<T>::AddToEnd(t); 498 } 499 InsertBefore(ElemPtr & elp,T & t)500 ElemPtr InsertBefore(ElemPtr & elp, T & t) 501 { 502 return (ElemPtr)BiList<T>::InsertBefore(elp, t); 503 } 504 InsertAfter(ElemPtr & elp,T & t)505 ElemPtr InsertAfter(ElemPtr & elp, T & t) 506 { 507 return (ElemPtr)BiList<T>::InsertAfter(elp, t); 508 } 509 GetFirst()510 ElemPtr GetFirst() 511 { 512 return (ElemPtr)BiList<T>::GetFirst(); 513 } 514 GetLast()515 ElemPtr GetLast() 516 { 517 return (ElemPtr)BiList<T>::GetLast(); 518 } 519 }; 520 521 #define STRBILIST_FOREACH(bclass, list, itname) \ 522 for(StrBiList<bclass>::ElemPtr itname = list->GetFirst(); itname; itname++) 523 524 //////////////////////////////////////////////////////////////////////////////// 525 // This class is "Indirect" double-linked list. We assume that it's elements 526 // are classes or structures (please no arrays ;-) to define operator->() to 527 // access them. 528 529 template <class T> 530 class IndBiList : protected TAbstractList 531 { 532 public: 533 534 class ElemPtr; 535 536 protected: 537 538 class Elem : public AbstractElem 539 { 540 friend class IndBiList<T>; 541 friend class ElemPtr; 542 char Owner; 543 public: 544 T * data; operator T*()545 operator T *() 546 { 547 return data; 548 } 549 operator +(int i)550 Elem * operator +(int i) 551 { 552 return (Elem *)((*(AbstractElem *)this) + i); 553 } 554 operator -(int i)555 Elem * operator -(int i) 556 { 557 return (Elem *)((*(AbstractElem *)this) - i); 558 } 559 560 protected: Elem(T * t,char own=1)561 Elem(T * t, char own = 1) 562 { 563 data = t; 564 Owner = own; 565 } 566 ~Elem()567 virtual ~Elem() 568 { 569 if(Owner) 570 { 571 delete data; 572 } 573 } 574 }; 575 GetFirstElem()576 Elem * GetFirstElem() 577 { 578 return (Elem *)TAbstractList::GetFirst(); 579 } 580 GetLastElem()581 Elem * GetLastElem() 582 { 583 return (Elem *)TAbstractList::GetLast(); 584 } 585 586 public: 587 588 class ElemPtr 589 { 590 friend class IndBiList<T>; 591 Elem * p; ElemPtr(Elem * e)592 ElemPtr(Elem * e) 593 { 594 p = e; 595 } 596 597 protected: GetP()598 Elem * GetP() 599 { 600 return p; 601 } 602 603 public: ElemPtr()604 ElemPtr() 605 { 606 p = NULL; 607 } 608 ElemPtr(const ElemPtr & e2)609 ElemPtr(const ElemPtr & e2) 610 { 611 p = e2.p; 612 } 613 ~ElemPtr()614 ~ElemPtr() {} 615 operator ++()616 ElemPtr operator ++() // Preincrement 617 { 618 p = p ? (*p) + 1 : 0; 619 return *this; 620 } 621 operator --()622 ElemPtr operator --() // Predecrement 623 { 624 p = p ? (*p) - 1 : 0; 625 return *this; 626 } 627 operator ++(int)628 ElemPtr operator ++(int) // Postincrement 629 { 630 Elem * p2 = p; 631 632 p = p ? (*p) + 1 : 0; 633 return ElemPtr(p2); 634 } 635 operator --(int)636 ElemPtr operator --(int) // Postdecrement 637 { 638 Elem * p2 = p; 639 640 p = p ? (*p) - 1 : 0; 641 return ElemPtr(p2); 642 } 643 operator +(int i)644 ElemPtr operator +(int i) 645 { 646 return ElemPtr((*p) + i); 647 } 648 operator -(int i)649 ElemPtr operator -(int i) 650 { 651 return ElemPtr((*p) - i); 652 } 653 operator ->() const654 T * operator ->() const 655 { 656 return p ? (T *)p->data : (T *)NULL; 657 } 658 operator T*() const659 operator T *() const 660 { 661 return operator ->(); 662 } 663 // operator T *() const 664 // { 665 // return p ? (T *)p->data : (T *)NULL; 666 // } 667 // T * operator ->() const 668 // { 669 // return operator T *(); 670 // } 671 }; 672 673 674 public: 675 IndBiList()676 IndBiList() : TAbstractList() {} 677 ~IndBiList()678 ~IndBiList() 679 { 680 Clear(); 681 } 682 AddToBegin(T * t,char own=1)683 ElemPtr AddToBegin(T * t, char own = 1) 684 { 685 Elem * el = new Elem(t, own); 686 687 LinkElemToBegin(el); 688 return ElemPtr(el); 689 } 690 AddToEnd(T * t,char own=1)691 ElemPtr AddToEnd(T * t, char own = 1) 692 { 693 Elem * el = new Elem(t, own); 694 695 LinkElemToEnd(el); 696 return ElemPtr(el); 697 } 698 InsertBefore(ElemPtr & elp,T * t,char own=1)699 ElemPtr InsertBefore(ElemPtr & elp, T * t, char own = 1) 700 { 701 Elem * el = elp.GetP(); 702 Elem * nel = new Elem(t, own); 703 704 LinkElemBefore(el, nel); 705 return ElemPtr(nel); 706 } 707 InsertAfter(ElemPtr & elp,T * t,char own=1)708 ElemPtr InsertAfter(ElemPtr & elp, T * t, char own = 1) 709 { 710 Elem * el = elp.GetP(); 711 Elem * nel = new Elem(t, own); 712 713 LinkElemAfter(el, nel); 714 return ElemPtr(nel); 715 } 716 AddToBegin(T & t)717 ElemPtr AddToBegin(T & t) 718 { 719 return AddToBegin(&t, 0); 720 } 721 AddToEnd(T & t)722 ElemPtr AddToEnd(T & t) 723 { 724 return AddToEnd(&t, 0); 725 } 726 InsertBefore(ElemPtr & elp,T & t)727 ElemPtr InsertBefore(ElemPtr & elp, T & t) 728 { 729 return InsertBefore(elp, &t, 0); 730 } 731 InsertAfter(ElemPtr & elp,T & t)732 ElemPtr InsertAfter(ElemPtr & elp, T & t) 733 { 734 return InsertAfter(elp, &t, 0); 735 } 736 GetFirst()737 ElemPtr GetFirst() 738 { 739 return ElemPtr(GetFirstElem()); 740 } 741 GetLast()742 ElemPtr GetLast() 743 { 744 return ElemPtr(GetLastElem()); 745 } 746 Remove(ElemPtr & elp)747 void Remove(ElemPtr & elp) 748 { 749 Elem * el = elp.GetP(); 750 751 UnlinkElem(el); 752 delete el; 753 } 754 PlaceToBegin(ElemPtr & elp)755 void PlaceToBegin(ElemPtr & elp) 756 { 757 Elem * el = elp.GetP(); 758 759 MoveElemToBegin(el); 760 } 761 PlaceToEnd(ElemPtr & elp)762 void PlaceToEnd(ElemPtr & elp) 763 { 764 Elem * el = elp.GetP(); 765 766 MoveElemToEnd(el); 767 } 768 Clear()769 void Clear() 770 { 771 TAbstractList::Clear(); 772 } 773 IsEmpty()774 int IsEmpty() 775 { 776 return GetFirstElem() == NULL; 777 } 778 ElemCount()779 int ElemCount() 780 { 781 int c = 0; 782 ElemPtr p(GetFirstElem()); 783 784 while(p) 785 { 786 c++; 787 p++; 788 } 789 return c; 790 } 791 }; 792 793 #define INDBILIST_FOREACH(bclass, list, itname) \ 794 for(IndBiList<bclass>::ElemPtr itname = list.GetFirst(); itname; itname++) 795 796 #endif // sentry 797 798