1 | --
|
---|
2 | -- Copyright (c) 2010 Jiri Svoboda
|
---|
3 | -- All rights reserved.
|
---|
4 | --
|
---|
5 | -- Redistribution and use in source and binary forms, with or without
|
---|
6 | -- modification, are permitted provided that the following conditions
|
---|
7 | -- are met:
|
---|
8 | --
|
---|
9 | -- o Redistributions of source code must retain the above copyright
|
---|
10 | -- notice, this list of conditions and the following disclaimer.
|
---|
11 | -- o Redistributions in binary form must reproduce the above copyright
|
---|
12 | -- notice, this list of conditions and the following disclaimer in the
|
---|
13 | -- documentation and/or other materials provided with the distribution.
|
---|
14 | -- o The name of the author may not be used to endorse or promote products
|
---|
15 | -- derived from this software without specific prior written permission.
|
---|
16 | --
|
---|
17 | -- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
---|
18 | -- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
---|
19 | -- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
---|
20 | -- IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
---|
21 | -- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
---|
22 | -- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
---|
23 | -- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
---|
24 | -- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
---|
25 | -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
---|
26 | -- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
---|
27 | --
|
---|
28 |
|
---|
29 | -- Doubly-linked list.
|
---|
30 | class List/t : IEnumerable/t is
|
---|
31 | var head : ListNode/t;
|
---|
32 |
|
---|
33 | -- New empty list.
|
---|
34 | new() is
|
---|
35 | head = new ListNode/t();
|
---|
36 | head.prev = head;
|
---|
37 | head.next = head;
|
---|
38 | end
|
---|
39 |
|
---|
40 | -- Append new entry at the end of the list.
|
---|
41 | fun Append(data : t) is
|
---|
42 | var n : ListNode/t;
|
---|
43 | var ntl : ListNode/t;
|
---|
44 |
|
---|
45 | ntl = head.prev;
|
---|
46 |
|
---|
47 | n = new ListNode/t();
|
---|
48 | n.data = data;
|
---|
49 |
|
---|
50 | n.prev = ntl;
|
---|
51 | n.next = head;
|
---|
52 | n.head = head;
|
---|
53 |
|
---|
54 | ntl.next = n;
|
---|
55 | head.prev = n;
|
---|
56 | end
|
---|
57 |
|
---|
58 | -- Return first node in the list or @c nil if there is none.
|
---|
59 | prop First : ListNode/t is
|
---|
60 | get is
|
---|
61 | return get_first();
|
---|
62 | end
|
---|
63 | end
|
---|
64 |
|
---|
65 | -- Return first node in the list or @c nil if there is none.
|
---|
66 | fun GetEnumerator() : IEnumerator/t is
|
---|
67 | return new ListEnumerator/t(get_first());
|
---|
68 | end
|
---|
69 |
|
---|
70 | -- Return first node in the list or @c nil if there is none.
|
---|
71 | fun get_first() : ListNode/t is
|
---|
72 | if head.next == head then
|
---|
73 | return nil;
|
---|
74 | else
|
---|
75 | return head.next;
|
---|
76 | end
|
---|
77 | end
|
---|
78 | end
|
---|
79 |
|
---|
80 | class ListNode/t is
|
---|
81 | var data : t;
|
---|
82 |
|
---|
83 | var prev : ListNode/t;
|
---|
84 | var next : ListNode/t;
|
---|
85 | var head : ListNode/t;
|
---|
86 |
|
---|
87 | -- Data stored in this node.
|
---|
88 | prop Data : t is
|
---|
89 | get is
|
---|
90 | return data;
|
---|
91 | end
|
---|
92 | end
|
---|
93 |
|
---|
94 | -- Previous node in list.
|
---|
95 | prop Prev : ListNode/t is
|
---|
96 | get is
|
---|
97 | return get_prev();
|
---|
98 | end
|
---|
99 | end
|
---|
100 |
|
---|
101 | -- Next node in list.
|
---|
102 | prop Next : ListNode/t is
|
---|
103 | get is
|
---|
104 | return get_next();
|
---|
105 | end
|
---|
106 | end
|
---|
107 |
|
---|
108 | -- Remove node from list.
|
---|
109 | fun Remove() is
|
---|
110 | var p : ListNode/t;
|
---|
111 | var n : ListNode/t;
|
---|
112 |
|
---|
113 | p = prev; n = next;
|
---|
114 | p.next = n;
|
---|
115 | n.prev = p;
|
---|
116 |
|
---|
117 | prev = nil;
|
---|
118 | next = nil;
|
---|
119 | end
|
---|
120 |
|
---|
121 | -- Get next node.
|
---|
122 | fun get_next() : ListNode/t is
|
---|
123 | if next != head then
|
---|
124 | return next;
|
---|
125 | else
|
---|
126 | return nil;
|
---|
127 | end
|
---|
128 | end
|
---|
129 |
|
---|
130 | -- Get previous node.
|
---|
131 | fun get_prev() : ListNode/t is
|
---|
132 | if prev != head then
|
---|
133 | return next;
|
---|
134 | else
|
---|
135 | return nil;
|
---|
136 | end
|
---|
137 | end
|
---|
138 | end
|
---|
139 |
|
---|
140 | class ListEnumerator/t : IEnumerator/t is
|
---|
141 | var first : ListNode/t;
|
---|
142 | var current : ListNode/t;
|
---|
143 | var started : bool;
|
---|
144 |
|
---|
145 | new(first_node : ListNode/t) is
|
---|
146 | first = first_node;
|
---|
147 | current = nil;
|
---|
148 | started = false;
|
---|
149 | end
|
---|
150 |
|
---|
151 | fun MoveNext() : bool is
|
---|
152 | if started then
|
---|
153 | current = current.Next;
|
---|
154 | else
|
---|
155 | current = first;
|
---|
156 | started = true;
|
---|
157 | end
|
---|
158 |
|
---|
159 | return current != nil;
|
---|
160 | end
|
---|
161 |
|
---|
162 | prop Data : t is
|
---|
163 | get is
|
---|
164 | return current.Data;
|
---|
165 | end
|
---|
166 | end
|
---|
167 | end
|
---|