1 module cogito.list;
2 
3 /**
4  * List range.
5  */
6 struct Range(T)
7 {
8     private Entry!T* entry;
9 
10     @disable this();
11 
12     private this(Entry!T* entry)
13     {
14         this.entry = entry;
15     }
16 
17     /**
18      * Returns: Whether the range is empty.
19      */
20     public bool empty() const
21     {
22         return this.entry is null;
23     }
24 
25     /**
26      * Returns: The front element.
27      */
28     public ref inout(T) front() inout
29     in(this.entry !is null)
30     {
31         return this.entry.element;
32     }
33 
34     /**
35      * Removes the front element of the range.
36      */
37     public void popFront()
38     in(this.entry !is null)
39     {
40         this.entry = this.entry.next;
41     }
42 }
43 
44 private struct Entry(T)
45 {
46     private T element;
47     private Entry!T* next;
48 }
49 
50 /**
51  * Queue that supports recursive data definitions.
52  */
53 struct List(T)
54 {
55     private Entry!T* first;
56     private Entry!T* last;
57 
58     invariant((this.first is null && this.last is null)
59         || (this.first !is null && this.last !is null));
60 
61     /**
62      * Appends $(D_PARAM element) to the list.
63      *
64      * Params:
65      *     element = The element to append.
66      */
67     void insert(T element)
68     {
69         auto entry = new Entry!T(element, null);
70 
71         if (this.first is null)
72         {
73             this.first = entry;
74         }
75         if (this.last is null)
76         {
77             this.last = entry;
78         }
79         else
80         {
81             this.last.next = entry;
82             this.last = entry;
83         }
84     }
85 
86     /**
87      * Remove the first element.
88      */
89     void removeFront()
90     in(!empty)
91     {
92         this.first = this.first.next;
93         if (this.first is null)
94         {
95             this.last = null;
96         }
97     }
98 
99     /**
100      * Returns: Whether this list is empty.
101      */
102     @property bool empty() const
103     {
104         return this.first is null;
105     }
106 
107     /**
108      * Returns: Head element.
109      */
110     @property ref inout(T) front() inout
111     in(!empty)
112     {
113         return this.first.element;
114     }
115 
116     /**
117      * Returns: Last element.
118      */
119     @property ref inout(T) back() inout
120     in(!empty)
121     {
122         return this.last.element;
123     }
124 
125     /**
126      * Returns: Range over this list.
127      */
128     Range!T opIndex()
129     {
130         return Range!T(this.first);
131     }
132 
133     /**
134      * Remove all elements.
135      */
136     void clear()
137     {
138         while (!empty)
139         {
140             removeFront();
141         }
142     }
143 }