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 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