Modernized GAlib  3.0.0 current
GAListBASE.h
1 // $Header$
2 /* ----------------------------------------------------------------------------
3  listbase.h
4  mbwall 25nov94
5  Copyright 1995 Massachusetts Institute of Technology
6 
7  DESCRIPTION:
8  This defines the list objects.
9 
10  TO DO:
11  Probably should put the size (and depth for trees) into the templateized
12 class since those take care of memory management. BASE class has no concept of
13 memory management, nor does it know the best way to count what its got.
14 ---------------------------------------------------------------------------- */
15 #ifndef _ga_listbase_h_
16 #define _ga_listbase_h_
17 
18 #include <GANode.h>
19 
20 /* ----------------------------------------------------------------------------
21  GAListBASE
22 -------------------------------------------------------------------------------
23  This is the base list class from which template lists are derived. This
24 object does no memory management - it just keeps track of a list structure.
25 Whoever calls the members of this object is responsible for allocating and
26 deallocating the memory associated with each node.
27  This class does not define any of the iteration operators for traversing the
28 list. That is left to the iterator friend of this class.
29  The iterator class is declared as a friend so that it can access our
30 internals. It iterates over the list without changing anything.
31  We have to break through the const-ness of the list in order to make things
32 work properly. When you ask for the size of a list, you don't change the size
33 but you do (possibly) change the value of the sz member. This doesn't change
34 the state of the tree, so it is, in effect, a const-correct operation. But
35 const is too strict, so we have to work around it. See the size() definition
36 to see how this is done.
37  Beware that copying this object will copy pointers, NOT the contents of the
38 pointers. You cannot simply say list1 = list2 or GAListBASE l = list1. If you
39 do this, you'll get a copy of the list object, but not a duplicate of the list.
40 
41 creation
42  You can create a list by passing a node (the node becomes the head of the
43  list) or by passing nothing (the head of the list is NULL, and the next
44  insert automatically becomes the head).
45 
46 insert
47  Stick a node into the list. Where the node goes depends on the second node
48  and the value of the flag. There are three flag values: head, before, and
49  after. The flag specifies where the new node should go relative to the old
50  node. If you don't pass a value for flag, it defaults to after. The syntax
51  for using the insert method looks like this:
52 
53  mylist.insert(newnode, oldnode, GAListBASE::before);
54  mylist.insert(newnode, oldnode);
55 
56  The node can be a member of a list. If it is, then the list will be broken
57  just previous to the node, then inserted into the list.
58  If the insert was successful, return NO_ERR. If there was a problem,
59  return ERR.
60 
61 remove
62  Remove the specified node from the list. If the node does not exist, an
63  ERR message is posted and NULL is returned. The node is returned if the
64  removal is successful, otherwise NULL.
65 
66 swapnode
67  Switch nodes a and b in the list. Leave the rest of the list intact.
68  If the swap was successful, return NO_ERR. If there was a problem,
69  return ERR.
70 
71 size
72  How many nodes are in the list? We keep a flag to tell us if any operation
73  has been performed that would require a recalculation of the size. If you
74  change the contents of the list using any method other than those in this
75  object (which you could do, by the way) then you risk screwing up the count.
76 ---------------------------------------------------------------------------- */
78 {
79  public:
80  enum Location
81  {
82  HEAD = 0,
83  TAIL,
84  BEFORE,
85  AFTER
86  }; // values for 'where' to insert
87  enum
88  {
89  NO_ERR = 0,
90  ERR = -1
91  }; // return codes
92 
93  GAListBASE()
94  {
95  hd = nullptr;
96  sz = 0;
97  csz = 0;
98  }
99  explicit GAListBASE(GANodeBASE *n)
100  {
101  hd = n;
102  csz = 1;
103  }
104 
105  int size() const;
106 
107  protected:
108  GANodeBASE *remove(GANodeBASE *n);
109 
118  int insert(GANodeBASE *n, GANodeBASE *idx, Location where = AFTER);
119  int swapnode(GANodeBASE *a, GANodeBASE *b);
120 
121  int sz, csz; // number of nodes, have contents changed?
122  GANodeBASE *hd; // the head node of the list
123 
124  private:
125  GAListBASE(const GAListBASE &) {} // copying is not allowed
126  GAListBASE &operator=(const GAListBASE &) { return *this; } // or op=
127  friend class GAListIterBASE;
128 };
129 
130 /* ----------------------------------------------------------------------------
131  GAListIterBASE
132 -------------------------------------------------------------------------------
133  This is the base class for iterators for the list objects. We define this
134 class separately from the List object so that you can have multiple interators
135 for each list and so that you can more easily customize the traversal
136 algorithms within the iterator. From the object point of view, the way you
137 traverse a list is independent of how you represent the list.
138  Like the ListBASE object, this object doesn't do any memory allocation or
139 deallocation. All we do is provide list traversal.
140  Notice that we keep a 'current location' in the list - whatever your last
141 query was is stored as the node, so if you refer to the current member, you'll
142 get your last query.
143  If you pass a NULL node to these routines they will not break; passing a NULL
144 will result in a no-op, and NULL will be returned.
145 
146 creation
147  When you create an iterator, you should pass another iterator (the new one
148  will copy the first) or a list (the iterator will default to the head node
149  of the list).
150 
151 current, head, tail, next, prev, warp
152  Set the iterator to the specified node and return a pointer to the node that
153  the iterator now points to. If current is NULL or a NULL is passed to one of
154  these routines, a NULL is returned and the iterator does not move.
155 
156 warp
157  Move the iterator to the node referenced by index. The head node is node '0'
158  then the count increases from there.
159 ---------------------------------------------------------------------------- */
161 {
162  public:
164  {
165  node = nullptr;
166  list = (GAListBASE *)nullptr;
167  }
168  explicit GAListIterBASE(const GAListBASE &t)
169  {
170  list = &t;
171  node = t.hd;
172  }
174  {
175  list = i.list;
176  node = i.node;
177  }
178  void operator()(const GAListBASE &t)
179  {
180  list = &t;
181  node = t.hd;
182  }
183  GANodeBASE *current(GANodeBASE *c)
184  {
185  return (c != nullptr ? (node = c) : nullptr);
186  }
187  GANodeBASE *current() { return node; }
188  GANodeBASE *next()
189  {
190  return (node != nullptr ? (node = node->next) : nullptr);
191  }
192  GANodeBASE *next(GANodeBASE *c)
193  {
194  return (c != nullptr ? (node = c->next) : nullptr);
195  }
196  GANodeBASE *prev()
197  {
198  return (node != nullptr ? (node = node->prev) : nullptr);
199  }
200  GANodeBASE *prev(GANodeBASE *c)
201  {
202  return (c != nullptr ? (node = c->prev) : nullptr);
203  }
204  GANodeBASE *head() { return (list != nullptr ? (node = list->hd) : nullptr); }
205  GANodeBASE *tail()
206  {
207  return (((list != nullptr) && (list->hd != nullptr)) ? (node = list->hd->prev) : nullptr);
208  }
209  GANodeBASE *warp(unsigned int);
210  GANodeBASE *warp(const GAListIterBASE &i)
211  {
212  list = i.list;
213  node = nullptr;
214  return (i.node != nullptr ? (node = i.node) : nullptr);
215  }
216  int size() { return (list != nullptr ? list->size() : 0); }
217 
218  protected:
219  GANodeBASE *node;
220  const GAListBASE *list;
221 };
222 
223 #endif
Definition: GAListBASE.h:78
int insert(GANodeBASE *n, GANodeBASE *idx, Location where=AFTER)
Definition: GAListBASE.h:161
This is the basic node object.
Definition: GANode.h:18