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