1 /* 2 Boost Software License - Version 1.0 - August 17th, 2003 3 4 Copyright (c) 2019 Clipsey 5 6 Permission is hereby granted, free of charge, to any person or organization 7 obtaining a copy of the software and accompanying documentation covered by 8 this license (the "Software") to use, reproduce, display, distribute, 9 execute, and transmit the Software, and to prepare derivative works of the 10 Software, and to permit third-parties to whom the Software is furnished to 11 do so, all subject to the following: 12 13 The copyright notices in the Software and this entire statement, including 14 the above license grant, this restriction and the following disclaimer, 15 must be included in all copies of the Software, in whole or in part, and 16 all derivative works of the Software, unless such copies or derivative 17 works are solely in the form of machine-executable object code generated by 18 a source language processor. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 DEALINGS IN THE SOFTWARE. 27 */ 28 module containers.list; 29 30 /** 31 An array-based list implementation 32 */ 33 struct List(T) { 34 private: 35 T[] data; 36 37 /// front element id 38 size_t frontElm; 39 40 public: 41 /// Constructs a list of specified length 42 this(size_t length) { 43 data = new T[](length); 44 } 45 46 /// Constructs a list with specified data 47 this(T[] data) { 48 this.data = data; 49 } 50 51 /// Constructs a list with specified data 52 this(List!T data) { 53 this.data = data.toArray; 54 } 55 56 /// Assignment overload for list 57 void opAssign(T rhs) { 58 this.data = [rhs]; 59 } 60 61 /// Assignment overload for list 62 void opAssign(T[] rhs) { 63 this.data = rhs; 64 } 65 66 /// Assignment overload for list at index 67 T opIndexAssign(T value, size_t index) { 68 data[index] = value; 69 return value; 70 } 71 72 /// Assignment overload for list append 73 T opOpAssign(string op = "~")(T value) { 74 add(value); 75 return value; 76 } 77 78 /// Assignment overload for list append 79 T opOpAssign(string op = "~")(T[] value) { 80 addRange(value); 81 return value; 82 } 83 84 /// Assignment overload for list append 85 T opOpAssign(string op = "~")(List!T value) { 86 addRange(value); 87 return value; 88 } 89 90 /// Index overload for list 91 T opIndex(size_t index) { 92 return data[index]; 93 } 94 95 int opApply(int delegate(ref T) operations) { 96 int result = 0; 97 98 for (size_t i = 0; i < data.length; ++i) { 99 result = operations(data[i]); 100 101 if (result) break; 102 } 103 104 return result; 105 } 106 107 int opApply(int delegate(ref size_t, ref T) operations) { 108 int result = 0; 109 110 for (size_t i = 0; i < data.length; ++i) { 111 result = operations(i, data[i]); 112 113 if (result) break; 114 } 115 116 return result; 117 } 118 119 int opApplyReverse(int delegate(ref T) operations) { 120 int result = 0; 121 122 for (ptrdiff_t i = data.length-1; i >= 0; i--) { 123 result = operations(data[i]); 124 125 if (result) break; 126 } 127 128 return result; 129 } 130 131 int opApplyReverse(int delegate(ref ptrdiff_t, ref T) operations) { 132 int result = 0; 133 134 for (ptrdiff_t i = data.length-1; i >= 0; i--) { 135 result = operations(i, data[i]); 136 137 if (result) break; 138 } 139 140 return result; 141 } 142 143 /// Returns the count of items in the list 144 @property size_t count() { 145 return data.length; 146 } 147 148 /// Returns wether the list is empty (has no items) 149 bool empty() { 150 return data.length != 0; 151 } 152 153 /// Add item to list 154 void add(T item) { 155 data ~= item; 156 } 157 158 /// Add range of items to list 159 void addRange(List!T items) { 160 data ~= items.toArray(); 161 } 162 163 /// Add range of items to list 164 void addRange(T[] items) { 165 data ~= items; 166 } 167 168 /// Clears the list 169 void clear() { 170 data = []; 171 } 172 173 /// Returns true if the list contains the item 174 bool contains(T item) { 175 foreach(srch; data) { 176 if (srch == item) return true; 177 } 178 return false; 179 } 180 181 /// copy elements (starting from start) to array. 182 void copyTo(T[] arr, size_t start) { 183 arr[start..start+count()] = data; 184 } 185 186 /++ 187 Returns the index of the first occurence of value. 188 Returns -1 if nothing was found 189 +/ 190 ptrdiff_t indexOf(T item) { 191 foreach(i, srch; data) { 192 if (srch == item) return i; 193 } 194 return -1; 195 } 196 197 /++ 198 Returns the index of the last occurence of value. 199 Returns -1 if nothing was found 200 +/ 201 ptrdiff_t lastIndexOf(T item) { 202 foreach_reverse(i, srch; data) { 203 if (srch == item) return i; 204 } 205 return -1; 206 } 207 208 /// Inserts item in to list at index 209 void insert(size_t index, T item) { 210 data.length++; 211 // First, move stuff 1 step ahead 212 data[index+1..$] = data[index+1..$-1]; 213 214 // Then insert the item 215 data[index] = item; 216 } 217 218 /// Inserts item range in to list at index 219 void insertRange(size_t index, List!T items) { 220 insertRange(index, items.toArray); 221 } 222 223 /// Inserts item range in to list at index 224 void insertRange(size_t index, T[] items) { 225 data.length += items.length; 226 227 // First, move stuff x steps ahead 228 data[index+items.length..$] = data[index+items.length..$-1]; 229 230 // Then insert the item range 231 data[index..index+items.length] = items[0..items.length]; 232 } 233 234 /// Remove item from list 235 void remove(T item) { 236 // Get the index 237 size_t index = indexOf(item); 238 removeAt(index); 239 } 240 241 /// Removes the element at index from the list 242 void removeAt(size_t index) { 243 // Slice it outta there. 244 data = data[0..index] ~ data[index+1..$]; 245 } 246 247 /// Removes a range of items from the list 248 void removeRange(size_t index, size_t count) { 249 size_t end = index+count; 250 251 // Slice it outta there. 252 data = data[0..index] ~ data[end..$]; 253 } 254 255 /// Reverses the contents of the list 256 void reverse() { 257 /// Store the old state temporarily. 258 T[] tmp = toArray(); 259 foreach_reverse(i, srch; tmp) { 260 data[(data.length-1)-i] = srch; 261 } 262 } 263 264 /// Returns a copy of the internal data of the list as an array 265 T[] toArray() { 266 T[] output = new T[](data.length); 267 /// Make a copy, by making the LEFT HAND side a slice. 268 output[] = data; 269 return output; 270 } 271 272 /// Gets string representation of list 273 string toString() { 274 import std.conv : text; 275 return data.text; 276 } 277 }