1 module prova.util.linkedlist;
2 
3 import std.typecons;
4 
5 /**
6  * Linked list node
7  */
8 class Node(T)
9 {
10   private LinkedList!T list;
11   private Node!T next;
12   private Node!T last;
13   private Nullable!T value;
14 
15   /**
16    * Retrieves the stored value
17    */
18   T getValue()
19   {
20     return value;
21   }
22 
23   /**
24    * Modifies the stored value
25    */
26   void setValue(T value)
27   {
28     this.value = value;
29   }
30 
31   /**
32    * Gets the node previous in order
33    */
34   Node!T getLast()
35   {
36     return last;
37   }
38 
39   /**
40    * Gets the node next in order
41    */
42   Node!T getNext()
43   {
44     return next;
45   }
46 
47   /**
48    * Detaches the node from the list
49    */
50   void remove()
51   {
52     if(last)
53       last.next = next;
54 
55     if(next)
56       next.last = last;
57 
58     if(list.last == this)
59       list.last = null;
60 
61     if(list.first == this)
62       list.first = null;
63 
64     list.count--;
65   }
66 }
67 
68 /**
69   * LinkedList template
70   */
71 class LinkedList(T)
72 {
73   private Node!T first;
74   private Node!T last;
75   private int count = 0;
76 
77   /**
78     * Returns the node count
79     */
80   @property int length()
81   {
82     return count;
83   }
84 
85   Node!T getFirstNode()
86   {
87     return first;
88   }
89 
90   Node!T getLastNode()
91   {
92     return last;
93   }
94 
95   /**
96     * Creates a node and places it at the start of the list
97     */
98   Node!T insertFront(T value)
99   {
100     return insertBefore(value, first);
101   }
102 
103   /**
104     * Creates a node and places it at the end of the list
105     */
106   Node!T insertBack(T value)
107   {
108     return insertAfter(value, last);
109   }
110 
111   /**
112     * Creates a node in the list placed before the specified node
113     */
114   Node!T insertBefore(T value, Node!T node)
115   {
116     if(!node && first)
117       return insertBefore(value, first);
118 
119     Node!T storedNode = new Node!T;
120     storedNode.value = value;
121     storedNode.list = this;
122 
123     if(node) {
124       storedNode.last = node.last;
125       node.last = storedNode;
126       storedNode.next = node;
127     } else {
128       first = last = storedNode;
129     }
130 
131     if(storedNode.last)
132       storedNode.last.next = storedNode;
133 
134     count++;
135     return storedNode;
136   }
137 
138   /**
139     * Creates a node in the list placed after the specified node
140     */
141   Node!T insertAfter(T value, Node!T node)
142   {
143     if(!node && last)
144       return insertAfter(value, last);
145 
146     Node!T storedNode = new Node!T;
147     storedNode.value = value;
148     storedNode.list = this;
149 
150     if(node) {
151       storedNode.next = node.next;
152       node.next = storedNode;
153       storedNode.last = node;
154     } else {
155       first = last = storedNode;
156     }
157 
158     if(storedNode.next)
159       storedNode.next.last = storedNode;
160 
161     count++;
162     return storedNode;
163   }
164 
165   /**
166     * Tests if the list contains a node with the specified value
167     */
168   bool contains(T value)
169   {
170     foreach(Node!T node; this)
171       if(node.value == value)
172         return true;
173 
174     return false;
175   }
176 
177   /**
178     * Removes the first node with the specified value
179     */
180   void remove(T value)
181   {
182     foreach(Node!T node; this) {
183       if(node.value == value) {
184         node.remove();
185         break;
186       }
187     }
188   }
189 
190   /**
191     * Empties the LinkedList
192     */
193   void clear()
194   {
195     first = null;
196     last = null;
197     count = 0;
198   }
199 
200   int opApply(int delegate(ref Node!T result) dg)
201   {
202     int result = 0;
203 
204     for(Node!T node = first; node; node = node.next) {
205       result = dg(node);
206 
207       if(result)
208         break;
209     }
210 
211     return result;
212   }
213 
214   int opApply(int delegate(ref T result) dg)
215   {
216     int result = 0;
217 
218     for(Node!T node = first; node; node = node.next) {
219       T value = node.getValue();
220       result = dg(value);
221 
222       if(result)
223         break;
224     }
225 
226     return result;
227   }
228 }