]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BaseLib/LinkedList.c
Roll back modification for autogen of assemble code, we do not support PCD autogen...
[mirror_edk2.git] / MdePkg / Library / BaseLib / LinkedList.c
CommitLineData
878ddf1f 1/** @file\r
2 Linked List Library Functions.\r
3\r
4 Copyright (c) 2006, Intel Corporation<BR>\r
5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13 Module Name: LinkedList.c\r
14\r
15**/\r
16\r
17BOOLEAN\r
18EFIAPI\r
19IsNodeInList (\r
20 IN CONST LIST_ENTRY *List,\r
21 IN CONST LIST_ENTRY *Node\r
22 )\r
23{\r
24 UINTN Count;\r
25 CONST LIST_ENTRY *Ptr;\r
26 BOOLEAN Found;\r
27\r
28 //\r
29 // Test the validity of List and Node\r
30 //\r
31 ASSERT (List != NULL);\r
32 ASSERT (List->ForwardLink != NULL);\r
33 ASSERT (List->BackLink != NULL);\r
34 ASSERT (Node != NULL);\r
35\r
dc530c7b 36 Count = PcdGet32 (PcdMaximumLinkedListLength);\r
7d7c2b46 37 if (Count != 0) {\r
38 Count++;\r
39 }\r
40\r
878ddf1f 41 Ptr = List;\r
42 do {\r
43 Ptr = Ptr->ForwardLink;\r
44 Count--;\r
45 } while ((Ptr != List) && (Ptr != Node) && (Count > 0));\r
46 Found = (BOOLEAN)(Ptr == Node);\r
47\r
dc530c7b 48 if (PcdGet32 (PcdMaximumLinkedListLength) > 0) {\r
878ddf1f 49 while ((Count > 0) && (Ptr != List)) {\r
50 Ptr = Ptr->ForwardLink;\r
7d7c2b46 51 Count--;\r
878ddf1f 52 }\r
53 ASSERT (Count > 0);\r
54 }\r
55\r
56 return Found;\r
57}\r
58\r
59/**\r
60 Initializes the head node of a doubly linked list, and returns the pointer to\r
61 the head node of the doubly linked list.\r
62\r
63 Initializes the forward and backward links of a new linked list. After\r
64 initializing a linked list with this function, the other linked list\r
65 functions may be used to add and remove nodes from the linked list. It is up\r
66 to the caller of this function to allocate the memory for ListHead.\r
67\r
68 If ListHead is NULL, then ASSERT().\r
69\r
70 @param ListHead A pointer to the head node of a new doubly linked list.\r
71\r
72 @return ListHead\r
73\r
74**/\r
75LIST_ENTRY *\r
76EFIAPI\r
77InitializeListHead (\r
78 IN OUT LIST_ENTRY *List\r
79 )\r
80\r
81{\r
82 ASSERT (List != NULL);\r
83\r
84 List->ForwardLink = List;\r
85 List->BackLink = List;\r
86 return List;\r
87}\r
88\r
89/**\r
90 Adds a node to the beginning of a doubly linked list, and returns the pointer\r
91 to the head node of the doubly linked list.\r
92\r
93 Adds the node Entry at the beginning of the doubly linked list denoted by\r
94 ListHead, and returns ListHead.\r
95\r
96 If ListHead is NULL, then ASSERT().\r
97 If Entry is NULL, then ASSERT().\r
98 If ListHead was not initialized with InitializeListHead(), then ASSERT().\r
99 If PcdMaximumLinkedListLenth is not zero, and ListHead contains more than\r
100 PcdMaximumLinkedListLenth nodes, then ASSERT().\r
101\r
102 @param ListHead A pointer to the head node of a doubly linked list.\r
103 @param Entry A pointer to a node that is to be inserted at the beginning\r
104 of a doubly linked list.\r
105\r
106 @return ListHead\r
107\r
108**/\r
109LIST_ENTRY *\r
110EFIAPI\r
111InsertHeadList (\r
112 IN OUT LIST_ENTRY *List,\r
113 IN OUT LIST_ENTRY *Entry\r
114 )\r
115{\r
116 //\r
117 // ASSERT List not too long and Entry is not one of the nodes of List\r
118 //\r
119 ASSERT (!IsNodeInList (List, Entry));\r
120\r
121 Entry->ForwardLink = List->ForwardLink;\r
122 Entry->BackLink = List;\r
123 Entry->ForwardLink->BackLink = Entry;\r
124 List->ForwardLink = Entry;\r
125 return List;\r
126}\r
127\r
128/**\r
129 Adds a node to the end of a doubly linked list, and returns the pointer to\r
130 the head node of the doubly linked list.\r
131\r
132 Adds the node Entry to the end of the doubly linked list denoted by ListHead,\r
133 and returns ListHead.\r
134\r
135 If ListHead is NULL, then ASSERT().\r
136 If Entry is NULL, then ASSERT().\r
137 If ListHead was not initialized with InitializeListHead(), then ASSERT().\r
138 If PcdMaximumLinkedListLenth is not zero, and ListHead contains more than\r
139 PcdMaximumLinkedListLenth nodes, then ASSERT().\r
140\r
141 @param ListHead A pointer to the head node of a doubly linked list.\r
142 @param Entry A pointer to a node that is to be added at the end of the\r
143 doubly linked list.\r
144\r
145 @return ListHead\r
146\r
147**/\r
148LIST_ENTRY *\r
149EFIAPI\r
150InsertTailList (\r
151 IN OUT LIST_ENTRY *List,\r
152 IN OUT LIST_ENTRY *Entry\r
153 )\r
154{\r
155 //\r
156 // ASSERT List not too long and Entry is not one of the nodes of List\r
157 //\r
158 ASSERT (!IsNodeInList (List, Entry));\r
159\r
160 Entry->ForwardLink = List;\r
161 Entry->BackLink = List->BackLink;\r
162 Entry->BackLink->ForwardLink = Entry;\r
163 List->BackLink = Entry;\r
164 return List;\r
165}\r
166\r
167/**\r
168 Retrieves the first node of a doubly linked list.\r
169\r
170 Returns the first node of a doubly linked list. List must have been\r
171 initialized with InitializeListHead(). If List is empty, then NULL is\r
172 returned.\r
173\r
174 If List is NULL, then ASSERT().\r
175 If List was not initialized with InitializeListHead(), then ASSERT().\r
176 If PcdMaximumLinkedListLenth is not zero, and List contains more than\r
177 PcdMaximumLinkedListLenth nodes, then ASSERT().\r
178\r
179 @param List A pointer to the head node of a doubly linked list.\r
180\r
181 @return The first node of a doubly linked list.\r
182 @retval NULL The list is empty.\r
183\r
184**/\r
185LIST_ENTRY *\r
186EFIAPI\r
187GetFirstNode (\r
188 IN CONST LIST_ENTRY *List\r
189 )\r
190{\r
191 //\r
192 // ASSERT List not too long\r
193 //\r
194 ASSERT (IsNodeInList (List, List));\r
195\r
196 return List->ForwardLink;\r
197}\r
198\r
199/**\r
200 Retrieves the next node of a doubly linked list.\r
201\r
202 Returns the node of a doubly linked list that follows Node. List must have\r
203 been initialized with InitializeListHead(). If List is empty, then List is\r
204 returned.\r
205\r
206 If List is NULL, then ASSERT().\r
207 If Node is NULL, then ASSERT().\r
208 If List was not initialized with InitializeListHead(), then ASSERT().\r
209 If PcdMaximumLinkedListLenth is not zero, and List contains more than\r
210 PcdMaximumLinkedListLenth nodes, then ASSERT().\r
211 If Node is not a node in List, then ASSERT().\r
212\r
213 @param List A pointer to the head node of a doubly linked list.\r
214 @param Node A pointer to a node in the doubly linked list.\r
215\r
216 @return Pointer to the next node if one exists. Otherwise a null value which\r
217 is actually List is returned.\r
218\r
219**/\r
220LIST_ENTRY *\r
221EFIAPI\r
222GetNextNode (\r
223 IN CONST LIST_ENTRY *List,\r
224 IN CONST LIST_ENTRY *Node\r
225 )\r
226{\r
227 //\r
228 // ASSERT List not too long and Node is one of the nodes of List\r
229 //\r
230 ASSERT (IsNodeInList (List, Node));\r
231\r
232 return Node->ForwardLink;\r
233}\r
234\r
235/**\r
236 Checks to see if a doubly linked list is empty or not.\r
237\r
238 Checks to see if the doubly linked list is empty. If the linked list contains\r
239 zero nodes, this function returns TRUE. Otherwise, it returns FALSE.\r
240\r
241 If ListHead is NULL, then ASSERT().\r
242 If ListHead was not initialized with InitializeListHead(), then ASSERT().\r
243 If PcdMaximumLinkedListLenth is not zero, and List contains more than\r
244 PcdMaximumLinkedListLenth nodes, then ASSERT().\r
245\r
246 @param ListHead A pointer to the head node of a doubly linked list.\r
247\r
248 @retval TRUE The linked list is empty.\r
249 @retval FALSE The linked list is not empty.\r
250\r
251**/\r
252BOOLEAN\r
253EFIAPI\r
254IsListEmpty (\r
255 IN CONST LIST_ENTRY *List\r
256 )\r
257{\r
258 //\r
259 // ASSERT List not too long\r
260 //\r
261 ASSERT (IsNodeInList (List, List));\r
262\r
263 return (BOOLEAN)(List->ForwardLink == List);\r
264}\r
265\r
266/**\r
267 Determines if a node in a doubly linked list is null.\r
268\r
269 Returns FALSE if Node is one of the nodes in the doubly linked list specified\r
270 by List. Otherwise, TRUE is returned. List must have been initialized with\r
271 InitializeListHead().\r
272\r
273 If List is NULL, then ASSERT().\r
274 If Node is NULL, then ASSERT().\r
275 If List was not initialized with InitializeListHead(), then ASSERT().\r
276 If PcdMaximumLinkedListLenth is not zero, and List contains more than\r
277 PcdMaximumLinkedListLenth nodes, then ASSERT().\r
278 If Node is not a node in List and Node is not equal to List, then ASSERT().\r
279\r
280 @param List A pointer to the head node of a doubly linked list.\r
281 @param Node A pointer to a node in the doubly linked list.\r
282\r
283 @retval TRUE Node is one of the nodes in the doubly linked list.\r
284 @retval FALSE Node is not one of the nodes in the doubly linked list.\r
285\r
286**/\r
287BOOLEAN\r
288EFIAPI\r
289IsNull (\r
290 IN CONST LIST_ENTRY *List,\r
291 IN CONST LIST_ENTRY *Node\r
292 )\r
293{\r
294 //\r
295 // ASSERT List not too long and Node is one of the nodes of List\r
296 //\r
297 ASSERT (IsNodeInList (List, Node));\r
298\r
299 return (BOOLEAN)(Node == List);\r
300}\r
301\r
302/**\r
303 Determines if a node the last node in a doubly linked list.\r
304\r
305 Returns TRUE if Node is the last node in the doubly linked list specified by\r
306 List. Otherwise, FALSE is returned. List must have been initialized with\r
307 InitializeListHead().\r
308\r
309 If List is NULL, then ASSERT().\r
310 If Node is NULL, then ASSERT().\r
311 If List was not initialized with InitializeListHead(), then ASSERT().\r
312 If PcdMaximumLinkedListLenth is not zero, and List contains more than\r
313 PcdMaximumLinkedListLenth nodes, then ASSERT().\r
314 If Node is not a node in List, then ASSERT().\r
315\r
316 @param List A pointer to the head node of a doubly linked list.\r
317 @param Node A pointer to a node in the doubly linked list.\r
318\r
319 @retval TRUE Node is the last node in the linked list.\r
320 @retval FALSE Node is not the last node in the linked list.\r
321\r
322**/\r
323BOOLEAN\r
324EFIAPI\r
325IsNodeAtEnd (\r
326 IN CONST LIST_ENTRY *List,\r
327 IN CONST LIST_ENTRY *Node\r
328 )\r
329{\r
330 //\r
331 // ASSERT List not too long and Node is one of the nodes of List\r
332 //\r
333 ASSERT (IsNodeInList (List, Node));\r
334\r
335 return (BOOLEAN)(!IsNull (List, Node) && List->BackLink == Node);\r
336}\r
337\r
338/**\r
339 Swaps the location of two nodes in a doubly linked list, and returns the\r
340 first node after the swap.\r
341\r
342 If FirstEntry is identical to SecondEntry, then SecondEntry is returned.\r
343 Otherwise, the location of the FirstEntry node is swapped with the location\r
344 of the SecondEntry node in a doubly linked list. SecondEntry must be in the\r
345 same double linked list as FirstEntry and that double linked list must have\r
346 been initialized with InitializeListHead(). SecondEntry is returned after the\r
347 nodes are swapped.\r
348\r
349 If FirstEntry is NULL, then ASSERT().\r
350 If SecondEntry is NULL, then ASSERT().\r
351 If SecondEntry and FirstEntry are not in the same linked list, then ASSERT().\r
352 If PcdMaximumLinkedListLenth is not zero, and the linked list containing\r
353 FirstEntry and SecondEntry contains more than PcdMaximumLinkedListLenth\r
354 nodes, then ASSERT().\r
355\r
356 @param FirstEntry A pointer to a node in a linked list.\r
357 @param SecondEntry A pointer to another node in the same linked list.\r
358\r
359**/\r
360LIST_ENTRY *\r
361EFIAPI\r
362SwapListEntries (\r
363 IN OUT LIST_ENTRY *FirstEntry,\r
364 IN OUT LIST_ENTRY *SecondEntry\r
365 )\r
366{\r
367 LIST_ENTRY *Ptr;\r
368\r
369 if (FirstEntry == SecondEntry) {\r
370 return SecondEntry;\r
371 }\r
372\r
373 //\r
374 // ASSERT Entry1 and Entry2 are in the same linked list\r
375 //\r
376 ASSERT (IsNodeInList (FirstEntry, SecondEntry));\r
377\r
378 //\r
379 // Ptr is the node pointed to by FirstEntry->ForwardLink\r
380 //\r
381 Ptr = RemoveEntryList (FirstEntry);\r
382\r
383 //\r
384 // If FirstEntry immediately follows SecondEntry, FirstEntry willl be placed\r
385 // immediately in front of SecondEntry\r
386 //\r
387 if (Ptr->BackLink == SecondEntry) {\r
388 return InsertTailList (SecondEntry, FirstEntry);\r
389 }\r
390\r
391 //\r
392 // Ptr == SecondEntry means SecondEntry immediately follows FirstEntry,\r
393 // then there are no further steps necessary\r
394 //\r
395 if (Ptr == InsertHeadList (SecondEntry, FirstEntry)) {\r
396 return Ptr;\r
397 }\r
398\r
399 //\r
400 // Move SecondEntry to the front of Ptr\r
401 //\r
402 RemoveEntryList (SecondEntry);\r
403 InsertTailList (Ptr, SecondEntry);\r
404 return SecondEntry;\r
405}\r
406\r
407/**\r
408 Removes a node from a doubly linked list, and returns the node that follows\r
409 the removed node.\r
410\r
411 Removes the node Entry from a doubly linked list. It is up to the caller of\r
412 this function to release the memory used by this node if that is required. On\r
413 exit, the node following Entry in the doubly linked list is returned. If\r
414 Entry is the only node in the linked list, then the head node of the linked\r
415 list is returned.\r
416\r
417 If Entry is NULL, then ASSERT().\r
418 If Entry is the head node of an empty list, then ASSERT().\r
419 If PcdMaximumLinkedListLenth is not zero, and the linked list containing\r
420 Entry contains more than PcdMaximumLinkedListLenth nodes, then ASSERT().\r
421\r
422 @param Entry A pointer to a node in a linked list\r
423\r
424 @return Entry\r
425\r
426**/\r
427LIST_ENTRY *\r
428EFIAPI\r
429RemoveEntryList (\r
430 IN CONST LIST_ENTRY *Entry\r
431 )\r
432{\r
433 ASSERT (!IsListEmpty (Entry));\r
434\r
435 Entry->ForwardLink->BackLink = Entry->BackLink;\r
436 Entry->BackLink->ForwardLink = Entry->ForwardLink;\r
437 return Entry->ForwardLink;\r
438}\r