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 }