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 private:
00025
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()
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
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 char *id = NULL )
00265 {
00266 (void)new WvLink((void *)data, after, tail, autofree, id);
00267 }
00268
00276 void append(T *data, bool autofree, char *id = NULL)
00277 { add_after(tail, data, autofree, id); }
00278
00283 void add(T *data, bool autofree, char *id = NULL)
00284 { append(data, autofree, id); }
00285
00293 void prepend(T *data, bool autofree, 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 { Iter i(*this); i.rewind(); i.next(); i.unlink(); }
00314
00323 void unlink_after(WvLink *after, bool destroy = true)
00324 {
00325 WvLink *next = after->next;
00326 T *obj = (destroy && next->get_autofree()) ?
00327 static_cast<T*>(next->data) : NULL;
00328 if (next == tail) tail = after;
00329 next->unlink(after);
00330 if (obj)
00331 WvTraits<T>::release(obj);
00332 }
00333
00345 class Iter : public WvListBase::IterBase
00346 {
00347 public:
00352 Iter(const WvList &l) : IterBase(l)
00353 { }
00354
00359 T *ptr() const
00360 { return (T *)link->data; }
00361
00362 WvIterStuff(T);
00363
00367 bool get_autofree() const
00368 {
00369 return link->get_autofree();
00370 }
00371
00375 void set_autofree(bool autofree)
00376 {
00377 link->set_autofree(autofree);
00378 }
00379
00385 void unlink(bool destroy = true)
00386 {
00387 if (prev) ((WvList *)list)->unlink_after(prev, destroy);
00388 link = prev->next;
00389 }
00390
00404 void xunlink(bool destroy = true)
00405 {
00406 if (prev) ((WvList *)list)->unlink_after(prev, destroy);
00407 link = prev;
00408 }
00409 };
00410
00412 typedef class WvSorter<T, WvListBase, WvListBase::IterBase> Sorter;
00413 };
00414
00415 #define DeclareWvList2(_classname_, _type_) \
00416 typedef class WvList<_type_> _classname_
00417
00418 #define DeclareWvList(_type_) DeclareWvList2(_type_##List, _type_)
00419
00420
00421 #endif