uLib  User mode C/C++ extended API library for Win32 programmers.
ListFunc.h
Go to the documentation of this file.
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 // Project: uLib - User mode utility library.
3 // Module: Enhanced double-linked and single-linked list classes.
4 // Author: Copyright (c) Love Nystrom
5 // License: NNOSL (BSD descendant, see NNOSL.txt in the base directory).
6 // Credits:
7 // Someone on Microsoft's kernel team for the original ntddk macros.
8 // Unknown@GeeksForGeeks.org Original ideas for QuickSort.
9 // KeremSahin@ideone.com Original ideas for QuickSort.
10 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 
12 // DLinkList -- Double linked list manipulation class.
13 // Initially based on the list macros in ntddk.h, and thoroughly enhanced.
14 // 2018: ListForEach and GetListEntryCount APIs have been added, to facilitate
15 // solid enumeration for standard listhead lists, and easily count their entries.
16 
17 #ifndef _ListFunc_h_incl_
18 #define _ListFunc_h_incl_
19 
20 //==---------------------------------------------------------------------------
34 //==---------------------------------------------------------------------------
36 
37 #ifndef _NTDEF_ // NtDef.h declares LIST_ENTRY in kernel mode.
38 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) // 3 id's I've seen
39 #include <Windows.h>
40 #else // Non-Windows compilation
41 // DList
42 typedef struct _LIST_ENTRY
43 {
44  struct _LIST_ENTRY *Flink;
45  struct _LIST_ENTRY *Blink;
46 }
47 *PLIST_ENTRY, LIST_ENTRY; // NB: Backward order due to doxygen.
48 // SList
49 typedef struct _SINGLE_LIST_ENTRY
50 {
51  struct _SINGLE_LIST_ENTRY *Next;
52 }
54 #endif
55 #endif//ndef _NTDEF_
56 
57 #ifdef __cplusplus
58 extern "C" {
59 #elif !defined( __bool_defined )
60 //typedef enum { false,true } bool; // int-size!
61 typedef unsigned char bool; // single byte, compliant.
62 #define true (1==1) // note: constant folding applies.
63 #define false (1==0) // -"-
64 #define __bool_defined
65 #endif
66 
68 #ifndef INOUT // Supplements to classic annotations
69  #define INOUT
70  #define OPTIN
71  #define OPTOUT
72  #define OPTIO
73 #endif
74 #ifdef ListFunc_Internal
75 // Currently unused.
76 #endif
77 
79 //-----------------------------------------------------------------------------
80 // C API's - Function equivalents of the DDK macros.
81 // Note: Leading underscore disambiguates from the macro and inline versions.
82 //-----------------------------------------------------------------------------
83 
87 
88 #define InitializeListEntry(E) (E)->Flink = (E)->Blink = (E)
89 #define _InitializeListEntry(E) _InitializeListHead( (PLIST_ENTRY)(E) )
90 
94 
95 #define UnlinkListEntry(E) InitializeListEntry( E )
96 
97 // Double-linked list
98 
99 void _InitializeListHead( PLIST_ENTRY ListHead );
100 bool _IsListEmpty( PLIST_ENTRY ListHead );
101 void _InsertTailList( PLIST_ENTRY ListHead, PLIST_ENTRY Entry );
102 void _InsertHeadList( PLIST_ENTRY ListHead, PLIST_ENTRY Entry );
103 void _RemoveEntryList( PLIST_ENTRY Entry );
106 
107 // Supplementary APIs for standard lists.
108 
109 UINT GetListEntryCount( PLIST_ENTRY ListHead );
110 
117 
118 bool ListForEach(
119  PLIST_ENTRY ListHead,
120  bool (__stdcall *Action)( PLIST_ENTRY Entry, void* UserData ),
121  void* UserData
122  );
123 
127 
128 void AttachHeadlessList( OUT PLIST_ENTRY Head, IN PLIST_ENTRY Circular );
129 
130 // Single-linked list
131 
132 void _InitializeEntryList( PSINGLE_LIST_ENTRY EntryOrHead );
133 void _PushEntryList( PSINGLE_LIST_ENTRY ListHead, PSINGLE_LIST_ENTRY Entry );
135 
136 #ifdef __cplusplus
137 } // end extern "C"
138 
139 //-----------------------------------------------------------------------------
140 // C++ double-linked list class
141 //-----------------------------------------------------------------------------
142 
143 typedef class DLinkList* PDLinkList;
144 
151 
152 typedef bool (__stdcall *PDListFunc)( PLIST_ENTRY Entry, void* UserData );
153 
158 
159 typedef int (__stdcall *PDListComp)( PLIST_ENTRY X, PLIST_ENTRY Y, void* UserData );
160 
161 //+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
178 //+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
179 
180 // NOTA BENE: Contributors, do NOT add virtual members to DLinkList !!
181 // The introduction of a vtable would offset (&Flink) by sizeof(void*),
182 // which would break the equality (this) == (&Flink).
183 
184 class DLinkList : protected LIST_ENTRY {
185 public:
186  UINT Count;
187  bool SafeRemove;
188 
200  DLinkList( bool Safe = true );
201 
206 
207  DLinkList( PLIST_ENTRY ListHead, bool Safe );
208 
211 
212  ~DLinkList(); // N.B: Can't be virtual, since that would make (this) != (&Flink) !
213 
219 
220  PDLinkList operator = ( PLIST_ENTRY ListHead );
221 
222  PLIST_ENTRY operator += ( PLIST_ENTRY Entry ) { return Append( Entry ); }
223  PLIST_ENTRY operator -= ( PLIST_ENTRY Entry ) { return RemoveEntry( Entry ); }
224 
225  bool IsEmpty() { return Flink == this; }
226  bool Exist( PLIST_ENTRY Entry );
227 
228  PLIST_ENTRY GetFirst() { return Flink; } // At head
229  PLIST_ENTRY GetLast() { return Blink; } // At tail
230 
235 
236  PLIST_ENTRY GetNext( PLIST_ENTRY Current );
237  PLIST_ENTRY GetPrev( PLIST_ENTRY Current );
238 
239  // Add entries
240 
241  PLIST_ENTRY Append( PLIST_ENTRY Entry );
242  PLIST_ENTRY Prepend( PLIST_ENTRY Entry );
243 
244  // Remove entries
245 
249 
255 
256  void RemoveAll( PDListFunc ItemAction, void* UserData = NULL );
257 
258  PLIST_ENTRY Push( PLIST_ENTRY Entry ) { return Prepend( Entry ); }
259  PLIST_ENTRY Pull() { return RemoveLast(); }
260  PLIST_ENTRY Pop() { return RemoveFirst(); }
261 
262  PLIST_ENTRY operator [] ( size_t Index );
263 
275 
276  bool ForEach( PDListFunc Action, void* UserData = NULL );
277 
280 
281  PLIST_ENTRY FirstThat( PDListFunc Match, void* UserData = NULL );
282 
285 
286  PLIST_ENTRY LastThat( PDListFunc Match, void* UserData = NULL );
287 
293 
294  void QuickSort( PDListComp Compare, void* UserData = NULL );
295 
296 public: // IMPORT / EXPORT
297 
306 
307  UINT AppendList( IN PLIST_ENTRY ListToAppend, OPTOUT PLIST_ENTRY* ppFirst );
308  UINT AppendList( IN PDLinkList ListToAppend, OPTOUT PLIST_ENTRY* ppFirst );
309  UINT operator += ( PDLinkList ListToAppend ) { return AppendList( ListToAppend, NULL ); }
310 
317 
318  UINT ExportToListHead( PLIST_ENTRY ListHead );
319 
324 
325  UINT ImportFromListHead( IN PLIST_ENTRY ListHead, OPTOUT PLIST_ENTRY* ppFirst );
326 
331 
332  UINT ExportToHeadlessList( PLIST_ENTRY* Circular ); // Preliminary
333 
348 
349  UINT ImportHeadlessList( IN PLIST_ENTRY Circular, OPTOUT PLIST_ENTRY* ppFirst ); // Preliminary
350 
351 protected:
353  void _grabList( PLIST_ENTRY ListHead );
354  void _qsortPartition(
355  PLIST_ENTRY *ppHead, PLIST_ENTRY *ppTail, PDListComp Compare, void* UserData
356  );
357  void _qsortRecursion(
358  PLIST_ENTRY *ppHead, PLIST_ENTRY *ppTail, PDListComp Compare, void* UserData
359  );
361 };
362 
363 //-----------------------------------------------------------------------------
364 // SLinkList -- Single linked list.
365 //-----------------------------------------------------------------------------
366 
367 typedef class SLinkList* PSLinkList;
368 typedef bool (__stdcall *PSListFunc)( PSINGLE_LIST_ENTRY Entry, void* UserData );
370 
378 
379 class SLinkList : protected SINGLE_LIST_ENTRY {
380 public:
381  UINT Count;
382 
384 
385  bool __forceinline IsEmpty();
387 
390 
393 
400 
401  PSINGLE_LIST_ENTRY Append( PSINGLE_LIST_ENTRY Entry ); // Return Entry
402 
405 
407 
408  // Some nifty operators are nice to have
409 
412 
413  PSINGLE_LIST_ENTRY operator [] ( size_t Index );
414 
418 
419  void RemoveAll( PSListFunc ItemAction, void* UserData = NULL );
420 
426 
427  PSINGLE_LIST_ENTRY FirstThat( PSListFunc Match, void* UserData = NULL );
428  bool ForEach( PSListFunc Action, void* UserData = NULL );
429 };
430 
431 #endif //__cplusplus
432 //-----------------------------------------------------------------------------
434 #endif //ndef _ListFunc_h_incl_
435 // EOF
PLIST_ENTRY FirstThat(PDListFunc Match, void *UserData=NULL)
Definition: ListCls.cpp:287
UINT ExportToListHead(PLIST_ENTRY ListHead)
Definition: ListCls.cpp:431
UINT Count
Definition: ListFunc.h:186
void AttachHeadlessList(OUT PLIST_ENTRY Head, IN PLIST_ENTRY Circular)
Definition: ListFunc.c:108
bool(__stdcall * PSListFunc)(PSINGLE_LIST_ENTRY Entry, void *UserData)
Definition: ListFunc.h:369
UINT ImportFromListHead(IN PLIST_ENTRY ListHead, OPTOUT PLIST_ENTRY *ppFirst)
Definition: ListCls.cpp:446
PLIST_ENTRY LastThat(PDListFunc Match, void *UserData=NULL)
Definition: ListCls.cpp:302
PLIST_ENTRY operator [](size_t Index)
Definition: ListCls.cpp:277
void _InitializeEntryList(PSINGLE_LIST_ENTRY EntryOrHead)
Definition: ListFunc.c:143
UINT ImportHeadlessList(IN PLIST_ENTRY Circular, OPTOUT PLIST_ENTRY *ppFirst)
Definition: ListCls.cpp:472
PLIST_ENTRY operator+=(PLIST_ENTRY Entry)
Definition: ListFunc.h:222
bool Exist(PLIST_ENTRY Entry)
Definition: ListCls.cpp:145
bool ForEach(PDListFunc Action, void *UserData=NULL)
Definition: ListCls.cpp:317
PLIST_ENTRY GetLast()
Definition: ListFunc.h:229
#define OPTOUT
Definition: Common.h:264
UINT AppendList(IN PLIST_ENTRY ListToAppend, OPTOUT PLIST_ENTRY *ppFirst)
Definition: ListCls.cpp:116
void _InsertHeadList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry)
Definition: ListFunc.c:71
PLIST_ENTRY RemoveLast()
Definition: ListCls.cpp:236
PSINGLE_LIST_ENTRY operator -=(PSINGLE_LIST_ENTRY Entry)
Definition: ListFunc.h:411
struct _LIST_ENTRY * PLIST_ENTRY
bool(__stdcall * PDListFunc)(PLIST_ENTRY Entry, void *UserData)
Definition: ListFunc.h:152
DLinkList(bool Safe=true)
Definition: ListCls.cpp:70
PLIST_ENTRY Pull()
Definition: ListFunc.h:259
PLIST_ENTRY GetNext(PLIST_ENTRY Current)
Definition: ListCls.cpp:191
void _PushEntryList(PSINGLE_LIST_ENTRY ListHead, PSINGLE_LIST_ENTRY Entry)
Definition: ListFunc.c:151
PDLinkList operator=(PLIST_ENTRY ListHead)
Definition: ListCls.cpp:407
bool ForEach(PSListFunc Action, void *UserData=NULL)
Definition: ListCls.cpp:626
PLIST_ENTRY Prepend(PLIST_ENTRY Entry)
Definition: ListCls.cpp:103
void RemoveAll(PSListFunc ItemAction, void *UserData=NULL)
Definition: ListCls.cpp:603
PLIST_ENTRY Append(PLIST_ENTRY Entry)
Definition: ListCls.cpp:90
int(__stdcall * PDListComp)(PLIST_ENTRY X, PLIST_ENTRY Y, void *UserData)
Definition: ListFunc.h:159
PLIST_ENTRY _RemoveTailList(PLIST_ENTRY ListHead)
Definition: ListFunc.c:27
void _InitializeListHead(PLIST_ENTRY ListHead)
Definition: ListFunc.c:17
class SLinkList * PSLinkList
Definition: ListFunc.h:367
void _RemoveEntryList(PLIST_ENTRY Entry)
Definition: ListFunc.c:47
void QuickSort(PDListComp Compare, void *UserData=NULL)
Definition: ListCls.cpp:335
PLIST_ENTRY _RemoveHeadList(PLIST_ENTRY ListHead)
Definition: ListFunc.c:37
struct _LIST_ENTRY * Blink
Definition: ListFunc.h:45
bool ListForEach(PLIST_ENTRY ListHead, bool(__stdcall *Action)(PLIST_ENTRY Entry, void *UserData), void *UserData)
Definition: ListFunc.c:92
PSINGLE_LIST_ENTRY FirstThat(PSListFunc Match, void *UserData=NULL)
Definition: ListCls.cpp:611
bool IsEmpty()
Definition: ListFunc.h:225
bool __forceinline IsEmpty()
Definition: ListCls.cpp:508
struct _SINGLE_LIST_ENTRY * PSINGLE_LIST_ENTRY
PSINGLE_LIST_ENTRY Remove(PSINGLE_LIST_ENTRY Entry)
Definition: ListCls.cpp:577
void RemoveAll(PDListFunc ItemAction, void *UserData=NULL)
Definition: ListCls.cpp:241
UINT GetListEntryCount(PLIST_ENTRY ListHead)
Definition: ListFunc.c:82
class DLinkList * PDLinkList
Definition: ListFunc.h:143
PSINGLE_LIST_ENTRY operator+=(PSINGLE_LIST_ENTRY Entry)
Definition: ListFunc.h:410
bool _IsListEmpty(PLIST_ENTRY ListHead)
Definition: ListFunc.c:22
PLIST_ENTRY Pop()
Definition: ListFunc.h:260
void _InsertTailList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry)
Definition: ListFunc.c:62
PSINGLE_LIST_ENTRY GetFirst()
Definition: ListFunc.h:386
PSINGLE_LIST_ENTRY PopEntry()
Definition: ListCls.cpp:535
~DLinkList()
Definition: ListCls.cpp:83
PSINGLE_LIST_ENTRY _PopEntryList(PSINGLE_LIST_ENTRY ListHead)
Definition: ListFunc.c:156
PLIST_ENTRY operator -=(PLIST_ENTRY Entry)
Definition: ListFunc.h:223
PSINGLE_LIST_ENTRY operator [](size_t Index)
Definition: ListCls.cpp:595
UINT ExportToHeadlessList(PLIST_ENTRY *Circular)
Definition: ListCls.cpp:462
bool SafeRemove
Definition: ListFunc.h:187
PLIST_ENTRY RemoveFirst()
Definition: ListCls.cpp:231
PSINGLE_LIST_ENTRY Append(PSINGLE_LIST_ENTRY Entry)
Definition: ListCls.cpp:556
PLIST_ENTRY GetFirst()
Definition: ListFunc.h:228
struct _SINGLE_LIST_ENTRY * Next
Definition: ListFunc.h:51
UINT Count
Definition: ListFunc.h:381
SLinkList()
Definition: ListFunc.h:383
struct _LIST_ENTRY * Flink
Definition: ListFunc.h:44
PLIST_ENTRY RemoveEntry(PLIST_ENTRY Entry)
Definition: ListCls.cpp:213
PLIST_ENTRY Push(PLIST_ENTRY Entry)
Definition: ListFunc.h:258
PSINGLE_LIST_ENTRY PushEntry(PSINGLE_LIST_ENTRY Entry)
Definition: ListCls.cpp:520
PLIST_ENTRY GetPrev(PLIST_ENTRY Current)
Definition: ListCls.cpp:202