uLib  User mode C/C++ extended API library for Win32 programmers.
ListFunc.c
Go to the documentation of this file.
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 // Project: uLib - User mode library.
3 // Module: Linked list C function equivalents of DDK macros.
4 // Author: Copyright (c) Love Nystrom
5 // License: NNOSL (BSD descendant, see NNOSL.txt in the base directory).
6 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 
8 // Based on the list macros in ntddk.h; Slightly optimized.
9 // Id's have a disambiguating leading underscore.
10 
11 #include <uLib/ListFunc.h>
12 
13 //-----------------------------------------------------------------------------
14 // C API's
15 //-----------------------------------------------------------------------------
16 
18 {
19  ListHead->Flink = ListHead->Blink = ListHead;
20 }
21 
22 bool _IsListEmpty( PLIST_ENTRY ListHead )
23 {
24  return (!ListHead || (ListHead->Flink == ListHead));
25 }
26 
28 {
29  register PLIST_ENTRY Entry = ListHead->Blink;
30  register PLIST_ENTRY Blink = Entry->Blink;
31  Blink->Flink = ListHead;
32  ListHead->Blink = Blink;
33  UnlinkListEntry( Entry );
34  return Entry;
35 }
36 
38 {
39  register PLIST_ENTRY Entry = ListHead->Flink;
40  register PLIST_ENTRY Flink = Entry->Flink;
41  Flink->Blink = ListHead;
42  ListHead->Flink = Flink;
43  UnlinkListEntry( Entry );
44  return Entry;
45 }
46 
48 {
49  // Overall performance is approximately equal for the two versions
50  #if 1 // 6 refs and 2 assigns
51  Entry->Blink->Flink = Entry->Flink;
52  Entry->Flink->Blink = Entry->Blink;
53  #else // 4 refs and 4 assigns
54  register PLIST_ENTRY Flink = Entry->Flink;
55  register PLIST_ENTRY Blink = Entry->Blink;
56  Blink->Flink = Flink;
57  Flink->Blink = Blink;
58  #endif
59  UnlinkListEntry( Entry );
60 }
61 
62 void _InsertTailList( PLIST_ENTRY ListHead, PLIST_ENTRY Entry )
63 {
64  register PLIST_ENTRY Blink = ListHead->Blink;
65  Entry->Flink = ListHead;
66  Entry->Blink = Blink;
67  Blink->Flink = Entry;
68  ListHead->Blink = Entry;
69 }
70 
71 void _InsertHeadList( PLIST_ENTRY ListHead, PLIST_ENTRY Entry )
72 {
73  register PLIST_ENTRY Flink = ListHead->Flink;
74  Entry->Flink = Flink;
75  Entry->Blink = ListHead;
76  Flink->Blink = Entry;
77  ListHead->Flink = Entry;
78 }
79 
80 // Addendum -------------------------------------------------------------------
81 
83 {
84  UINT Count = 0; PLIST_ENTRY Entry;
85  if (ListHead) for(
86  Entry = ListHead->Flink; Entry != ListHead;
87  Count++, Entry = Entry->Flink
88  );
89  return Count;
90 }
91 
92 bool ListForEach( PLIST_ENTRY ListHead,
93  bool (__stdcall *Action)( PLIST_ENTRY Entry, void* UserData ),
94  void* UserData )
95 {
96  PLIST_ENTRY Entry;
97  if (_IsListEmpty( ListHead )) return false;
98  Entry = ListHead->Flink;
99  while( Entry != ListHead )
100  {
101  PLIST_ENTRY Next = Entry->Flink;
102  if (!Action( Entry, UserData )) return false;
103  Entry = Next;
104  }
105  return true;
106 }
107 
108 void AttachHeadlessList( OUT PLIST_ENTRY Head, IN PLIST_ENTRY Circular )
109 {
110  Head->Flink = Circular;
111  Head->Blink = Circular->Blink;
112 }
113 
114 #if 0 // Pending
115 void _AppendTailList( PLIST_ENTRY ListHead, PLIST_ENTRY HeadlessListToAppend )
116 {
117  PLIST_ENTRY ListEnd = ListHead->Blink;
118 
119  ListHead->Blink->Flink = HeadlessListToAppend;
120  ListHead->Blink = HeadlessListToAppend->Blink;
121  HeadlessListToAppend->Blink->Flink = ListHead;
122  HeadlessListToAppend->Blink = ListEnd;
123 }
124 
125 PLIST_ENTRY _AppendList( PLIST_ENTRY Head, PLIST_ENTRY HeadedListToAppend )
126 {
127  PLIST_ENTRY FirstEntry;
128  if (IsListEmpty( HeadedListToAppend )) return NULL;
129 
130  FirstEntry = HeadedListToAppend->Flink;
131  _RemoveEntryList( HeadedListToAppend ); // Remove the listhead
132  _InitializeListHead( HeadedListToAppend ); // Reset to empty
133  _AppendTailList( Head, FirstEntry );
134  return FirstEntry;
135 }
136 #endif
137 
138 //-----------------------------------------------------------------------------
139 
140 // Hmm.. Where and when did [MSDN] InitializeEntryList disappear ?
141 // Did I just collect it from a parallell universe ?
142 
144  #if SEMICIRCULAR_SLIST
145  EntryOrHead->Next = EntryOrHead;
146  #else
147  EntryOrHead->Next = NULL;
148  #endif
149  }
150 
152  Entry->Next = ListHead->Next;
153  ListHead->Next = Entry;
154  }
155 
157  PSINGLE_LIST_ENTRY Entry = ListHead->Next;
158  #if SEMICIRCULAR_SLIST
159  if (Entry == ListHead) Entry = NULL; else ListHead->Next = Entry->Next;
160  #else
161  //ListHead->Next = (Entry == NULL) ? ListHead : Entry->Next; // Hybrid
162  if (Entry != NULL) ListHead->Next = Entry->Next; // DDK compliant
163  #endif
164  return Entry;
165  }
166 
167 //-----------------------------------------------------------------------------
168 // EOF
void AttachHeadlessList(OUT PLIST_ENTRY Head, IN PLIST_ENTRY Circular)
Definition: ListFunc.c:108
void _InitializeEntryList(PSINGLE_LIST_ENTRY EntryOrHead)
Definition: ListFunc.c:143
void _InsertHeadList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry)
Definition: ListFunc.c:71
struct _LIST_ENTRY * PLIST_ENTRY
#define UnlinkListEntry(E)
Definition: ListFunc.h:95
void _PushEntryList(PSINGLE_LIST_ENTRY ListHead, PSINGLE_LIST_ENTRY Entry)
Definition: ListFunc.c:151
PLIST_ENTRY _RemoveTailList(PLIST_ENTRY ListHead)
Definition: ListFunc.c:27
void _InitializeListHead(PLIST_ENTRY ListHead)
Definition: ListFunc.c:17
void _RemoveEntryList(PLIST_ENTRY Entry)
Definition: ListFunc.c:47
PLIST_ENTRY _RemoveHeadList(PLIST_ENTRY ListHead)
Definition: ListFunc.c:37
bool ListForEach(PLIST_ENTRY ListHead, bool(__stdcall *Action)(PLIST_ENTRY Entry, void *UserData), void *UserData)
Definition: ListFunc.c:92
struct _SINGLE_LIST_ENTRY * PSINGLE_LIST_ENTRY
UINT GetListEntryCount(PLIST_ENTRY ListHead)
Definition: ListFunc.c:82
bool _IsListEmpty(PLIST_ENTRY ListHead)
Definition: ListFunc.c:22
void _InsertTailList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry)
Definition: ListFunc.c:62
PSINGLE_LIST_ENTRY _PopEntryList(PSINGLE_LIST_ENTRY ListHead)
Definition: ListFunc.c:156