filters

list.h
1/* This file is part of the LibMSWrite Library
2 Copyright (C) 2001-2003 Clarence Dang <clarencedang@users.sourceforge.net>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License Version 2 as published by the Free Software Foundation.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License Version 2 for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 Version 2 along with this library; see the file COPYING.LIB. If not,
15 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 * Boston, MA 02110-1301, USA.
17
18 LibMSWrite Project Website:
19 http://sourceforge.net/projects/libmswrite/
20*/
21
22/*
23 * list.h - linked list implementation
24 * This file ensures that we do not have to depend on STL but don't waste
25 * time and memory trying to reallocate arrays.
26 *
27 * An implementation without C++-style iterators would have taken half
28 * as many lines and would probably be twice as efficient...
29 *
30 */
31
32#ifndef __MSWRITE_LIST_H__
33#define __MSWRITE_LIST_H__
34
35#ifndef NULL
36 #define NULL 0
37#endif
38
39#include <assert.h>
40// TODO: _desperately_ need to implement ConstIterator so that all the List<dtype>::end (void) const's can have the const etc.
41namespace MSWrite
42{
43 template <class dtype> class List;
44 template <class dtype> class ListIterator;
45 template <class dtype>
46 class ListElement
47 {
48 private:
49 dtype m_data;
50 ListElement *m_prev, *m_next;
51
52 public:
53 ListElement ()
54 {
55 m_prev = m_next = NULL;
56 }
57
58 ListElement (dtype &data)
59 {
60 m_prev = m_next = NULL;
61 m_data = data;
62 }
63
64 ~ListElement ()
65 {
66 }
67
68 dtype &getData (void) const
69 {
70 return m_data;
71 }
72 dtype &operator* (void) const
73 {
74 return m_data;
75 }
76 bool operator== (const ListElement &rhs)
77 {
78 return this->m_data == rhs.m_data;
79 }
80
81 void setData (const dtype &data)
82 {
83 m_data = data;
84 }
85 dtype &operator= (const ListElement &rhs)
86 {
87 if (this == &rhs)
88 return *this;
89
90 this->m_data = rhs.m_data;
91 return this->m_data;
92 }
93
94 friend class List <dtype>;
95 friend class ListIterator <dtype>;
96 };
97
98 template <class dtype> class List;
99 template <class dtype>
100 class ListIterator
101 {
102 private:
103 bool m_forward;
104 ListElement <dtype> *m_upto;
105
106 void setPtr (ListElement <dtype> *ptr)
107 {
108 m_upto = ptr;
109 }
110
111 public:
112 ListIterator (const bool forward = true)
113 {
114 m_forward = forward;
115 }
116
117 ListIterator <dtype> &prev (void)
118 {
119 if (m_forward)
120 m_upto = m_upto->m_prev;
121 else
122 m_upto = m_upto->m_next;
123
124 return *this;
125 }
126
127 ~ListIterator ()
128 {
129 }
130
131 ListIterator <dtype> &operator-- (void)
132 {
133 return prev ();
134 }
135
136 ListIterator <dtype> &operator-- (int)
137 {
138 return prev ();
139 }
140
141 ListIterator <dtype> &next (void)
142 {
143 if (m_forward)
144 m_upto = m_upto->m_next;
145 else
146 m_upto = m_upto->m_prev;
147
148 return *this;
149 }
150
151 ListIterator <dtype> &operator++ (void)
152 {
153 return next ();
154 }
155
156 ListIterator <dtype> &operator++ (int)
157 {
158 return next ();
159 }
160
161 bool operator== (const ListIterator <dtype> &rhs)
162 {
163 return this->m_upto == rhs.m_upto;
164 }
165
166 bool operator!= (const ListIterator <dtype> &rhs)
167 {
168 return this->m_upto != rhs.m_upto;
169 }
170
171 dtype &operator* (void)
172 {
173 //return *(*m_upto); // why doesn't this work?
174 return m_upto->m_data;
175 }
176
177 friend class List <dtype>;
178 };
179
180 template <class dtype>
181 class List
182 {
183 private:
184 ListElement <dtype> *m_head, *m_tail;
185 int m_num;
186 bool m_good;
187
188 public:
189 List ()
190 {
191 m_head = m_tail = (ListElement <dtype> *) NULL;
192 m_num = 0;
193 m_good = true;
194 }
195
196 virtual ~List ()
197 {
198 killself ();
199 }
200
201 void killself (void)
202 {
203 ListElement <dtype> *e = m_head;
204 ListElement <dtype> *nexte;
205 while (e)
206 {
207 nexte = e->m_next;
208 delete e;
209 e = nexte;
210 }
211 m_head = m_tail = NULL;
212 m_num = 0;
213 m_good = true;
214 }
215
216 bool empty (void) const
217 {
218 return m_head;
219 }
220
221 bool good (void) const
222 {
223 return m_good;
224 }
225
226 bool bad (void) const
227 {
228 return !good ();
229 }
230
231 bool addToFront (dtype &data)
232 {
233 ListElement <dtype> *e = new ListElement <dtype> (data);
234 if (!e)
235 {
236 m_good = false;
237 return false;
238 }
239
240 if (m_head)
241 {
242 e->next = m_head;
243 m_head->prev = e;
244 m_head = e;
245 }
246 // empty
247 else
248 {
249 m_head = m_tail = e;
250 }
251
252 m_num++;
253 return true;
254 }
255
256 bool addToBack (void)
257 {
258 ListElement <dtype> *e = new ListElement <dtype> ();
259 if (!e)
260 {
261 m_good = false;
262 return false;
263 }
264
265 if (m_tail)
266 {
267 e->m_prev = m_tail;
268 m_tail->m_next = e;
269 m_tail = e;
270 }
271 // empty
272 else
273 {
274 m_head = m_tail = e;
275 }
276
277 m_num++;
278 return true;
279 }
280
281 // for efficiency, you can call the above void argument list version
282 // and initialise the data within the list yourself (avoiding a copy)
283 bool addToBack (const dtype &data)
284 {
285 if (!addToBack ())
286 return false;
287 m_tail->setData (data);
288 return true;
289 }
290
291 int getNumElements (void) const
292 {
293 return m_num;
294 }
295
296 List <dtype> &operator= (const List <dtype> &rhs)
297 {
298 if (this == &rhs)
299 return *this;
300
301 killself ();
302
303 m_num = rhs.m_num;
304 m_good = rhs.m_good;
305
306 ListElement <dtype> *e = rhs.m_head;
307 while (e)
308 {
309 if (!addToBack (e->m_data)) break;
310 e = e->m_next;
311 }
312
313 return *this;
314 }
315
316 typedef ListIterator <dtype> Iterator;
317 friend class ListIterator <dtype>;
318
319 ListIterator <dtype> begin (const bool forward = true) const
320 {
321 ListIterator <dtype> ret (forward);
322 if (forward)
323 ret.setPtr (m_head);
324 else
325 ret.setPtr (m_tail);
326 return ret; // not a reference
327 }
328
329 ListIterator <dtype> end (void) const
330 {
331 ListIterator <dtype> ret;
332 ret.setPtr (NULL); // true regardless of which direction
333 return ret; // not a reference
334 }
335
336 ListIterator <dtype> erase (ListIterator <dtype> &it)
337 {
338 // regardless of iterator direction
339 ListElement <dtype> *eat = it.m_upto;
340 ListElement <dtype> *prevElement = it.m_upto->m_prev;
341 ListElement <dtype> *nextElement = it.m_upto->m_next;
342 it++;
343 delete (eat);
344
345 if (prevElement)
346 prevElement->m_next = nextElement;
347 else
348 m_head = nextElement;
349
350 if (nextElement)
351 nextElement->m_prev = prevElement;
352 else
353 m_tail = prevElement;
354
355 m_num--;
356 return it;
357 }
358
359 ListIterator <dtype> search (const dtype &value) const
360 {
361 ListIterator <dtype> it;
362 for (it = begin (); it != end (); it++)
363 {
364 if ((*it) == value)
365 break;
366 }
367
368 // not reference
369 return it;
370 }
371 };
372} // namespace MSWrite {
373
374#endif // #ifndef __MSWRITE_LIST_H__
375
376// end of list.h