WvStreams
wvlinklist.h
00001 /* -*- Mode: C++ -*-
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  *
00005  * A linked list container.
00006  */
00007 #ifndef __WVLINKLIST_H
00008 #define __WVLINKLIST_H
00009 
00010 #include "wvtypetraits.h"
00011 #include "wvsorter.h"
00012 
00021 class WvListBase
00022 {
00023     WvListBase(const WvListBase &l); // copy constructor - not actually defined anywhere!
00024 private:
00025     //This is private to force people to pass by reference, not by value
00026     WvListBase& operator= (const WvListBase &l);
00027     
00028 public:
00029     WvLink head, *tail;
00030 
00032     WvListBase() : head(NULL, false)
00033         { tail = &head; }
00034 
00043     size_t count() const;
00044 
00053     void reverse();
00054 
00062     bool isempty() const
00063         { return head.next == NULL; }
00064 
00073     class IterBase
00074     {
00075     public:
00076         const WvListBase *list;
00077         WvLink *link, *prev;
00078 
00083         IterBase(const WvListBase &l)
00084             { list = &l; link = NULL; }
00085 
00090         void rewind() // dropping a const pointer here!  Danger!
00091             { prev = NULL; link = &((WvListBase *)list)->head; }
00092 
00093         
00103         WvLink *next()
00104             { prev = link; return link = link->next; }
00105 
00111         WvLink *cur() const
00112             { return link; }
00113         
00118         void *vptr() const
00119             { return link->data; }
00120 
00134         WvLink *find(const void *data);
00135 
00146         WvLink *find_next(const void*data);
00147     };
00148 };
00149 
00150 
00196 template<class T>
00197 class WvList : public WvListBase
00198 {
00199     // copy constructor: not defined anywhere!
00200     WvList(const WvList &list);
00201 
00202 public:
00204     WvList()
00205         { }
00206     
00213     ~WvList()
00214         { zap(); }
00215         
00217     void setup() {}
00218     
00220     void shutdown() {}
00221 
00228     void zap(bool destroy = true)
00229     {
00230         while (head.next)
00231             unlink_after(& head, destroy);
00232     }
00233 
00241     T *first() const
00242         { return (T*)head.next->data; }
00243 
00251     T *last() const
00252         { return (T*)tail->data; }
00253 
00263     void add_after(WvLink *after, T *data, bool autofree,
00264                         const char *id = NULL )
00265     {
00266         (void)new WvLink((void *)data, after, tail, autofree, id);
00267     }
00268 
00276     void append(T *data, bool autofree, const char *id = NULL)
00277         { add_after(tail, data, autofree, id); }
00278 
00283     void add(T *data, bool autofree, const char *id = NULL)
00284         { append(data, autofree, id); }
00285 
00293     void prepend(T *data, bool autofree, const char *id = NULL)
00294         { add_after(&head, data, autofree, id); }
00295 
00303     void unlink(T *data)
00304         { Iter i(*this); while (i.find(data)) i.unlink(); }
00305 
00312     void unlink_first()
00313     { 
00314         if(head.next != NULL)   
00315         { Iter i(*this); i.rewind(); i.next(); i.unlink(); }
00316     }
00325     void unlink_after(WvLink *after, bool destroy = true)
00326     {
00327         WvLink *next = after->next;
00328         if(next != NULL)
00329         {
00330             T *obj = (destroy && next->get_autofree()) ?
00331             static_cast<T*>(next->data) : NULL;
00332             if (next == tail) tail = after;
00333             next->unlink(after);
00334             if (obj)
00335                 WvTraits<T>::release(obj);
00336         }
00337     }
00338 
00350     class Iter : public WvListBase::IterBase
00351     {
00352     public:
00357         Iter(const WvList &l) : IterBase(l)
00358             { }
00359 
00364         T *ptr() const
00365             { return (T *)link->data; }
00366 
00367         WvIterStuff(T);
00368 
00372         bool get_autofree() const
00373         {
00374             return link->get_autofree();
00375         }
00376 
00380         void set_autofree(bool autofree)
00381         {
00382             link->set_autofree(autofree);
00383         }
00384 
00390         void unlink(bool destroy = true)
00391         {
00392             if (prev) ((WvList *)list)->unlink_after(prev, destroy);
00393             link = prev->next;
00394         }
00395         
00409         void xunlink(bool destroy = true)
00410         {
00411             if (prev) ((WvList *)list)->unlink_after(prev, destroy);
00412             link = prev;
00413         }
00414     };
00415     
00417     typedef class WvSorter<T, WvListBase, WvListBase::IterBase> Sorter;
00418 };
00419 
00420 #define DeclareWvList2(_classname_, _type_)  \
00421     typedef class WvList<_type_> _classname_ 
00422 
00423 #define DeclareWvList(_type_) DeclareWvList2(_type_##List, _type_)
00424 
00425 
00426 #endif // __WVLINKLIST_H