diff options
author | Mike Buland <eichlan@xagasoft.com> | 2007-07-03 00:28:59 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2007-07-03 00:28:59 +0000 |
commit | ac517a2b7625e0aa0862679e961c6349f859ea3b (patch) | |
tree | e3e27a6b9bd5e2be6150088495c91fc91786ad9d /src/list.h | |
parent | f8d4301e9fa4f3709258505941e37fab2eadadc6 (diff) | |
parent | bd865cee5f89116c1f054cd0e5c275e97c2d0a9b (diff) | |
download | libbu++-ac517a2b7625e0aa0862679e961c6349f859ea3b.tar.gz libbu++-ac517a2b7625e0aa0862679e961c6349f859ea3b.tar.bz2 libbu++-ac517a2b7625e0aa0862679e961c6349f859ea3b.tar.xz libbu++-ac517a2b7625e0aa0862679e961c6349f859ea3b.zip |
The reorg is being put in trunk, I think it's ready. Now we just get to find
out how many applications won't work anymore :)
Diffstat (limited to '')
-rw-r--r-- | src/list.h | 574 |
1 files changed, 481 insertions, 93 deletions
@@ -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 | 7 | namespace Bu |
6 | * does define all standard interface functions to access a list. | ||
7 | *@author Mike Buland | ||
8 | */ | ||
9 | class List | ||
10 | { | 8 | { |
11 | public: | 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 | ||