00001
00002
00003
00004
00005
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);
00024 protected:
00025 WvListBase& operator= (const WvListBase &l);
00026
00027 public:
00028 WvLink head, *tail;
00029
00031 WvListBase() : head(NULL, false)
00032 { tail = &head; }
00033
00042 size_t count() const;
00043
00052 void reverse();
00053
00061 bool isempty() const
00062 { return head.next == NULL; }
00063
00072 class IterBase
00073 {
00074 public:
00075 const WvListBase *list;
00076 WvLink *link, *prev;
00077
00082 IterBase(const WvListBase &l)
00083 { list = &l; link = NULL; }
00084
00089 void rewind()
00090 { prev = NULL; link = &((WvListBase *)list)->head; }
00091
00092
00102 WvLink *next()
00103 { prev = link; return link = link->next; }
00104
00110 WvLink *cur() const
00111 { return link; }
00112
00117 void *vptr() const
00118 { return link->data; }
00119
00135 WvLink *find(const void *data);
00136 };
00137 };
00138
00139
00185 template<class T>
00186 class WvList : public WvListBase
00187 {
00188
00189 WvList(const WvList &list);
00190
00191 public:
00193 WvList()
00194 { }
00195
00202 ~WvList()
00203 { zap(); }
00204
00206 void setup() {}
00207
00209 void shutdown() {}
00210
00217 void zap(bool destroy = true)
00218 {
00219 while (head.next)
00220 unlink_after(& head, destroy);
00221 }
00222
00230 T *first() const
00231 { return (T*)head.next->data; }
00232
00240 T *last() const
00241 { return (T*)tail->data; }
00242
00252 void add_after(WvLink *after, T *data, bool auto_free,
00253 char *id = NULL )
00254 {
00255 (void)new WvLink((void *)data, after, tail, auto_free, id);
00256 }
00257
00265 void append(T *data, bool auto_free, char *id = NULL)
00266 { add_after(tail, data, auto_free, id); }
00267
00272 void add(T *data, bool auto_free, char *id = NULL)
00273 { append(data, auto_free, id); }
00274
00282 void prepend(T *data, bool auto_free, char *id = NULL)
00283 { add_after(&head, data, auto_free, id); }
00284
00292 void unlink(T *data)
00293 { Iter i(*this); while (i.find(data)) i.unlink(); }
00294
00301 void unlink_first()
00302 { Iter i(*this); i.rewind(); i.next(); i.unlink(); }
00303
00312 void unlink_after(WvLink *after, bool destroy = true)
00313 {
00314 WvLink *next = after->next;
00315 T *obj = (destroy && next->auto_free) ?
00316 static_cast<T*>(next->data) : NULL;
00317 if (next == tail) tail = after;
00318 next->unlink(after);
00319 if (obj)
00320 WvTraits<T>::release(obj);
00321 }
00322
00334 class Iter : public WvListBase::IterBase
00335 {
00336 public:
00341 Iter(const WvList &l) : IterBase(l)
00342 { }
00343
00348 T *ptr() const
00349 { return (T *)link->data; }
00350
00351 WvIterStuff(T);
00352
00358 void unlink()
00359 {
00360 if (prev) ((WvList *)list)->unlink_after(prev);
00361 link = prev->next;
00362 }
00363
00377 void xunlink()
00378 {
00379 if (prev) ((WvList *)list)->unlink_after(prev);
00380 link = prev;
00381 }
00382 };
00383
00385 typedef class WvSorter<T, WvListBase, WvListBase::IterBase> Sorter;
00386 };
00387
00388 #define DeclareWvList2(_classname_, _type_) \
00389 typedef class WvList<_type_> _classname_
00390
00391 #define DeclareWvList(_type_) DeclareWvList2(_type_##List, _type_)
00392
00393
00394 #endif