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.
252 When supplied with a NULL list argument, defaults to the exec port list.
258 // Look for a node with the name "Hello"
259 node = FindName (list, "Hello");
268 ******************************************************************************/
273 FindNode when supplied with a NULL list searches the exec ports list.
274 per ampurtle, reference RKM 1.0
275 Hmmm... why is there also a separate FindName.c
276 Both files changed....
279 list
= &SysBase
->PortList
;
284 /* Look through the list */
285 for (node
=GetHead(list
); node
; node
=GetSucc(node
))
287 /* Only compare the names if this node has one. */
290 /* Check the node. If we found it, stop. */
291 if (!strcmp (node
->ln_Name
, name
))
297 If we found a node, this will contain the pointer to it. If we
298 didn't, this will be <code>NULL</code> (either because the list was
299 empty or because we tried all nodes in the list)
304 /*#AROS_LH********************************************************************
310 struct List
* list
, /*#A0
311 The list to insert the node into */
312 struct Node
* node
, /*#A1
313 This node is to be inserted */
314 struct Node
* pred
) /*#A2
315 Insert after this node. If this is NULL, node is inserted
316 as the first node (same as AddHead()) */
319 Exec (39), BaseNotNecessary
322 Insert Node <code>node</code> after <code>pred</code> in list.
330 struct Node * pred, * node;
332 // Insert Node node as second node in list
333 pred = GetHead (list);
334 Insert (list, node, pred);
343 ******************************************************************************/
348 /* If we have a node to insert behind... */
351 /* Is this the last node in the list ? */
352 if (pred
->ln_Succ
) /* Normal node ? */
355 Our successor is the successor of the node we add ourselves
356 behind and our predecessor is just the node itself.
358 node
->ln_Succ
= pred
->ln_Succ
;
359 node
->ln_Pred
= pred
;
362 We are the predecessor of the successor of our predecessor
363 (What ? blblblb... ;) and of our predecessor itself.
364 Note that here the sequence is quite important since
365 we need ln_Succ in the first expression and change it in
368 pred
->ln_Succ
->ln_Pred
= node
;
369 pred
->ln_Succ
= node
;
374 Add the node at the end of the list.
375 Make the node point to the head of the list. Our
376 predecessor is the previous last node of the list.
378 node
->ln_Succ
= (struct Node
*)&list
->lh_Tail
;
379 node
->ln_Pred
= list
->lh_TailPred
;
382 Now we are the last now. Make the old last node point to us
383 and the pointer to the last node, too.
385 list
->lh_TailPred
->ln_Succ
= node
;
386 list
->lh_TailPred
= node
;
392 add at the top of the list. I do not use <code>AddHead()</code>
393 here but write the code twice for two reasons: 1. The code is small
394 and therefore errors are unlikely and 2. If I would call
395 <code>AddHead()</code>, it would take almost as long to call the
396 function as the execution would take yielding 100% overhead.
398 node
->ln_Succ
= list
->lh_Head
;
399 node
->ln_Pred
= (struct Node
*)&list
->lh_Head
;
400 list
->lh_Head
->ln_Pred
= node
;
401 list
->lh_Head
= node
;
405 /*#AROS_LH********************************************************************
408 struct Node
* RemHead (
411 struct List
* list
) /*#A0
412 The list to remove the node from */
415 Exec (43), BaseNotNecessary
418 Remove the first node from a list.
421 The node that has been removed.
429 // Remove node and return it
430 head = RemHead (list);
439 ******************************************************************************/
445 Unfortunately, there is no (quick) check that the node
449 /* Get the address of the first node or NULL */
450 node
= list
->lh_Head
->ln_Succ
;
453 node
->ln_Pred
= (struct Node
*)list
;
454 node
= list
->lh_Head
;
455 list
->lh_Head
= node
->ln_Succ
;
458 /* Return the address or NULL */
462 /*#AROS_LH********************************************************************
468 struct Node
* node
) /*#A1
469 Remove this node from the list it is currently in. */
472 Exec (42), BaseNotNecessary
475 Remove a node from a list.
480 There is no need to specify the list but the node must be in
496 ******************************************************************************/
500 Unfortunately, there is no (quick) check that the node
505 Just bend the pointers around the node, ie. we make our
506 predecessor point to our successor and vice versa
508 node
->ln_Pred
->ln_Succ
= node
->ln_Succ
;
509 node
->ln_Succ
->ln_Pred
= node
->ln_Pred
;
512 /*#AROS_LH********************************************************************
515 struct Node
* RemTail (
518 struct List
* list
) /*#A0
519 The list to remove the node from */
522 Exec (44), BaseNotNecessary
525 Remove the last node from a list.
528 The node that has been removed.
536 // Remove node and return it
537 tail = RemTail (list);
546 ******************************************************************************/
552 Unfortunately, there is no (quick) check that the node
556 /* Get the last node of the list */
557 if ( (node
= GetTail (list
)) )
559 /* normal code to remove a node if there is one */
560 node
->ln_Pred
->ln_Succ
= node
->ln_Succ
;
561 node
->ln_Succ
->ln_Pred
= node
->ln_Pred
;
564 /* return it's address or NULL if there was no node */