WvStreams
wvlinklist.h
1 /* -*- Mode: C++ -*-
2  * Worldvisions Weaver Software:
3  * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4  *
5  * A linked list container.
6  */
7 #ifndef __WVLINKLIST_H
8 #define __WVLINKLIST_H
9 
10 #include "wvtypetraits.h"
11 #include "wvsorter.h"
12 
22 {
23  WvListBase(const WvListBase &l); // copy constructor - not actually defined anywhere!
24 private:
25  //This is private to force people to pass by reference, not by value
26  WvListBase& operator= (const WvListBase &l);
27 
28 public:
29  WvLink head, *tail;
30 
32  WvListBase() : head(NULL, false)
33  { tail = &head; }
34 
43  size_t count() const;
44 
53  void reverse();
54 
62  bool isempty() const
63  { return head.next == NULL; }
64 
73  class IterBase
74  {
75  public:
76  const WvListBase *list;
77  WvLink *link, *prev;
78 
83  IterBase(const WvListBase &l)
84  { list = &l; link = NULL; }
85 
90  void rewind() // dropping a const pointer here! Danger!
91  { prev = NULL; link = &((WvListBase *)list)->head; }
92 
93 
104  { prev = link; return link = link->next; }
105 
111  WvLink *cur() const
112  { return link; }
113 
118  void *vptr() const
119  { return link->data; }
120 
134  WvLink *find(const void *data);
135 
146  WvLink *find_next(const void*data);
147  };
148 };
149 
150 
196 template<class T>
197 class WvList : public WvListBase
198 {
199  // copy constructor: not defined anywhere!
200  WvList(const WvList &list);
201 
202 public:
205  { }
206 
214  { zap(); }
215 
217  void setup() {}
218 
220  void shutdown() {}
221 
228  void zap(bool destroy = true)
229  {
230  while (head.next)
231  unlink_after(& head, destroy);
232  }
233 
241  T *first() const
242  { return (T*)head.next->data; }
243 
251  T *last() const
252  { return (T*)tail->data; }
253 
263  void add_after(WvLink *after, T *data, bool autofree,
264  const char *id = NULL )
265  {
266  (void)new WvLink((void *)data, after, tail, autofree, id);
267  }
268 
276  void append(T *data, bool autofree, const char *id = NULL)
277  { add_after(tail, data, autofree, id); }
278 
283  void add(T *data, bool autofree, const char *id = NULL)
284  { append(data, autofree, id); }
285 
293  void prepend(T *data, bool autofree, const char *id = NULL)
294  { add_after(&head, data, autofree, id); }
295 
303  void unlink(T *data)
304  { Iter i(*this); while (i.find(data)) i.unlink(); }
305 
313  {
314  if(head.next != NULL)
315  { Iter i(*this); i.rewind(); i.next(); i.unlink(); }
316  }
325  void unlink_after(WvLink *after, bool destroy = true)
326  {
327  WvLink *next = after->next;
328  if(next != NULL)
329  {
330  T *obj = (destroy && next->get_autofree()) ?
331  static_cast<T*>(next->data) : NULL;
332  if (next == tail) tail = after;
333  next->unlink(after);
334  if (obj)
336  }
337  }
338 
350  class Iter : public WvListBase::IterBase
351  {
352  public:
357  Iter(const WvList &l) : IterBase(l)
358  { }
359 
364  T *ptr() const
365  { return (T *)link->data; }
366 
367  WvIterStuff(T);
368 
372  bool get_autofree() const
373  {
374  return link->get_autofree();
375  }
376 
380  void set_autofree(bool autofree)
381  {
382  link->set_autofree(autofree);
383  }
384 
390  void unlink(bool destroy = true)
391  {
392  if (prev) ((WvList *)list)->unlink_after(prev, destroy);
393  link = prev->next;
394  }
395 
409  void xunlink(bool destroy = true)
410  {
411  if (prev) ((WvList *)list)->unlink_after(prev, destroy);
412  link = prev;
413  }
414  };
415 
418 };
419 
420 #define DeclareWvList2(_classname_, _type_) \
421  typedef class WvList<_type_> _classname_
422 
423 #define DeclareWvList(_type_) DeclareWvList2(_type_##List, _type_)
424 
425 
426 #endif // __WVLINKLIST_H