| Previous | Table of Contents | Next |
10.4.3.10. Implementing the Linked List Package
Now I examine the body of HB.Lists_Generic, which, given the preceding discussion, is mostly straightforward.
1 with Ada.Unchecked_Deallocation;
2 package body HB.Lists_Generic is
3
4 procedure Display(L: in List) is
5 Current: ListPtr := L.Head;
6 begin
7 while Current /= Null loop
8 DisplayElement(Current.Element);
9 Current := Current.Next;
10 end loop;
11 end Display;
12
13 procedure AddToEnd
14 (L: in out List; Element: in ElementType) is
15 begin
16 if L.Tail = Null then
17 L.Tail := new ListNode(Element, Null);
18 L.Head := L.Tail;
19 else
20 L.Tail.Next := new ListNode(Element, Null);
21 L.Tail := L.Tail.Next;
22 end if;
23 end AddToEnd;
24
25 function =(L1, L2: List) return Boolean is
26 Current1: ListPtr := L1.Head;
27 Current2: ListPtr := L2.Head;
28 begin
29 while Current1 /= Null and Current2 /= Null loop
30 if Current1.Element /= Current2.Element then
31 return False;
32 end if;
33 Current1 := Current1.Next;
34 Current2 := Current2.Next;
35 end loop;
36 return (Current1 = Null and Current2 = Null);
37 end =;
38
39 procedure Adjust (L: in out List) is
40 TempList: List;
41 Current: ListPtr;
42 begin
43 Current := L.Head;
44 while Current /= Null loop
45 AddToEnd (TempList, Current.Element);
46 Current := Current.Next;
47 end loop;
48 L.Head := TempList.Head;
49 L.Tail := TempList.Tail;
50 TempList.Head := Null;
51 TempList.Tail := Null;
52 end Adjust;
53
54 procedure Dispose is
55 new Ada.Unchecked_Deallocation
56 (Object => ListNode, Name => ListPtr);
57
58 procedure Finalize (L: in out List) is
59 Current: ListPtr := L.Head;
60 Leading: ListPtr;
61 begin
62 while Current /= Null loop
63 Leading := Current.Next;
64 Dispose(Current);
65 Current := Leading;
66 end loop;
67 L.Head := Null;
68 L.Tail := Null;
69 end Finalize;
70
71 procedure MakeEmpty (L: in out List) is
72 begin
73 Finalize(L);
74 end MakeEmpty;
75
76 procedure Initialize (L: in out List) is
77 begin
78 Finalize (L);
79 end Initialize;
80
81 end HB.Lists_Generic;
Refer again to the linked list:
The context clause in line 1 mentions Ada.Unchecked_Deallocation. I explain this shortly. Now given a list like the preceding one, it is easy to see that the procedure in lines 4-11 declares a temporary pointer Current, initialized to the first node in the list. The while loop, in traditional linked-list programming style, walks down the list, calling DisplayElement to display each element in turn.
In AddToEnd (lines 13-23), I allocate a new node, store the element in it, and connect it to the list. If the list is initially empty, the new node is the first and only one, and
L.Tail := new ListNode(Element, Null);
stores in L.Tail a pointer to a new (heap-allocated) node with Element and Null in the corresponding fields. (Strictly speaking, the Null could have been omitted because that field is already Null; I include it for emphasis.) If the list already contains some nodes, then I connect the new node to the end of the list and change the Tail pointer accordingly (lines 20-21).
The overloaded (=) operator (lines 25-37) simply moves two temporary pointers down the two lists in parallel, returning False to the calling program if, at a given point in both lists, their elements disagree. The loop iterates until the end of one or both lists is reached. The two lists are equal (line 36) if and only both ends are reached at the same time.
Lines 39-52 give the implementation of the overriding Adjust procedure. Because Adjust has only one parameter, L, I make Adjust work as a deep copy operation by copying L into a temporary list, TempList, using AddToEnd in a straightforward while loop, and then I copy the head and tail pointers of TempList back into L. In this manner I return in L a list that is distinct from the one received in L. Now suppose a client program executes
L1 := L2;
Because List is a controlled type, L1 is first finalized. Then the header block (head and tail pointers) of L2 are copied into L1. At this point, the Adjust is called. The client now has, in L1, a complete but distinct copy of L2, as desired.
| Previous | Table of Contents | Next |