aboutsummaryrefslogtreecommitdiff
path: root/src/list.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/list.h')
-rw-r--r--src/list.h574
1 files changed, 481 insertions, 93 deletions
diff --git a/src/list.h b/src/list.h
index c71b328..e05ebbc 100644
--- a/src/list.h
+++ b/src/list.h
@@ -1,101 +1,489 @@
1#ifndef LIST_H 1#ifndef BU_LIST_H
2#define LIST_H 2#define BU_LIST_H
3 3
4#include <memory>
5#include "bu/exceptionbase.h"
4 6
5/** The basic List class ADT. This, on it's own, does absolutely nothing, but 7namespace Bu
6 * does define all standard interface functions to access a list.
7 *@author Mike Buland
8 */
9class List
10{ 8{
11public: 9 template<typename value>
12 /** 10 struct ListLink
13 * Construct a list. 11 {
14 */ 12 value *pValue;
15 List(); 13 ListLink *pNext;
14 ListLink *pPrev;
15 };
16 16
17 /** 17 /**
18 * Desconstruct a list. 18 * Linked list template container. This class is similar to the stl list
19 * class except for a few minor changes. First, it doesn't mimic a stack or
20 * queue, use the Stack or Queue clasess for that. Second, when const, all
21 * members are only accessable const. Third, erasing a location does not
22 * invalidate the iterator, it simply points to the next valid location, or
23 * end() if there are no more.
24 *
25 *@param value (typename) The type of data to store in your list
26 *@param valuealloc (typename) Memory Allocator for your value type
27 *@param linkalloc (typename) Memory Allocator for the list links.
19 */ 28 */
20 virtual ~List(); 29 template<typename value, typename valuealloc=std::allocator<value>, typename linkalloc=std::allocator<struct ListLink<value> > >
21 30 class List
22 /** Gets the value at a specified index. 31 {
23 *@param nIndex The index of the item to return. 32 private:
24 *@returns The specified item, or NULL if the index was beyond the range 33 typedef struct ListLink<value> Link;
25 * of the list. 34 typedef class List<value, valuealloc, linkalloc> MyType;
26 *@author Mike Buland
27 */
28 virtual void *getAt( int nIndex ) = 0;
29
30 /** Append the given data to the end of the list. This increases the
31 * size of the list by one.
32 *@param pData The data to append to the list.
33 *@author Mike Buland
34 */
35 virtual void append( void *pData ) = 0;
36
37 /** Inserts an item at the specified position in the list. The
38 * new item takes the index that you specify, and all other items
39 * are moved up one position. The size of the list is increased by
40 * one.
41 *@param pData The value to insert into the list.
42 *@param nPos Where to insert the data into the list.
43 *@author Mike Buland
44 */
45 virtual void insertBefore( void *pData, int nPos = 0 ) = 0;
46
47 /** Determines the size of the list, in elements.
48 *@returns The size of the list.
49 *@author Mike Buland
50 */
51 virtual int getSize( ) = 0;
52
53 /** Determines if the list is empty or not.
54 *@returns True if the list is empty, or false if the list has
55 * data in it (if the size is greater than zero).
56 *@author Mike Buland
57 */
58 virtual bool isEmpty( ) = 0;
59
60 /** Deletes an item at the specified index and moves all other
61 * values down one index. The size of the list is decreased by one.
62 *@param nIndex The index of the item to delete.
63 *@author Mike Buland
64 */
65 virtual void deleteAt( int nIndex ) = 0;
66
67 /** Completely empties the list, and sets the effective size to
68 * zero.
69 *@author Mike Buland
70 */
71 virtual void empty() = 0;
72
73 /** Sets the size of the list. This can be larger or smaller
74 * than what it was previously. If larger, new blank items will
75 * be added to the end of the list. If smaller than the old list
76 * items will be deleted from the end.
77 *@param nNewSize The new size of the list.
78 *@author Mike Buland
79 */
80 virtual void setSize( int nNewSize ) = 0;
81
82 /** Sets a member at a specified location to a new value.
83 * If the member being set is outside of the range of the
84 * current list it should be expanded.
85 *@param nIndex The zero-based index of the item to change.
86 *@param pData The new value for that index.
87 *@author Mike Buland
88 */
89 virtual void setAt( int nIndex, void *pData ) = 0;
90
91 /** Makes the List work like an array. Just say listObj[2] to get
92 * the third element.
93 *@param nIndex The index to access in the list.
94 *@returns A pointer to the data at element index.
95 *@author Mike Buland
96 */
97 void *operator[]( int nIndex ) { return getAt( nIndex ); };
98};
99 35
100#endif 36 public:
37 List() :
38 pFirst( NULL ),
39 pLast( NULL ),
40 nSize( 0 )
41 {
42 }
43
44 List( const MyType &src ) :
45 pFirst( NULL ),
46 pLast( NULL ),
47 nSize( 0 )
48 {
49 for( Link *pCur = src.pFirst; pCur; pCur = pCur->pNext )
50 {
51 append( *pCur->pValue );
52 }
53 }
54
55 ~List()
56 {
57 clear();
58 }
59
60 /**
61 * Assignment operator.
62 *@param src (const MyType &) The list to assign to your list.
63 */
64 MyType &operator=( const MyType &src )
65 {
66 clear();
67 for( Link *pCur = src.pFirst; pCur; pCur = pCur->pNext )
68 {
69 append( *pCur->pValue );
70 }
71 }
72
73 /**
74 * Clear the data from the list.
75 */
76 void clear()
77 {
78 Link *pCur = pFirst;
79 for(;;)
80 {
81 if( pCur == NULL ) break;
82 va.destroy( pCur->pValue );
83 va.deallocate( pCur->pValue, 1 );
84 Link *pTmp = pCur->pNext;
85 la.destroy( pCur );
86 la.deallocate( pCur, 1 );
87 pCur = pTmp;
88 }
89 pFirst = pLast = NULL;
90 nSize = 0;
91 }
92
93 /**
94 * Append a value to the list.
95 *@param v (const value_type &) The value to append.
96 */
97 void append( const value &v )
98 {
99 Link *pNew = la.allocate( 1 );
100 pNew->pValue = va.allocate( 1 );
101 va.construct( pNew->pValue, v );
102 nSize++;
103 if( pFirst == NULL )
104 {
105 // Empty list
106 pFirst = pLast = pNew;
107 pNew->pNext = pNew->pPrev = NULL;
108 }
109 else
110 {
111 pNew->pNext = NULL;
112 pNew->pPrev = pLast;
113 pLast->pNext = pNew;
114 pLast = pNew;
115 }
116 }
117
118 /**
119 * Prepend a value to the list.
120 *@param v (const value_type &) The value to prepend.
121 */
122 void prepend( const value &v )
123 {
124 Link *pNew = la.allocate( 1 );
125 pNew->pValue = va.allocate( 1 );
126 va.construct( pNew->pValue, v );
127 nSize++;
128 if( pFirst == NULL )
129 {
130 // Empty list
131 pFirst = pLast = pNew;
132 pNew->pNext = pNew->pPrev = NULL;
133 }
134 else
135 {
136 pNew->pNext = pFirst;
137 pNew->pPrev = NULL;
138 pFirst->pPrev = pNew;
139 pFirst = pNew;
140 }
141 }
142
143 /**
144 * An iterator to iterate through your list.
145 */
146 typedef struct iterator
147 {
148 friend class List<value, valuealloc, linkalloc>;
149 private:
150 Link *pLink;
151 iterator() :
152 pLink( NULL )
153 {
154 }
155
156 iterator( Link *pLink ) :
157 pLink( pLink )
158 {
159 }
160
161 public:
162 /**
163 * Equals comparison operator.
164 *@param oth (const iterator &) The iterator to compare to.
165 *@returns (bool) Are they equal?
166 */
167 bool operator==( const iterator &oth ) const
168 {
169 return ( pLink == oth.pLink );
170 }
171
172 /**
173 * Equals comparison operator.
174 *@param pOth (const Link *) The link to compare to.
175 *@returns (bool) Are they equal?
176 */
177 bool operator==( const Link *pOth ) const
178 {
179 return ( pLink == pOth );
180 }
181
182 /**
183 * Not equals comparison operator.
184 *@param oth (const iterator &) The iterator to compare to.
185 *@returns (bool) Are they not equal?
186 */
187 bool operator!=( const iterator &oth ) const
188 {
189 return ( pLink != oth.pLink );
190 }
191
192 /**
193 * Not equals comparison operator.
194 *@param pOth (const Link *) The link to compare to.
195 *@returns (bool) Are they not equal?
196 */
197 bool operator!=( const Link *pOth ) const
198 {
199 return ( pLink != pOth );
200 }
201
202 /**
203 * Dereference operator.
204 *@returns (value_type &) The value.
205 */
206 value &operator*()
207 {
208 return *(pLink->pValue);
209 }
210
211 /**
212 * Pointer access operator.
213 *@returns (value_type *) A pointer to the value.
214 */
215 value *operator->()
216 {
217 return pLink->pValue;
218 }
219
220 /**
221 * Increment operator.
222 */
223 iterator &operator++()
224 {
225 if( pLink != NULL )
226 pLink = pLink->pNext;
227 return *this;
228 }
229
230 /**
231 * Decrement operator.
232 */
233 iterator &operator--()
234 {
235 if( pLink != NULL )
236 pLink = pLink->pPrev;
237 return *this;
238 }
239
240 /**
241 * Increment operator.
242 */
243 iterator &operator++( int )
244 {
245 if( pLink != NULL )
246 pLink = pLink->pNext;
247 return *this;
248 }
249
250 /**
251 * Decrement operator.
252 */
253 iterator &operator--( int )
254 {
255 if( pLink != NULL )
256 pLink = pLink->pPrev;
257 return *this;
258 }
259
260 /**
261 * Assignment operator.
262 *@param oth (const iterator &) The other iterator to set this
263 * one to.
264 */
265 iterator &operator=( const iterator &oth )
266 {
267 pLink = oth.pLink;
268 return *this;
269 }
270 };
271
272 /**
273 *@see iterator
274 */
275 typedef struct const_iterator
276 {
277 friend class List<value, valuealloc, linkalloc>;
278 private:
279 Link *pLink;
280 const_iterator() :
281 pLink( NULL )
282 {
283 }
101 284
285 const_iterator( Link *pLink ) :
286 pLink( pLink )
287 {
288 }
289
290 const_iterator( const iterator &i ) :
291 pLink( i.pLink )
292 {
293 }
294
295 public:
296 bool operator==( const const_iterator &oth ) const
297 {
298 return ( pLink == oth.pLink );
299 }
300
301 bool operator==( const Link *pOth ) const
302 {
303 return ( pLink == pOth );
304 }
305
306 bool operator!=( const const_iterator &oth ) const
307 {
308 return ( pLink != oth.pLink );
309 }
310
311 bool operator!=( const Link *pOth ) const
312 {
313 return ( pLink != pOth );
314 }
315
316 const value &operator*()
317 {
318 return *(pLink->pValue);
319 }
320
321 const value *operator->()
322 {
323 return pLink->pValue;
324 }
325
326 const_iterator &operator++()
327 {
328 if( pLink != NULL )
329 pLink = pLink->pNext;
330 return *this;
331 }
332
333 const_iterator &operator--()
334 {
335 if( pLink != NULL )
336 pLink = pLink->pPrev;
337 return *this;
338 }
339
340 const_iterator &operator++( int )
341 {
342 if( pLink != NULL )
343 pLink = pLink->pNext;
344 return *this;
345 }
346
347 const_iterator &operator--( int )
348 {
349 if( pLink != NULL )
350 pLink = pLink->pPrev;
351 return *this;
352 }
353
354 const_iterator &operator=( const iterator &oth )
355 {
356 pLink = oth.pLink;
357 return *this;
358 }
359
360 const_iterator &operator=( const const_iterator &oth )
361 {
362 pLink = oth.pLink;
363 return *this;
364 }
365 };
366
367 /**
368 * Get an iterator pointing to the first item in the list.
369 *@returns (iterator)
370 */
371 iterator begin()
372 {
373 return iterator( pFirst );
374 }
375
376 /**
377 * Get a const iterator pointing to the first item in the list.
378 *@returns (const const_iterator)
379 */
380 const const_iterator begin() const
381 {
382 return const_iterator( pFirst );
383 }
384
385 /**
386 * Get an iterator pointing to a place just past the last item in
387 * the list.
388 *@returns (const Link *)
389 */
390 const Link *end() const
391 {
392 return NULL;
393 }
394
395 /**
396 * Erase an item from the list.
397 *@param i (iterator) The item to erase.
398 */
399 void erase( iterator &i )
400 {
401 Link *pCur = i.pLink;
402 Link *pPrev = pCur->pPrev;
403 if( pPrev == NULL )
404 {
405 va.destroy( pCur->pValue );
406 va.deallocate( pCur->pValue, 1 );
407 pFirst = pCur->pNext;
408 la.destroy( pCur );
409 la.deallocate( pCur, 1 );
410 if( pFirst == NULL )
411 pLast = NULL;
412 nSize--;
413 i.pLink = pFirst;
414 }
415 else
416 {
417 va.destroy( pCur->pValue );
418 va.deallocate( pCur->pValue, 1 );
419 Link *pTmp = pCur->pNext;
420 la.destroy( pCur );
421 la.deallocate( pCur, 1 );
422 pPrev->pNext = pTmp;
423 if( pTmp != NULL )
424 pTmp->pPrev = pPrev;
425 nSize--;
426 i.pLink = pTmp;
427 }
428 }
429
430 /**
431 * Get the current size of the list.
432 *@returns (int) The current size of the list.
433 */
434 int getSize() const
435 {
436 return nSize;
437 }
438
439 /**
440 * Get the first item in the list.
441 *@returns (value_type &) The first item in the list.
442 */
443 value &first()
444 {
445 return *pFirst->pValue;
446 }
447
448 /**
449 * Get the first item in the list.
450 *@returns (const value_type &) The first item in the list.
451 */
452 const value &first() const
453 {
454 return *pFirst->pValue;
455 }
456
457 /**
458 * Get the last item in the list.
459 *@returns (value_type &) The last item in the list.
460 */
461 value &last()
462 {
463 return *pLast->pValue;
464 }
465
466 /**
467 * Get the last item in the list.
468 *@returns (const value_type &) The last item in the list.
469 */
470 const value &last() const
471 {
472 return *pLast->pValue;
473 }
474
475 const bool isEmpty() const
476 {
477 return (nSize == 0);
478 }
479
480 private:
481 Link *pFirst;
482 Link *pLast;
483 linkalloc la;
484 valuealloc va;
485 int nSize;
486 };
487}
488
489#endif