2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
4 #Description: @AROS.Exec.LISTS@
6 <chapter title="Exec Lists">
8 <p>Exec offers a standard way to create lists of structures. All you
9 need to do is to put <code>struct Node node;</code>
11 field into any structure you want to collect in a list. You can
12 then use the macro <code>NEWLIST()</code> to initialize a structure
13 of the type <code>struct List</code> and insert the nodes
14 with <code>AddHead()</code>, <code>AddTail()</code>,
15 <code>Enqueue()</code> or <code>Insert()</code>.<p>
17 <p>FIXME Explain other functions, how to use the macros,
18 give some example programs and explain how lists work.<p>
24 #include <exec/lists.h> /*#ALL*/
25 #include <proto/exec.h> /*#ALL*/
27 /*#AROS_LH********************************************************************
33 struct List
* list
, /*#A0
34 The list to insert the node into */
35 struct Node
* node
) /*#A1
36 This node is to be inserted */
39 Exec (40), BaseNotNecessary
42 Insert Node <code>node</code> as the first node of the list.
63 ******************************************************************************/
65 ASSERT_VALID_PTR(node
);
66 ASSERT_VALID_PTR(list
);
69 Make the node point to the old first node in the list and to the
72 node
->ln_Succ
= list
->lh_Head
;
73 node
->ln_Pred
= (struct Node
*)&list
->lh_Head
;
76 New we come before the old first node which must now point to us
77 and the same applies to the pointer to-the-first-node in the
80 list
->lh_Head
->ln_Pred
= node
;
84 /*#AROS_LH********************************************************************
90 struct List
* list
, /*#A0
91 The list to insert the node into */
92 struct Node
* node
) /*#A1
93 This node is to be inserted */
96 Exec (41), BaseNotNecessary
99 Insert Node node at the end of a list.
109 // Insert Node at end of the list
110 AddTail (list, node);
119 ******************************************************************************/
121 // ASSERT_VALID_PTR(node); argh! TypeOfMem() doesn't know about the data segment!
122 ASSERT_VALID_PTR(list
);
125 Make the node point to the head of the list. Our predecessor is the
126 previous last node of the list.
128 node
->ln_Succ
= (struct Node
*)&list
->lh_Tail
;
129 node
->ln_Pred
= list
->lh_TailPred
;
132 Now we are the last now. Make the old last node point to us
133 and the pointer to the last node, too.
135 list
->lh_TailPred
->ln_Succ
= node
;
136 list
->lh_TailPred
= node
;
139 /*#AROS_LH********************************************************************
145 struct List
* list
, /*#A0
146 Insert into this list. The list has to be in descending
147 order in respect to the field ln_Pri of all nodes. */
148 struct Node
* node
) /*#A1
149 This node is to be inserted. Note that this has to
150 be a complete node and not a MinNode ! */
153 Exec (45), BaseNotNecessary
156 Sort a node into a list. The sort-key is the field
157 <code>node->ln_Pri</code>.
158 The node will be inserted into the list before the first node
159 with lower priority. This creates a FIFO queue for nodes with
163 The new node will be inserted before nodes with lower
167 The list has to be in descending order in respect to the field
168 <code>ln_Pri</code> of all nodes.
176 // Sort the node at the correct place into the list
177 Enqueue (list, node);
186 ******************************************************************************/
193 /* Look through the list */
194 ForeachNode (list
, next
)
197 Look for the first node with a lower pri as the node
198 we have to insert into the list.
200 if (node
->ln_Pri
> next
->ln_Pri
)
204 /* Insert the node before(!) next. The situation looks like this:
206 A<->next<->B *<-node->*
208 ie. next->ln_Pred points to A, A->ln_Succ points to next,
209 next->ln_Succ points to B, B->ln_Pred points to next.
210 ln_Succ and ln_Pred of node contain illegal pointers.
213 /* Let node point to A: A<-node */
214 node
->ln_Pred
= next
->ln_Pred
;
216 /* Let A point to node: A->node */
217 next
->ln_Pred
->ln_Succ
= node
;
219 /* Make next point to node: A<->node<-next<->B */
220 next
->ln_Pred
= node
;
222 /* Make node point to next: A<->node->next<->B */
223 node
->ln_Succ
= next
;
227 /*#AROS_LH********************************************************************
230 struct Node
* FindName (
233 struct List
* list
, /*#A0
236 This is the name to look for. */
239 Exec (46), BaseNotNecessary
242 Look for a node with a certain name in a list.
247 The search is case-sensitive, so "Hello" will not find a node
250 The list must contain complete Nodes and no MinNodes.
256 // Look for a node with the name "Hello"
257 node = FindName (list, "Hello");
266 ******************************************************************************/
273 /* Look through the list */
274 for (node
=GetHead(list
); node
; node
=GetSucc(node
))
276 /* Only compare the names if this node has one. */
279 /* Check the node. If we found it, stop. */
280 if (!strcmp (node
->ln_Name
, name
))
286 If we found a node, this will contain the pointer to it. If we
287 didn't, this will be <code>NULL</code> (either because the list was
288 empty or because we tried all nodes in the list)
293 /*#AROS_LH********************************************************************
299 struct List
* list
, /*#A0
300 The list to insert the node into */
301 struct Node
* node
, /*#A1
302 This node is to be inserted */
303 struct Node
* pred
) /*#A2
304 Insert after this node. If this is NULL, node is inserted
305 as the first node (same as AddHead()) */
308 Exec (39), BaseNotNecessary
311 Insert Node <code>node</code> after <code>pred</code> in list.
319 struct Node * pred, * node;
321 // Insert Node node as second node in list
322 pred = GetHead (list);
323 Insert (list, node, pred);
332 ******************************************************************************/
337 /* If we have a node to insert behind... */
340 /* Is this the last node in the list ? */
341 if (pred
->ln_Succ
) /* Normal node ? */
344 Our successor is the successor of the node we add ourselves
345 behind and our predecessor is just the node itself.
347 node
->ln_Succ
= pred
->ln_Succ
;
348 node
->ln_Pred
= pred
;
351 We are the predecessor of the successor of our predecessor
352 (What ? blblblb... ;) and of our predecessor itself.
353 Note that here the sequence is quite important since
354 we need ln_Succ in the first expression and change it in
357 pred
->ln_Succ
->ln_Pred
= node
;
358 pred
->ln_Succ
= node
;
363 Add the node at the end of the list.
364 Make the node point to the head of the list. Our
365 predecessor is the previous last node of the list.
367 node
->ln_Succ
= (struct Node
*)&list
->lh_Tail
;
368 node
->ln_Pred
= list
->lh_TailPred
;
371 Now we are the last now. Make the old last node point to us
372 and the pointer to the last node, too.
374 list
->lh_TailPred
->ln_Succ
= node
;
375 list
->lh_TailPred
= node
;
381 add at the top of the list. I do not use <code>AddHead()</code>
382 here but write the code twice for two reasons: 1. The code is small
383 and therefore errors are unlikely and 2. If I would call
384 <code>AddHead()</code>, it would take almost as long to call the
385 function as the execution would take yielding 100% overhead.
387 node
->ln_Succ
= list
->lh_Head
;
388 node
->ln_Pred
= (struct Node
*)&list
->lh_Head
;
389 list
->lh_Head
->ln_Pred
= node
;
390 list
->lh_Head
= node
;
394 /*#AROS_LH********************************************************************
397 struct Node
* RemHead (
400 struct List
* list
) /*#A0
401 The list to remove the node from */
404 Exec (43), BaseNotNecessary
407 Remove the first node from a list.
410 The node that has been removed.
418 // Remove node and return it
419 head = RemHead (list);
428 ******************************************************************************/
434 Unfortunately, there is no (quick) check that the node
438 /* Get the address of the first node or NULL */
439 node
= list
->lh_Head
->ln_Succ
;
442 node
->ln_Pred
= (struct Node
*)list
;
443 node
= list
->lh_Head
;
444 list
->lh_Head
= node
->ln_Succ
;
447 /* Return the address or NULL */
451 /*#AROS_LH********************************************************************
457 struct Node
* node
) /*#A1
458 Remove this node from the list it is currently in. */
461 Exec (42), BaseNotNecessary
464 Remove a node from a list.
469 There is no need to specify the list but the node must be in
485 ******************************************************************************/
489 Unfortunately, there is no (quick) check that the node
494 Just bend the pointers around the node, ie. we make our
495 predecessor point to our successor and vice versa
497 node
->ln_Pred
->ln_Succ
= node
->ln_Succ
;
498 node
->ln_Succ
->ln_Pred
= node
->ln_Pred
;
501 /*#AROS_LH********************************************************************
504 struct Node
* RemTail (
507 struct List
* list
) /*#A0
508 The list to remove the node from */
511 Exec (44), BaseNotNecessary
514 Remove the last node from a list.
517 The node that has been removed.
525 // Remove node and return it
526 tail = RemTail (list);
535 ******************************************************************************/
541 Unfortunately, there is no (quick) check that the node
545 /* Get the last node of the list */
546 if ( (node
= GetTail (list
)) )
548 /* normal code to remove a node if there is one */
549 node
->ln_Pred
->ln_Succ
= node
->ln_Succ
;
550 node
->ln_Succ
->ln_Pred
= node
->ln_Pred
;
553 /* return it's address or NULL if there was no node */