GM6000 Digital Heater Controller Branch: main
SDX-1330
DList.h
Go to the documentation of this file.
1#ifndef Cpl_Container_DList_h_
2#define Cpl_Container_DList_h_
3/*-----------------------------------------------------------------------------
4* This file is part of the Colony.Core Project. The Colony.Core Project is an
5* open source project with a BSD type of licensing agreement. See the license
6* agreement (license.txt) in the top/ directory or on the Internet at
7* http://integerfox.com/colony.core/license.txt
8*
9* Copyright (c) 2014-2022 John T. Taylor
10*
11* Redistributions of the source code must retain the above copyright notice.
12*----------------------------------------------------------------------------*/
13/** @file */
14
15
16///
17namespace Cpl {
18///
19namespace Container {
20
21
22/** This template class implements a Doubly linked list
23 which maintains the ordering imposed on it by the application.
24
25 NOTE: ITEM must be a subclass of ExtendedItem.
26 */
27template <class ITEM>
28class DList
29{
30private:
31 /** Points to the first item in the list.
32 */
33 ITEM * m_headPtr;
34
35 /** Points to the last item in the list.
36 */
37 ITEM* m_tailPtr;
38
39public:
40 /** Public constructor initializes head and tail pointers.
41 */
42 DList() noexcept;
43
44 /** This is a special constructor for when the list is
45 statically declared (i.e. it is initialized as part of
46 C++ startup BEFORE main() is executed. C/C++ guarantees
47 that all statically declared data will be initialized
48 to zero by default (see r.8.4 in C++ Programming Language,
49 Second Edition). Since the head & tail pointers are
50 initialized to zero - then the C/C++ default is OK. Why
51 do I care about all this? Because if you attempt to build
52 static list(s), then the order of when the list is
53 constructed vs. when the static elements are added to the
54 list is a problem! To avoid this problem, a alternate
55 constructor that does NOT initialize the head & tail pointers
56 is provided. It assumes that the pointers are already set
57 zero because the list is "static". Whew!
58 */
59 DList( const char* ignoreThisParameter_usedToCreateAUniqueConstructor ) noexcept;
60
61
62public: ///@name Operations on the List itself
63 ///@{
64 /** Moves the content of the this List to the specified List.
65 */
66 void move( DList<ITEM>& dst );
67
68 /** Empties the list. All references to the item(s) in the
69 list are lost.
70 */
72 ///@}
73
74public: ///@name View as a FIFO
75 ///@{
76 /** Removes the first item in the list. Returns 0 if the list
77 is empty.
78 */
79 ITEM* get( void ) noexcept;
80
81 /** Adds the item as the last item in the list
82 */
83 void put( ITEM& item ) noexcept;
84
85 /** Return a pointer to the first item in the list.
86 The returned item remains in the list. Returns 0
87 if the list is empty.
88 */
89 ITEM* head( void ) const noexcept;
90
91 /** Return a pointer to the last item in the list.
92 The returned item remains in the list. Returns 0
93 if the list is empty.
94 */
95 ITEM* tail( void ) const noexcept;
96 ///@}
97
98
99public: ///@name View as a STACK
100 ///@{
101 /** Removes the top element from stack and return a pointer to
102 it as a result. Returns 0, if the stack is empty
103 */
104 ITEM* pop( void ) noexcept;
105
106 /** Adds the ITEM item to top of the stack.
107 */
108 void push( ITEM& item ) noexcept;
109
110 /** Return a pointer to the top ITEM item in the stack.
111 The returned item remains in the queue. Returns 0
112 if the stack is empty.
113 */
114 ITEM* top( void ) const noexcept;
115 ///@}
116
117public: ///@name View as Ordered List
118 ///@{
119 /** Removes the first item in the list. Returns 0 if the list
120 is empty.
121 */
122 ITEM* getFirst( void ) noexcept;
123
124 /** Removes the last item in the list. Returns 0 if the list
125 is empty.
126 */
127 ITEM* getLast( void ) noexcept;
128
129 /** Adds the item as the first item in the list.
130 */
131 void putFirst( ITEM& item ) noexcept;
132
133 /** Adds the item as the last item in the list.
134 */
135 void putLast( ITEM& item ) noexcept;
136
137 /** Remove specified ITEM element from the list.
138 Returns true, if the specified element was found and
139 removed from the list, else false.
140 */
141 bool remove( ITEM& item ) noexcept;
142
143 /** Insert the "item" ITEM into the list behind the
144 "after" ITEM element. If 'after' is 0, then 'item'
145 is added to the head of the list.
146 */
147 void insertAfter( ITEM& after, ITEM& item ) noexcept;
148
149 /** Insert the "item" ITEM into the list ahead of the
150 "before" ITEM element. If 'before' is 0, then 'item'
151 is added to the tail of the list.
152 */
153 void insertBefore( ITEM& before, ITEM& item ) noexcept;
154
155 /** Returns true of the specified item/pointer is
156 already in the list, else false.
157 */
158 bool find( const ITEM& item ) const noexcept;
159
160 /** Return a pointer to the first item in the list.
161 The returned item remains in the list. Returns 0
162 if the list is empty.
163 */
164 ITEM* first( void ) const noexcept;
165
166 /** Return a pointer to the last item in the list.
167 The returned item remains in the list. Returns 0
168 if the list is empty.
169 */
170 ITEM* last( void ) const noexcept;
171
172 /** Return a pointer to the item after the item "current".
173 Both items remain in the list. Returns 0 when the
174 end-of-list is reached.
175 */
176 ITEM* next( ITEM& current ) const noexcept;
177
178 /** Return a pointer to the item before the item "current".
179 Both items remain in the list. Returns 0 when the
180 end-of-list is reached.
181 */
182 ITEM* previous( ITEM& current ) const noexcept;
183 ///@}
184
185
186private: ///@name Prevent the container from being copied
187 ///@{
188 /// Prevent access to the copy constructor -->Containers can not be copied!
189 DList( const DList& m );
190
191 /// Prevent access to the assignment operator -->Containers can not be copied!
192 const DList& operator=( const DList& m );
193 ///@}
194};
195
196/////////////////////////////////////////////////////////////////////////////
197// INLINE IMPLEMENTAION
198/////////////////////////////////////////////////////////////////////////////
199
200
201template <class ITEM>
202DList<ITEM>::DList( void ) noexcept
203 :m_headPtr( 0 ), m_tailPtr( 0 )
204{
205}
206
207template <class ITEM>
208DList<ITEM>::DList( const char* ) noexcept
209{
210}
211
212
213template <class ITEM>
215{
216 // clear the destination list
217 dst.clearTheList();
218
219 // Copy each item (so the debug info is correct)
220 ITEM* nextPtr;
221 while ( (nextPtr=get()) )
222 {
223 dst.put( *nextPtr );
224 }
225}
226
227template <class ITEM>
229{
230 // Drain list so the debug traps work correctly
231 while ( get() )
232 ;
233}
234
235template <class ITEM>
236inline ITEM* DList<ITEM>::get( void ) noexcept
237{
238 ITEM* firstPtr = m_headPtr;
239 if ( firstPtr )
240 {
241 remove( *firstPtr );
242 }
243 return firstPtr;
244}
245
246template <class ITEM>
247inline ITEM* DList<ITEM>::getFirst( void ) noexcept
248{
249 return get();
250}
251
252template <class ITEM>
253inline ITEM* DList<ITEM>::getLast( void ) noexcept
254{
255 ITEM* lastPtr = m_tailPtr;
256 if ( lastPtr )
257 {
258 remove( *m_tailPtr );
259 }
260 return lastPtr;
261}
262
263template <class ITEM>
264inline void DList<ITEM>::putFirst( ITEM& item ) noexcept
265{
266 if ( item.insert_( this ) )
267 {
268 if ( m_headPtr )
269 {
270 item.m_nextPtr_ = m_headPtr;
271 m_headPtr->m_prevPtr_ = &item;
272 m_headPtr = &item;
273 }
274 else
275 {
276 m_headPtr = m_tailPtr = &item;
277 item.m_nextPtr_ = 0;
278 }
279 item.m_prevPtr_ = 0;
280 }
281}
282
283template <class ITEM>
284inline void DList<ITEM>::put( ITEM& item ) noexcept
285{
286 if ( item.insert_( this ) )
287 {
288 if ( m_headPtr )
289 {
290 m_tailPtr->m_nextPtr_ = &item;
291 item.m_prevPtr_ = m_tailPtr;
292 }
293 else
294 {
295 m_headPtr = &item;
296 item.m_prevPtr_ = 0;
297 }
298 item.m_nextPtr_ = 0;
299 m_tailPtr = &item;
300 }
301}
302
303template <class ITEM>
304inline void DList<ITEM>::putLast( ITEM& item ) noexcept
305{
306 put( item );
307}
308
309template <class ITEM>
310inline bool DList<ITEM>::remove( ITEM& item ) noexcept
311{
312 if ( item.isInContainer_( this ) )
313 {
314 ITEM* prvPtr = (ITEM*) item.m_prevPtr_;
315 ITEM* nxtPtr = (ITEM*) item.m_nextPtr_;
316 if ( prvPtr )
317 {
318 if ( !(prvPtr->m_nextPtr_=nxtPtr) )
319 {
320 m_tailPtr = prvPtr; // Case: Remove tail object
321 }
322 else
323 {
324 nxtPtr->m_prevPtr_ = prvPtr; // Case: Remove intermediate object
325 }
326 }
327 else
328 {
329 if ( !(m_headPtr=nxtPtr) )
330 {
331 m_tailPtr = 0; // Case: Remove last object
332 }
333 else
334 {
335 nxtPtr->m_prevPtr_ = 0; // Case: Remove Head object
336 }
337 }
338
339 Item::remove_( &item );
340 return true;
341 }
342
343 return false;
344}
345
346
347template <class ITEM>
348inline void DList<ITEM>::insertAfter( ITEM& after, ITEM& item ) noexcept
349{
350 if ( item.insert_( this ) )
351 {
352 ITEM* nxtPtr = (ITEM*) (item.m_nextPtr_ = after.m_nextPtr_);
353 item.m_prevPtr_ = &after;
354 after.m_nextPtr_ = &item;
355 if ( !nxtPtr )
356 {
357 m_tailPtr = &item;
358 }
359 else
360 {
361 nxtPtr->m_prevPtr_ = &item;
362 }
363 }
364}
365
366template <class ITEM>
367inline void DList<ITEM>::insertBefore( ITEM& before, ITEM& item ) noexcept
368{
369 if ( item.insert_( this ) )
370 {
371 ITEM* prvPtr = (ITEM*) (item.m_prevPtr_ = before.m_prevPtr_);
372 item.m_nextPtr_ = &before;
373 before.m_prevPtr_ = &item;
374 if ( !prvPtr )
375 {
376 m_headPtr = &item;
377 }
378 else
379 {
380 prvPtr->m_nextPtr_ = &item;
381 }
382 }
383}
384
385template <class ITEM>
386inline bool DList<ITEM>::find( const ITEM& item ) const noexcept
387{
388 return item.isInContainer_( this );
389}
390
391template <class ITEM>
392inline ITEM* DList<ITEM>::first( void ) const noexcept
393{
394 return m_headPtr;
395}
396
397template <class ITEM>
398inline ITEM* DList<ITEM>::last( void ) const noexcept
399{
400 return m_tailPtr;
401}
402
403template <class ITEM>
404inline ITEM* DList<ITEM>::next( ITEM& cur ) const noexcept
405{
406 return (ITEM*) cur.m_nextPtr_;
407}
408
409template <class ITEM>
410inline ITEM* DList<ITEM>::previous( ITEM& cur ) const noexcept
411{
412 return (ITEM*) cur.m_prevPtr_;
413}
414
415template <class ITEM>
416inline void DList<ITEM>::push( ITEM& item ) noexcept
417{
418 putFirst( item );
419}
420
421template <class ITEM>
422inline ITEM* DList<ITEM>::pop( void ) noexcept
423{
424 return get();
425}
426
427template <class ITEM>
428inline ITEM* DList<ITEM>::top( void ) const noexcept
429{
430 return first();
431}
432
433template <class ITEM>
434inline ITEM* DList<ITEM>::head( void ) const noexcept
435{
436 return first();
437}
438
439template <class ITEM>
440inline ITEM* DList<ITEM>::tail( void ) const noexcept
441{
442 return last();
443}
444
445
446}; // end namespaces
447};
448#endif // end header latch
This template class implements a Doubly linked list which maintains the ordering imposed on it by the...
Definition DList.h:29
ITEM * head(void) const noexcept
Return a pointer to the first item in the list.
Definition DList.h:434
bool remove(ITEM &item) noexcept
Remove specified ITEM element from the list.
Definition DList.h:310
ITEM * first(void) const noexcept
Return a pointer to the first item in the list.
Definition DList.h:392
void insertAfter(ITEM &after, ITEM &item) noexcept
Insert the "item" ITEM into the list behind the "after" ITEM element.
Definition DList.h:348
ITEM * previous(ITEM &current) const noexcept
Return a pointer to the item before the item "current".
Definition DList.h:410
ITEM * get(void) noexcept
Removes the first item in the list.
Definition DList.h:236
void move(DList< ITEM > &dst)
Moves the content of the this List to the specified List.
Definition DList.h:214
ITEM * getFirst(void) noexcept
Removes the first item in the list.
Definition DList.h:247
ITEM * last(void) const noexcept
Return a pointer to the last item in the list.
Definition DList.h:398
void insertBefore(ITEM &before, ITEM &item) noexcept
Insert the "item" ITEM into the list ahead of the "before" ITEM element.
Definition DList.h:367
void putFirst(ITEM &item) noexcept
Adds the item as the first item in the list.
Definition DList.h:264
ITEM * top(void) const noexcept
Return a pointer to the top ITEM item in the stack.
Definition DList.h:428
void clearTheList()
Empties the list.
Definition DList.h:228
DList() noexcept
Public constructor initializes head and tail pointers.
Definition DList.h:202
void put(ITEM &item) noexcept
Adds the item as the last item in the list.
Definition DList.h:284
void putLast(ITEM &item) noexcept
Adds the item as the last item in the list.
Definition DList.h:304
ITEM * getLast(void) noexcept
Removes the last item in the list.
Definition DList.h:253
bool find(const ITEM &item) const noexcept
Returns true of the specified item/pointer is already in the list, else false.
Definition DList.h:386
ITEM * pop(void) noexcept
Removes the top element from stack and return a pointer to it as a result.
Definition DList.h:422
ITEM * next(ITEM &current) const noexcept
Return a pointer to the item after the item "current".
Definition DList.h:404
void push(ITEM &item) noexcept
Adds the ITEM item to top of the stack.
Definition DList.h:416
ITEM * tail(void) const noexcept
Return a pointer to the last item in the list.
Definition DList.h:440
static void remove_(Item *itemPtr) noexcept
Helper method to do the proper 'clean-up' for the multiple-containers-error-trap when removing an ite...
The 'Cpl' namespace is the root name space for the Colony.
Definition Api16.h:20