Template class to implement a list with a fixed maximum number of elements (i.e. number of elements in the list is dynamic but cannot exceed the initially defined value)

Dependents:   FixedLengthListTest XBeeApi

Committer:
johnb
Date:
Wed Jan 29 23:01:01 2014 +0000
Revision:
2:16c77b601175
Parent:
1:d98987d1d67c
Add remove() method

Who changed what in which revision?

UserRevisionLine numberNew contents of line
johnb 0:99d701354221 1 /**
johnb 0:99d701354221 2 @file
johnb 2:16c77b601175 3 @brief Template class ( FixedLengthList ) to implement a list with
johnb 0:99d701354221 4 a limited number of elements.
johnb 0:99d701354221 5
johnb 2:16c77b601175 6 @author John Bailey
johnb 0:99d701354221 7
johnb 0:99d701354221 8 @copyright Copyright 2013 John Bailey
johnb 0:99d701354221 9
johnb 0:99d701354221 10 @section LICENSE
johnb 2:16c77b601175 11
johnb 0:99d701354221 12 Licensed under the Apache License, Version 2.0 (the "License");
johnb 0:99d701354221 13 you may not use this file except in compliance with the License.
johnb 0:99d701354221 14 You may obtain a copy of the License at
johnb 0:99d701354221 15
johnb 0:99d701354221 16 http://www.apache.org/licenses/LICENSE-2.0
johnb 0:99d701354221 17
johnb 0:99d701354221 18 Unless required by applicable law or agreed to in writing, software
johnb 0:99d701354221 19 distributed under the License is distributed on an "AS IS" BASIS,
johnb 0:99d701354221 20 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
johnb 0:99d701354221 21 See the License for the specific language governing permissions and
johnb 0:99d701354221 22 limitations under the License.
johnb 0:99d701354221 23
johnb 0:99d701354221 24 */
johnb 0:99d701354221 25
johnb 0:99d701354221 26 #if !defined FIXEDLENGTHLIST_HPP
johnb 0:99d701354221 27 #define FIXEDLENGTHLIST_HPP
johnb 0:99d701354221 28
johnb 0:99d701354221 29 #include <cstddef> // for size_t, NULL
johnb 0:99d701354221 30 #include <cstring> // For memset()
johnb 0:99d701354221 31 #include <algorithm> // for min()
johnb 0:99d701354221 32
johnb 0:99d701354221 33 #ifndef STATIC_ASSERT
johnb 0:99d701354221 34 /** Emulation of C++11's static_assert */
johnb 0:99d701354221 35 #define STATIC_ASSERT( condition, name ) typedef char assert_failed_ ## name [ (condition) ? 1 : -1 ]
johnb 0:99d701354221 36 #endif
johnb 0:99d701354221 37
johnb 1:d98987d1d67c 38 /*
johnb 1:d98987d1d67c 39 Each item in the FixedLengthList is wrapped in a
johnb 1:d98987d1d67c 40 FixedLengthListItem which provides the actual item and
johnb 1:d98987d1d67c 41 infrastructure support for the list */
johnb 1:d98987d1d67c 42 template < class L > class FixedLengthListItem
johnb 1:d98987d1d67c 43 {
johnb 1:d98987d1d67c 44 public:
johnb 1:d98987d1d67c 45 /** Pointer to the next item in the list */
johnb 1:d98987d1d67c 46 FixedLengthListItem<L>* m_forward;
johnb 1:d98987d1d67c 47 /** The content/value of the item itself */
johnb 1:d98987d1d67c 48 L m_item;
johnb 1:d98987d1d67c 49 };
johnb 1:d98987d1d67c 50
johnb 1:d98987d1d67c 51
johnb 1:d98987d1d67c 52 /**
johnb 1:d98987d1d67c 53 Iterator support class for FixedLengthList
johnb 1:d98987d1d67c 54
johnb 1:d98987d1d67c 55 Example:
johnb 1:d98987d1d67c 56 \code
johnb 1:d98987d1d67c 57 #define LIST_LEN (20U)
johnb 1:d98987d1d67c 58 FixedLengthList<int, LIST_LEN > list;
johnb 1:d98987d1d67c 59
johnb 1:d98987d1d67c 60 int main( void ) {
johnb 1:d98987d1d67c 61 // List is empty
johnb 1:d98987d1d67c 62
johnb 1:d98987d1d67c 63 list.queue( 111 );
johnb 1:d98987d1d67c 64 list.queue( 222 );
johnb 1:d98987d1d67c 65
johnb 1:d98987d1d67c 66 FixedLengthList<int, LIST_LEN>::iterator it = list.begin();
johnb 1:d98987d1d67c 67 *it == 111;
johnb 1:d98987d1d67c 68 it++;
johnb 1:d98987d1d67c 69 *it == 222;
johnb 1:d98987d1d67c 70 it++;
johnb 1:d98987d1d67c 71 *it == list.end();
johnb 1:d98987d1d67c 72 }
johnb 1:d98987d1d67c 73 \endcode
johnb 1:d98987d1d67c 74 */
johnb 1:d98987d1d67c 75 template< class T, size_t queueMax > class FixedLengthListIter
johnb 1:d98987d1d67c 76 {
johnb 1:d98987d1d67c 77 protected:
johnb 1:d98987d1d67c 78 /** The iterator hooks into the used list within the FixedLengthList */
johnb 1:d98987d1d67c 79 FixedLengthListItem<T>* m_item;
johnb 1:d98987d1d67c 80 public:
johnb 1:d98987d1d67c 81 /** Void constructor - iterator will be equal to T::end() */
johnb 1:d98987d1d67c 82 FixedLengthListIter( void );
johnb 1:d98987d1d67c 83 /** Construct an iterator which points to a list item within a
johnb 1:d98987d1d67c 84 FixedLengthList */
johnb 1:d98987d1d67c 85 FixedLengthListIter( FixedLengthListItem<T>* p_item );
johnb 1:d98987d1d67c 86 /** De-reference operator, yields the value of the list item */
johnb 1:d98987d1d67c 87 T& operator*();
johnb 1:d98987d1d67c 88 /** Inequality operator */
johnb 1:d98987d1d67c 89 bool operator!=( const FixedLengthListIter& p_comp ) const;
johnb 1:d98987d1d67c 90 /** Equality operator */
johnb 1:d98987d1d67c 91 bool operator==( const FixedLengthListIter& p_comp ) const;
johnb 1:d98987d1d67c 92 /** Move the iterator forward a specified number of list elements
johnb 1:d98987d1d67c 93
johnb 1:d98987d1d67c 94 \param p_inc Number of items to traverse */
johnb 1:d98987d1d67c 95 FixedLengthListIter& operator+=( const unsigned p_inc );
johnb 1:d98987d1d67c 96 /** Post-increment operator */
johnb 1:d98987d1d67c 97 FixedLengthListIter operator++( int p_int );
johnb 1:d98987d1d67c 98 /** Pre-increment operator */
johnb 1:d98987d1d67c 99 FixedLengthListIter& operator++( void );
johnb 1:d98987d1d67c 100 };
johnb 1:d98987d1d67c 101
johnb 1:d98987d1d67c 102
johnb 0:99d701354221 103 /**
johnb 0:99d701354221 104 Template class to implement a list with a fixed maximum
johnb 0:99d701354221 105 number of elements (i.e. the number of elements in the list
johnb 0:99d701354221 106 is variable but cannot exceed a defined maximum).
johnb 2:16c77b601175 107
johnb 0:99d701354221 108 While stl::list may be suitable for many
johnb 0:99d701354221 109 occasions, it invariably makes use of dynamic memory
johnb 0:99d701354221 110 allocation which can either be undesirable or overkill
johnb 0:99d701354221 111 in some situations. Of course, the down side of this
johnb 0:99d701354221 112 class is that the memory required to store all items
johnb 2:16c77b601175 113 in the list is allocated for the duration of the
johnb 0:99d701354221 114 instantiation.
johnb 0:99d701354221 115
johnb 0:99d701354221 116 The implementation is based around a singly linked list
johnb 0:99d701354221 117 with a stack of free elements. Adding an item to the list
johnb 0:99d701354221 118 causes one of the free elements to be popped, populated
johnb 0:99d701354221 119 then inserted into the linked list of used elements. For
johnb 0:99d701354221 120 convenience both a head and tail pointer of the used list
johnb 0:99d701354221 121 are maintained.
johnb 0:99d701354221 122
johnb 0:99d701354221 123 Note that the class currently is not thread safe.
johnb 2:16c77b601175 124
johnb 0:99d701354221 125 Example:
johnb 0:99d701354221 126 \code
johnb 0:99d701354221 127 #define LIST_LEN (20U)
johnb 0:99d701354221 128 FixedLengthList<int, LIST_LEN > list;
johnb 0:99d701354221 129
johnb 0:99d701354221 130 int main( void ) {
johnb 0:99d701354221 131 int i;
johnb 0:99d701354221 132
johnb 0:99d701354221 133 // List is empty
johnb 0:99d701354221 134
johnb 0:99d701354221 135 list.queue( 111 );
johnb 0:99d701354221 136 // List now contains 111
johnb 0:99d701354221 137
johnb 0:99d701354221 138 list.queue( 222 );
johnb 0:99d701354221 139 // List now contains 111, 222
johnb 0:99d701354221 140
johnb 0:99d701354221 141 list.push( 333 );
johnb 0:99d701354221 142 // List now contains 333, 111, 222
johnb 0:99d701354221 143
johnb 0:99d701354221 144 list.pop( &i );
johnb 0:99d701354221 145 // i == 333
johnb 0:99d701354221 146 // List now contains 111, 222
johnb 0:99d701354221 147
johnb 0:99d701354221 148 return 0;
johnb 0:99d701354221 149 }
johnb 0:99d701354221 150 \endcode
johnb 0:99d701354221 151 */
johnb 0:99d701354221 152 template < class T, size_t queueMax > class FixedLengthList
johnb 0:99d701354221 153 {
johnb 0:99d701354221 154 /* Pointless to have a queue with no space in it, so the various methods
johnb 0:99d701354221 155 shouldn't have to deal with this situation */
johnb 0:99d701354221 156 STATIC_ASSERT( queueMax > 0, Queue_must_have_a_non_zero_length );
johnb 0:99d701354221 157
johnb 0:99d701354221 158 private:
johnb 0:99d701354221 159
johnb 0:99d701354221 160 /** Pool of list items */
johnb 0:99d701354221 161 FixedLengthListItem<T> m_items[ queueMax ];
johnb 0:99d701354221 162
johnb 1:d98987d1d67c 163
johnb 0:99d701354221 164 /** Pointer to the start of the queue of free list slots. Will be NULL
johnb 0:99d701354221 165 in the case that there none are available */
johnb 0:99d701354221 166 FixedLengthListItem<T>* m_freeHead;
johnb 0:99d701354221 167
johnb 0:99d701354221 168 /** Pointer to the first item in the list of utilised item slots. Will
johnb 0:99d701354221 169 be NULL in the case that there are none */
johnb 0:99d701354221 170 FixedLengthListItem<T>* m_usedHead;
johnb 0:99d701354221 171
johnb 0:99d701354221 172 /** Pointer to the last item in the list of utilised item slots. Will
johnb 0:99d701354221 173 be NULL in the case that there are none */
johnb 0:99d701354221 174 FixedLengthListItem<T>* m_usedTail;
johnb 0:99d701354221 175
johnb 0:99d701354221 176 /** Keep count of the number of used items on the list. Ranges between
johnb 0:99d701354221 177 0 and queueMax */
johnb 0:99d701354221 178 size_t m_usedCount;
johnb 0:99d701354221 179
johnb 2:16c77b601175 180 /** Remove the specified item from the list.
johnb 2:16c77b601175 181
johnb 2:16c77b601175 182 \p_item Item to be removed. Note that item must exist in the list
johnb 2:16c77b601175 183 of used items
johnb 2:16c77b601175 184 */
johnb 2:16c77b601175 185 void remove_node( FixedLengthListItem<T>* p_item );
johnb 2:16c77b601175 186
johnb 0:99d701354221 187 public:
johnb 0:99d701354221 188 /** Constructor for FixedLengthList */
johnb 0:99d701354221 189 FixedLengthList( void );
johnb 0:99d701354221 190
johnb 0:99d701354221 191 /** Initialising constructor for FixedLengthList. Parameters will be
johnb 0:99d701354221 192 used to initialise the list
johnb 2:16c77b601175 193
johnb 0:99d701354221 194 \param p_items An array of items used to initialise the list. They
johnb 0:99d701354221 195 will be added in the order in which they appear in
johnb 0:99d701354221 196 p_items
johnb 0:99d701354221 197 \param p_count The number of items in p_items. Only up to queueMax
johnb 0:99d701354221 198 items will be used - any additional items will be
johnb 0:99d701354221 199 ignored */
johnb 0:99d701354221 200 FixedLengthList( const T* const p_items, size_t p_count );
johnb 0:99d701354221 201
johnb 0:99d701354221 202 /**
johnb 0:99d701354221 203 push an item onto the front of the list
johnb 0:99d701354221 204
johnb 0:99d701354221 205 \param p_item The item to be added to the list
johnb 0:99d701354221 206 \returns true in the case that the item was added
johnb 0:99d701354221 207 false in the case that the item was not added (no space) */
johnb 0:99d701354221 208 bool push( const T p_item );
johnb 0:99d701354221 209
johnb 0:99d701354221 210 /**
johnb 0:99d701354221 211 pop an item from the front of the list (item is removed and returned
johnb 0:99d701354221 212
johnb 0:99d701354221 213 \param p_item Pointer to be populated with the value of the item
johnb 0:99d701354221 214 \returns true in the case that an item was returned
johnb 0:99d701354221 215 false in the case that an item was not returned (list empty)
johnb 0:99d701354221 216 */
johnb 0:99d701354221 217 bool pop( T* const p_item );
johnb 0:99d701354221 218
johnb 0:99d701354221 219 /**
johnb 0:99d701354221 220 queue an item onto the end of the list
johnb 0:99d701354221 221
johnb 0:99d701354221 222 \param p_item The item to be added to the list
johnb 0:99d701354221 223 \returns true in the case that the item was added
johnb 0:99d701354221 224 false in the case that the item was not added (no space) */
johnb 0:99d701354221 225 bool queue( const T p_item );
johnb 0:99d701354221 226
johnb 0:99d701354221 227 /**
johnb 0:99d701354221 228 dequeue an item from the end of the list (item is removed and
johnb 0:99d701354221 229 returned
johnb 0:99d701354221 230
johnb 0:99d701354221 231 \param p_item Pointer to be populated with the value of the item
johnb 0:99d701354221 232 \returns true in the case that an item was returned
johnb 0:99d701354221 233 false in the case that an item was not returned (list empty)
johnb 0:99d701354221 234 */
johnb 0:99d701354221 235 bool dequeue( T* const p_item );
johnb 0:99d701354221 236
johnb 2:16c77b601175 237 /** Remove the first node matching p_item from the list. In the case
johnb 2:16c77b601175 238 that there are multiple matches, only the first is removed.
johnb 2:16c77b601175 239
johnb 2:16c77b601175 240 \param p_item Value to be removed
johnb 2:16c77b601175 241 \returns true in the case that an item was matched and remove
johnb 2:16c77b601175 242 false in the case that no item could be matched
johnb 2:16c77b601175 243 */
johnb 2:16c77b601175 244 bool remove( const T p_item );
johnb 2:16c77b601175 245
johnb 0:99d701354221 246 /** Used to find out how many items are in the list
johnb 0:99d701354221 247
johnb 0:99d701354221 248 \returns Number of used items, ranging from 0 to queueMax */
johnb 0:99d701354221 249 size_t used() const;
johnb 0:99d701354221 250
johnb 0:99d701354221 251 /** Used to find out how many slots are still available in the list
johnb 0:99d701354221 252
johnb 0:99d701354221 253 \returns Number of available slots, ranging from 0 to queueMax */
johnb 0:99d701354221 254 size_t available() const;
johnb 0:99d701354221 255
johnb 0:99d701354221 256 /** Determine whether or not a particular item is in the list
johnb 0:99d701354221 257
johnb 0:99d701354221 258 \param p_val Item to be matched against
johnb 0:99d701354221 259 \returns true in the case that the item is found in the list
johnb 0:99d701354221 260 false in the case that it is not found in the list
johnb 0:99d701354221 261 */
johnb 0:99d701354221 262 bool inList( const T p_val ) const;
johnb 0:99d701354221 263
johnb 0:99d701354221 264 /** Remove the entire contents of the list and return it back to
johnb 0:99d701354221 265 an empty state */
johnb 0:99d701354221 266 void clear( void );
johnb 1:d98987d1d67c 267
johnb 1:d98987d1d67c 268 typedef FixedLengthListIter<T, queueMax> iterator;
johnb 1:d98987d1d67c 269 typedef T value_type;
johnb 1:d98987d1d67c 270 typedef T * pointer;
johnb 1:d98987d1d67c 271 typedef T & reference;
johnb 1:d98987d1d67c 272
johnb 1:d98987d1d67c 273 iterator begin( void );
johnb 1:d98987d1d67c 274 iterator end( void );
johnb 0:99d701354221 275 };
johnb 0:99d701354221 276
johnb 1:d98987d1d67c 277
johnb 0:99d701354221 278 template < class T, size_t queueMax >
johnb 0:99d701354221 279 FixedLengthList< T, queueMax >::FixedLengthList( void )
johnb 0:99d701354221 280 {
johnb 0:99d701354221 281 clear();
johnb 0:99d701354221 282 }
johnb 0:99d701354221 283
johnb 0:99d701354221 284 template < class T, size_t queueMax >
johnb 1:d98987d1d67c 285 FixedLengthList< T, queueMax >::FixedLengthList( const T* const p_items, size_t p_count )
johnb 1:d98987d1d67c 286 {
johnb 0:99d701354221 287
johnb 0:99d701354221 288 const T* src = p_items;
johnb 0:99d701354221 289
johnb 0:99d701354221 290 /* Can only populate up to queueMax items */
johnb 0:99d701354221 291 size_t init_count = std::min( queueMax, p_count );
johnb 0:99d701354221 292 FixedLengthListItem<T>* prev = NULL;
johnb 0:99d701354221 293
johnb 0:99d701354221 294 m_usedHead = NULL;
johnb 0:99d701354221 295 m_usedTail = NULL;
johnb 0:99d701354221 296
johnb 0:99d701354221 297 /* Initialise the list from p_items, building the forward links */
johnb 0:99d701354221 298 for( size_t i = 0;
johnb 0:99d701354221 299 i < init_count;
johnb 0:99d701354221 300 i++ )
johnb 0:99d701354221 301 {
johnb 0:99d701354221 302 FixedLengthListItem<T>* current = &(m_items[i]);
johnb 0:99d701354221 303
johnb 0:99d701354221 304 current->m_forward = NULL;
johnb 0:99d701354221 305 current->m_item = *(src++);
johnb 0:99d701354221 306
johnb 0:99d701354221 307 /* If there was a previous item in the list, set up its forward pointer,
johnb 0:99d701354221 308 otherwise set up the list head */
johnb 0:99d701354221 309 if( prev != NULL ) {
johnb 0:99d701354221 310 prev->m_forward = current;
johnb 0:99d701354221 311 } else {
johnb 0:99d701354221 312 m_usedHead = current;
johnb 0:99d701354221 313 }
johnb 0:99d701354221 314
johnb 0:99d701354221 315 m_usedTail = current;
johnb 0:99d701354221 316
johnb 0:99d701354221 317 prev = current;
johnb 0:99d701354221 318 }
johnb 0:99d701354221 319
johnb 0:99d701354221 320 m_usedCount = init_count;
johnb 0:99d701354221 321
johnb 0:99d701354221 322 m_freeHead = NULL;
johnb 0:99d701354221 323
johnb 0:99d701354221 324 /* Any remaining items get moved into the free stack */
johnb 0:99d701354221 325
johnb 0:99d701354221 326 prev = NULL;
johnb 0:99d701354221 327 for( size_t i = init_count;
johnb 0:99d701354221 328 i < queueMax;
johnb 0:99d701354221 329 i++ )
johnb 0:99d701354221 330 {
johnb 0:99d701354221 331 FixedLengthListItem<T>* current = &(m_items[i]);
johnb 0:99d701354221 332 current->m_forward = NULL;
johnb 0:99d701354221 333 if( prev != NULL ) {
johnb 0:99d701354221 334 prev->m_forward = current;
johnb 0:99d701354221 335 } else {
johnb 0:99d701354221 336 m_freeHead = current;
johnb 0:99d701354221 337 }
johnb 0:99d701354221 338 prev = current;
johnb 0:99d701354221 339 }
johnb 0:99d701354221 340 }
johnb 0:99d701354221 341
johnb 0:99d701354221 342 template < class T, size_t queueMax >
johnb 0:99d701354221 343 void FixedLengthList< T, queueMax >::clear( void )
johnb 0:99d701354221 344 {
johnb 0:99d701354221 345 FixedLengthListItem<T>* p;
johnb 0:99d701354221 346 size_t i;
johnb 0:99d701354221 347
johnb 0:99d701354221 348 m_usedHead = NULL;
johnb 0:99d701354221 349 m_usedTail = NULL;
johnb 0:99d701354221 350 m_freeHead = m_items;
johnb 0:99d701354221 351
johnb 0:99d701354221 352 /* Move all items into the free stack, setting up the forward links */
johnb 0:99d701354221 353 for( p = m_items, i = (queueMax-1);
johnb 0:99d701354221 354 i > 0 ;
johnb 0:99d701354221 355 i-- )
johnb 0:99d701354221 356 {
johnb 0:99d701354221 357 FixedLengthListItem<T>* next = p+1;
johnb 0:99d701354221 358 p->m_forward = next;
johnb 0:99d701354221 359 p = next;
johnb 0:99d701354221 360 }
johnb 0:99d701354221 361 p->m_forward = NULL;
johnb 0:99d701354221 362 m_usedCount = 0U;
johnb 0:99d701354221 363 }
johnb 0:99d701354221 364
johnb 0:99d701354221 365 template < class T, size_t queueMax >
johnb 0:99d701354221 366 bool FixedLengthList< T, queueMax >::push( const T p_item )
johnb 0:99d701354221 367 {
johnb 0:99d701354221 368 bool ret_val = false;
johnb 0:99d701354221 369
johnb 0:99d701354221 370 /* Check that there's space in the list */
johnb 0:99d701354221 371 if( m_freeHead != NULL )
johnb 0:99d701354221 372 {
johnb 0:99d701354221 373 FixedLengthListItem<T>* new_item = m_freeHead;
johnb 0:99d701354221 374
johnb 0:99d701354221 375 /* Move the head pointer to the next free item in the list */
johnb 0:99d701354221 376 m_freeHead = new_item->m_forward;
johnb 0:99d701354221 377
johnb 0:99d701354221 378 new_item->m_forward = m_usedHead;
johnb 0:99d701354221 379
johnb 0:99d701354221 380 new_item->m_item = p_item;
johnb 0:99d701354221 381
johnb 0:99d701354221 382 m_usedHead = new_item;
johnb 0:99d701354221 383
johnb 0:99d701354221 384 if( m_usedTail == NULL )
johnb 0:99d701354221 385 {
johnb 0:99d701354221 386 m_usedTail = new_item;
johnb 0:99d701354221 387 }
johnb 0:99d701354221 388
johnb 0:99d701354221 389 m_usedCount++;
johnb 0:99d701354221 390
johnb 0:99d701354221 391 /* Indicate success */
johnb 0:99d701354221 392 ret_val = true;
johnb 0:99d701354221 393 }
johnb 0:99d701354221 394
johnb 0:99d701354221 395 return ret_val;
johnb 0:99d701354221 396 }
johnb 0:99d701354221 397
johnb 0:99d701354221 398 template < class T, size_t queueMax >
johnb 0:99d701354221 399 bool FixedLengthList< T, queueMax >::queue( const T p_item )
johnb 0:99d701354221 400 {
johnb 0:99d701354221 401 bool ret_val = false;
johnb 0:99d701354221 402
johnb 0:99d701354221 403 /* Check that there's space in the list */
johnb 0:99d701354221 404 if( m_freeHead != NULL )
johnb 0:99d701354221 405 {
johnb 0:99d701354221 406 /* Grab a free item */
johnb 0:99d701354221 407 FixedLengthListItem<T>* new_item = m_freeHead;
johnb 0:99d701354221 408
johnb 0:99d701354221 409 /* Move the head pointer to the next free item in the list */
johnb 0:99d701354221 410 m_freeHead = m_freeHead->m_forward;
johnb 0:99d701354221 411
johnb 0:99d701354221 412 /* Item is going at end of list - no forward link */
johnb 0:99d701354221 413 new_item->m_forward = NULL;
johnb 0:99d701354221 414
johnb 0:99d701354221 415 new_item->m_item = p_item;
johnb 0:99d701354221 416
johnb 0:99d701354221 417 /* Update the current tail item, if exists */
johnb 0:99d701354221 418 if( m_usedTail != NULL )
johnb 0:99d701354221 419 {
johnb 0:99d701354221 420 m_usedTail->m_forward = new_item;
johnb 0:99d701354221 421 }
johnb 0:99d701354221 422
johnb 0:99d701354221 423 m_usedTail = new_item;
johnb 0:99d701354221 424
johnb 0:99d701354221 425 if( m_usedHead == NULL )
johnb 0:99d701354221 426 {
johnb 0:99d701354221 427 m_usedHead = new_item;
johnb 0:99d701354221 428 }
johnb 0:99d701354221 429
johnb 0:99d701354221 430 m_usedCount++;
johnb 0:99d701354221 431
johnb 0:99d701354221 432 /* Indicate success */
johnb 0:99d701354221 433 ret_val = true;
johnb 0:99d701354221 434 }
johnb 0:99d701354221 435
johnb 0:99d701354221 436 return ret_val;
johnb 0:99d701354221 437 }
johnb 0:99d701354221 438
johnb 0:99d701354221 439 template < class T, size_t queueMax >
johnb 0:99d701354221 440 bool FixedLengthList< T, queueMax >::pop( T* const p_item )
johnb 0:99d701354221 441 {
johnb 0:99d701354221 442 bool ret_val = false;
johnb 0:99d701354221 443
johnb 0:99d701354221 444 if( m_usedHead != NULL )
johnb 0:99d701354221 445 {
johnb 0:99d701354221 446 FixedLengthListItem<T>* old_item = m_usedHead;
johnb 0:99d701354221 447
johnb 0:99d701354221 448 *p_item = old_item->m_item;
johnb 0:99d701354221 449
johnb 0:99d701354221 450 m_usedHead = old_item->m_forward;
johnb 0:99d701354221 451
johnb 0:99d701354221 452 if( m_usedTail == old_item )
johnb 0:99d701354221 453 {
johnb 0:99d701354221 454 m_usedTail = NULL;
johnb 0:99d701354221 455 }
johnb 0:99d701354221 456
johnb 0:99d701354221 457 old_item->m_forward = m_freeHead;
johnb 0:99d701354221 458
johnb 0:99d701354221 459 m_freeHead = old_item;
johnb 0:99d701354221 460
johnb 0:99d701354221 461 m_usedCount--;
johnb 0:99d701354221 462
johnb 0:99d701354221 463 /* Indicate success */
johnb 0:99d701354221 464 ret_val = true;
johnb 0:99d701354221 465 }
johnb 0:99d701354221 466
johnb 0:99d701354221 467 return ret_val;
johnb 0:99d701354221 468 }
johnb 0:99d701354221 469
johnb 0:99d701354221 470 template < class T, size_t queueMax >
johnb 0:99d701354221 471 bool FixedLengthList< T, queueMax >::dequeue( T* const p_item )
johnb 0:99d701354221 472 {
johnb 0:99d701354221 473 bool ret_val = false;
johnb 2:16c77b601175 474
johnb 0:99d701354221 475 if( m_usedTail != NULL )
johnb 0:99d701354221 476 {
johnb 0:99d701354221 477 FixedLengthListItem<T>* old_item = m_usedTail;
johnb 0:99d701354221 478
johnb 0:99d701354221 479 *p_item = old_item->m_item;
johnb 0:99d701354221 480
johnb 2:16c77b601175 481 remove_node( old_item );
johnb 0:99d701354221 482
johnb 0:99d701354221 483 /* Indicate success */
johnb 0:99d701354221 484 ret_val = true;
johnb 0:99d701354221 485 }
johnb 0:99d701354221 486
johnb 0:99d701354221 487 return ret_val;
johnb 0:99d701354221 488 }
johnb 2:16c77b601175 489
johnb 2:16c77b601175 490
johnb 2:16c77b601175 491 template < class T, size_t queueMax >
johnb 2:16c77b601175 492 void FixedLengthList< T, queueMax >::remove_node( FixedLengthListItem<T>* p_item )
johnb 2:16c77b601175 493 {
johnb 2:16c77b601175 494 /* Item removed was only item in the list? */
johnb 2:16c77b601175 495 if( m_usedHead == p_item )
johnb 2:16c77b601175 496 {
johnb 2:16c77b601175 497 m_usedHead = NULL;
johnb 2:16c77b601175 498 m_usedTail = NULL;
johnb 2:16c77b601175 499 } else {
johnb 2:16c77b601175 500 FixedLengthListItem<T>* p = m_usedHead;
johnb 2:16c77b601175 501
johnb 2:16c77b601175 502 /* Need to update the forward pointer of the
johnb 2:16c77b601175 503 item preceding the one which we've just removed.
johnb 2:16c77b601175 504 That item also becomes the new tail
johnb 2:16c77b601175 505
johnb 2:16c77b601175 506 Iterate the list and find it */
johnb 2:16c77b601175 507 while( p != NULL )
johnb 2:16c77b601175 508 {
johnb 2:16c77b601175 509 if( p->m_forward == p_item )
johnb 2:16c77b601175 510 {
johnb 2:16c77b601175 511 p->m_forward = NULL;
johnb 2:16c77b601175 512 m_usedTail = p;
johnb 2:16c77b601175 513 break;
johnb 2:16c77b601175 514 }
johnb 2:16c77b601175 515 else
johnb 2:16c77b601175 516 {
johnb 2:16c77b601175 517 p = p->m_forward;
johnb 2:16c77b601175 518 }
johnb 2:16c77b601175 519 }
johnb 2:16c77b601175 520 }
johnb 2:16c77b601175 521
johnb 2:16c77b601175 522 /* Move item to free list */
johnb 2:16c77b601175 523 p_item->m_forward = m_freeHead;
johnb 2:16c77b601175 524 m_freeHead = p_item;
johnb 2:16c77b601175 525
johnb 2:16c77b601175 526 m_usedCount--;
johnb 2:16c77b601175 527 }
johnb 2:16c77b601175 528
johnb 2:16c77b601175 529 template < class T, size_t queueMax >
johnb 2:16c77b601175 530 bool FixedLengthList< T, queueMax >::remove( const T p_item )
johnb 2:16c77b601175 531 {
johnb 2:16c77b601175 532 bool ret_val = false;
johnb 2:16c77b601175 533 FixedLengthListItem<T>* last = NULL;
johnb 2:16c77b601175 534 FixedLengthListItem<T>* p = m_usedHead;
johnb 2:16c77b601175 535
johnb 2:16c77b601175 536 /* Run through all the items in the used list */
johnb 2:16c77b601175 537 while( p != NULL )
johnb 2:16c77b601175 538 {
johnb 2:16c77b601175 539 /* Does the item match the one we're looking for? */
johnb 2:16c77b601175 540 if( p->m_item == p_item )
johnb 2:16c77b601175 541 {
johnb 2:16c77b601175 542 /* If there was no last item then this must be the head, so update
johnb 2:16c77b601175 543 the head pointer, otherwise update the forward pointer on the
johnb 2:16c77b601175 544 prevceding item in the list */
johnb 2:16c77b601175 545 if( last == NULL )
johnb 2:16c77b601175 546 {
johnb 2:16c77b601175 547 m_usedHead = p->m_forward;
johnb 2:16c77b601175 548 }
johnb 2:16c77b601175 549 else
johnb 2:16c77b601175 550 {
johnb 2:16c77b601175 551 last->m_forward = p->m_forward;
johnb 2:16c77b601175 552 }
johnb 2:16c77b601175 553
johnb 2:16c77b601175 554 /* Is this item the tail? If so, update! */
johnb 2:16c77b601175 555 if( m_usedTail == p )
johnb 2:16c77b601175 556 {
johnb 2:16c77b601175 557 m_usedTail = last;
johnb 2:16c77b601175 558 }
johnb 2:16c77b601175 559
johnb 2:16c77b601175 560 /* Move item to free list */
johnb 2:16c77b601175 561 p->m_forward = m_freeHead;
johnb 2:16c77b601175 562 m_freeHead = p;
johnb 2:16c77b601175 563
johnb 2:16c77b601175 564 m_usedCount--;
johnb 2:16c77b601175 565
johnb 2:16c77b601175 566 ret_val = true;
johnb 2:16c77b601175 567 break;
johnb 2:16c77b601175 568 }
johnb 2:16c77b601175 569 else
johnb 2:16c77b601175 570 {
johnb 2:16c77b601175 571 last = p;
johnb 2:16c77b601175 572 p = p->m_forward;
johnb 2:16c77b601175 573 }
johnb 2:16c77b601175 574 }
johnb 2:16c77b601175 575
johnb 2:16c77b601175 576 return ret_val;
johnb 2:16c77b601175 577 }
johnb 0:99d701354221 578
johnb 0:99d701354221 579 template < class T, size_t queueMax >
johnb 0:99d701354221 580 size_t FixedLengthList< T, queueMax >::used() const
johnb 0:99d701354221 581 {
johnb 0:99d701354221 582 return m_usedCount;
johnb 0:99d701354221 583 }
johnb 0:99d701354221 584
johnb 0:99d701354221 585 template < class T, size_t queueMax >
johnb 0:99d701354221 586 size_t FixedLengthList< T, queueMax >::available() const
johnb 0:99d701354221 587 {
johnb 0:99d701354221 588 return queueMax - m_usedCount;
johnb 0:99d701354221 589 }
johnb 0:99d701354221 590
johnb 0:99d701354221 591 template < class T, size_t queueMax >
johnb 0:99d701354221 592 bool FixedLengthList< T, queueMax >::inList( const T p_val ) const
johnb 0:99d701354221 593 {
johnb 0:99d701354221 594 bool ret_val = false;
johnb 0:99d701354221 595 FixedLengthListItem<T>* p = m_usedHead;
johnb 0:99d701354221 596
johnb 0:99d701354221 597 /* Ordered iteration of the list checking for specified item */
johnb 0:99d701354221 598 while( p != NULL )
johnb 0:99d701354221 599 {
johnb 0:99d701354221 600 if( p->m_item == p_val ) {
johnb 0:99d701354221 601 /* Item found - flag and break out */
johnb 0:99d701354221 602 ret_val = true;
johnb 0:99d701354221 603 break;
johnb 0:99d701354221 604 } else {
johnb 0:99d701354221 605 p = p->m_forward;
johnb 0:99d701354221 606 }
johnb 0:99d701354221 607 }
johnb 0:99d701354221 608
johnb 0:99d701354221 609 return ret_val;
johnb 0:99d701354221 610 }
johnb 0:99d701354221 611
johnb 1:d98987d1d67c 612 template < class T, size_t queueMax >
johnb 1:d98987d1d67c 613 FixedLengthListIter<T, queueMax> FixedLengthList< T,queueMax >::begin( void )
johnb 1:d98987d1d67c 614 {
johnb 1:d98987d1d67c 615 return iterator( m_usedHead );
johnb 1:d98987d1d67c 616 }
johnb 1:d98987d1d67c 617
johnb 1:d98987d1d67c 618 template < class T, size_t queueMax >
johnb 1:d98987d1d67c 619 FixedLengthListIter<T, queueMax> FixedLengthList< T,queueMax >::end( void )
johnb 1:d98987d1d67c 620 {
johnb 1:d98987d1d67c 621 return iterator( NULL );
johnb 1:d98987d1d67c 622 }
johnb 1:d98987d1d67c 623
johnb 1:d98987d1d67c 624 template < class T, size_t queueMax >
johnb 1:d98987d1d67c 625 FixedLengthListIter< T, queueMax >::FixedLengthListIter( void ) : m_item( NULL)
johnb 1:d98987d1d67c 626 {
johnb 1:d98987d1d67c 627 }
johnb 1:d98987d1d67c 628
johnb 1:d98987d1d67c 629 template < class T, size_t queueMax >
johnb 1:d98987d1d67c 630 FixedLengthListIter< T, queueMax >::FixedLengthListIter( FixedLengthListItem<T>* p_item ) : m_item( p_item )
johnb 1:d98987d1d67c 631 {
johnb 1:d98987d1d67c 632 }
johnb 1:d98987d1d67c 633
johnb 1:d98987d1d67c 634 template < class T, size_t queueMax >
johnb 1:d98987d1d67c 635 T& FixedLengthListIter< T, queueMax >::operator*()
johnb 1:d98987d1d67c 636 {
johnb 1:d98987d1d67c 637 return m_item->m_item;
johnb 1:d98987d1d67c 638 }
johnb 1:d98987d1d67c 639
johnb 1:d98987d1d67c 640 template < class T, size_t queueMax >
johnb 1:d98987d1d67c 641 FixedLengthListIter< T,queueMax > FixedLengthListIter< T,queueMax >::operator++( int p_int )
johnb 1:d98987d1d67c 642 {
johnb 1:d98987d1d67c 643 FixedLengthListIter< T,queueMax > clone( *this );
johnb 1:d98987d1d67c 644 m_item = m_item->m_forward;
johnb 1:d98987d1d67c 645 return clone;
johnb 1:d98987d1d67c 646 }
johnb 1:d98987d1d67c 647
johnb 1:d98987d1d67c 648 template < class T, size_t queueMax >
johnb 1:d98987d1d67c 649 FixedLengthListIter< T,queueMax >& FixedLengthListIter< T,queueMax >::operator++( void )
johnb 1:d98987d1d67c 650 {
johnb 1:d98987d1d67c 651 m_item = m_item->m_forward;
johnb 1:d98987d1d67c 652 return *this;
johnb 1:d98987d1d67c 653 }
johnb 1:d98987d1d67c 654
johnb 1:d98987d1d67c 655 template < class T, size_t queueMax >
johnb 1:d98987d1d67c 656 FixedLengthListIter< T,queueMax >& FixedLengthListIter< T,queueMax >::operator+=( const unsigned p_inc ) {
johnb 1:d98987d1d67c 657 for(unsigned i = 0;
johnb 1:d98987d1d67c 658 i < p_inc;
johnb 1:d98987d1d67c 659 i++ )
johnb 1:d98987d1d67c 660 {
johnb 1:d98987d1d67c 661 if( m_item == NULL ) {
johnb 1:d98987d1d67c 662 break;
johnb 1:d98987d1d67c 663 } else {
johnb 1:d98987d1d67c 664 m_item = m_item->m_forward;
johnb 1:d98987d1d67c 665 }
johnb 1:d98987d1d67c 666 }
johnb 1:d98987d1d67c 667 return *this;
johnb 1:d98987d1d67c 668 }
johnb 1:d98987d1d67c 669
johnb 1:d98987d1d67c 670 template < class T, size_t queueMax >
johnb 1:d98987d1d67c 671 bool FixedLengthListIter< T,queueMax >::operator==( const FixedLengthListIter& p_comp ) const
johnb 1:d98987d1d67c 672 {
johnb 1:d98987d1d67c 673 return m_item == p_comp.m_item;
johnb 1:d98987d1d67c 674 }
johnb 1:d98987d1d67c 675
johnb 1:d98987d1d67c 676 template < class T, size_t queueMax >
johnb 1:d98987d1d67c 677 bool FixedLengthListIter< T,queueMax >::operator!=( const FixedLengthListIter& p_comp ) const
johnb 1:d98987d1d67c 678 {
johnb 1:d98987d1d67c 679 return m_item != p_comp.m_item;
johnb 1:d98987d1d67c 680 }
johnb 1:d98987d1d67c 681
johnb 1:d98987d1d67c 682
johnb 2:16c77b601175 683 #endif