1 /** 2 * Copyright: Copyright (c) 2008-2009 Jacob Carlborg. All rights reserved. 3 * Authors: Jacob Carlborg 4 * Version: Initial created: 2008 5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 * 7 */ 8 module mambo.core.Array; 9 10 import stdArray = std.array; 11 import algorithm = std.algorithm; 12 import stdRange = std.range; 13 import stdString = std.string; 14 15 static import tango.core.Array; 16 import tango.stdc.string : memmove; 17 static import tango.text.Util; 18 19 import mambo.core.AssociativeArray; 20 import mambo.core.core; 21 import mambo.util.Traits; 22 23 alias stdArray.array toArray; 24 alias algorithm.canFind contains; 25 alias algorithm.count count; 26 alias algorithm.countUntil indexOf; 27 alias algorithm.filter filter; 28 alias stdArray.join join; 29 alias algorithm.sort sort; 30 alias algorithm.startsWith startsWith; 31 alias algorithm.uniq unique; 32 33 alias stdRange.chain append; 34 alias stdArray.split split; 35 36 /** 37 * Inserts the given element(s) or range at the given position into the array. Shifts the 38 * element currently at that position (if any) and any subsequent elements to the right. 39 * 40 * Params: 41 * arr = the array to insert the element(s) or range into 42 * index = the index at which the specified element(s) or range is to be inserted to 43 * r = the element(s) or range to be inserted 44 * 45 * Returns: a copy of the given array with the element(s) or range inserted 46 */ 47 T[] insert (T, RangeOrElement...) (T[] arr, size_t index, RangeOrElement r) 48 { 49 auto copy = arr.dup; 50 stdArray.insertInPlace(copy, index, r); 51 return copy; 52 } 53 54 /** 55 * Inserts the given element(s) or range, in place, at the given position into the array. 56 * Shifts the element currently at that position (if any) and any subsequent elements to the 57 * right. 58 * 59 * This will modify the given array in place. 60 * 61 * Params: 62 * arr = the array to insert the element(s) or range into 63 * index = the index at which the specified element(s) or range is to be inserted to 64 * r = the element(s) or range to be inserted 65 * 66 * Returns: the modified array with the element(s) or range inserted 67 */ 68 T[] insertInPlace (T, RangeOrElement...) (ref T[] arr, size_t index, RangeOrElement r) 69 { 70 stdArray.insertInPlace(arr, index, r); 71 return arr; 72 } 73 74 /** 75 * Removes the given elements from the given array. 76 * 77 * Params: 78 * arr = the array to remove the elements from 79 * elements = the elements to be removed 80 * 81 * Returns: the array with the elements removed 82 */ 83 T[] remove (T) (T[] arr, T[] elements ...) 84 { 85 return algorithm.remove!((e) => elements.contains(e))(arr); 86 } 87 88 /** 89 * Removes the elements with the given indexes from the given range. 90 * 91 * Params: 92 * range = the range to remove the elements from 93 * indexes = the index of the elements to be remove 94 * 95 * Returns: the range with the indexes removed 96 */ 97 Range remove (Range, Index ...) (Range range, Index indexes) 98 { 99 return algorithm.remove(range, indexes); 100 } 101 102 /** 103 * Returns $(D_KEYWORD true) if this array contains no elements. 104 * 105 * Params: 106 * arr = the array to check if it's empty 107 * 108 * Returns: $(D_KEYWORD true) if this array contains no elements 109 */ 110 @property bool isEmpty (T) (T arr) 111 if (__traits(compiles, { auto a = arr.length; }) || 112 __traits(compiles, { bool b = arr.empty; })) 113 { 114 static if (__traits(compiles, { auto a = arr.length; })) 115 return arr.length == 0; 116 117 else 118 return arr.empty; 119 } 120 121 /** 122 * Removes all of the elements from this array. The array will be empty after this call 123 * returns. 124 * 125 * Params: 126 * arr = the array to clear 127 * 128 * Returns: the cleared array 129 * 130 * Throws: AssertException if length of the return array isn't 0 131 */ 132 T[] clear (T) (ref T[] arr) 133 out (result) 134 { 135 assert(result.length == 0, "mambo.collection.Array.clear: The length of the resulting array was not 0"); 136 } 137 body 138 { 139 arr.length = 0; 140 return arr; 141 } 142 143 /** 144 * Returns the index of the last occurrence of the specifed element 145 * 146 * Params: 147 * arr = the array to get the index of the element from 148 * element = the element to find the index of 149 * 150 * Returns: the index of the last occurrence of the element in the 151 * specified array, or U.max 152 * if the element does not occur. 153 * 154 * Throws: AssertException if the length of the array is 0 155 * Throws: AssertException if the return value is less than -1 or 156 * greater than the length of the array - 1. 157 */ 158 U lastIndexOf (T, U = size_t) (in T[] arr, T element) 159 in 160 { 161 assert(arr.length > 0, "mambo.collection.Array.lastIndexOf: The length of the array was 0"); 162 } 163 body 164 { 165 U index = tango.text.Util.locatePrior(arr, element); 166 167 if (index == arr.length) 168 return U.max; 169 170 return index; 171 } 172 173 /** 174 * Returns true if a begins with b 175 * 176 * Params: 177 * a = the array to 178 * b = 179 * 180 * Returns: true if a begins with b, otherwise false 181 */ 182 bool beginsWith (T) (T[] a, T[] b) 183 { 184 return a.length > b.length && a[0 .. b.length] == b; 185 } 186 187 /** 188 * Returns true if a ends with b 189 * 190 * Params: 191 * a = the array to 192 * b = 193 * 194 * Returns: true if a ends with b, otherwise false 195 */ 196 bool endsWith (T) (T[] a, T[] b) 197 { 198 return a.length > b.length && a[$ - b.length .. $] == b; 199 } 200 201 /** 202 * Repests $(D_PARAM arr) $(D_PARAM number) of times. 203 * 204 * Params: 205 * arr = the array to repeat 206 * number = the number of times to repeat 207 * 208 * Returns: a new array containing $(D_PARAM arr) $(D_PARAM number) of times 209 */ 210 T[] repeat (T) (T[] arr, size_t number) 211 { 212 T[] result; 213 result.reserve(arr.length * number); 214 215 foreach (_ ; 0 .. number) 216 result ~= arr; 217 218 return result; 219 } 220 221 /** 222 * Returns $(D_KEYWORD true) if this array contains any elements. 223 * 224 * Params: 225 * arr = the array to check if it contains elements 226 * 227 * Returns: $(D_KEYWORD true) if this array contains elements 228 */ 229 @property bool any (T) (T arr) if (__traits(compiles, { bool a = arr.isEmpty; })) 230 { 231 return !arr.isEmpty; 232 } 233 234 bool any (alias predicate, Range) (Range range) 235 { 236 static if (isAssociativeArray!(Range)) 237 return _anyAA!(predicate)(range); 238 239 else 240 return algorithm.any!(predicate)(range); 241 } 242 243 /// Returns the first element of the given array. 244 @property auto first (T) (T[] arr) 245 { 246 return stdArray.front(arr); 247 } 248 249 /// Returns the first element of the given array. 250 @property auto last (T) (T[] arr) 251 { 252 return stdArray.back(arr); 253 } 254 255 /// Strips all the trailing delimiters from the given array. 256 T[] strip (T, C) (T[] arr, C delimiter) 257 { 258 if (arr.isEmpty) 259 return arr; 260 261 auto a = arr; 262 auto del = [delimiter]; 263 264 while (a.last == delimiter) 265 a = stdString.chomp(a, del); 266 267 return a; 268 } 269 270 auto find (alias predicate, Range) (Range range) 271 { 272 static if (isAssociativeArray!(Range)) 273 return _findAA!(predicate)(range); 274 275 else 276 return algorithm.find!(predicate)(range); 277 } 278 279 auto reduce (alias func, Range) (Range range) 280 { 281 return algorithm.reduce!(func)(range); 282 } 283 284 auto reduce (alias func, Range, Seed) (Range range, Seed seed) 285 { 286 return algorithm.reduce!(func)(seed, range); 287 } 288 289 auto reduce (alias seed, alias func, Range) (Range range) 290 { 291 return algorithm.reduce!(func)(seed, range); 292 } 293 294 auto map (alias func, Range) (Range range) 295 { 296 static if (isAssociativeArray!(Range)) 297 return _mapAA!(func)(range); 298 299 else 300 return algorithm.map!(func)(range); 301 } 302 303 inout(T)[] assumeUnique (T) (ref T[] source, ref inout(T)[] destination) 304 { 305 destination = cast(inout(T)[]) source; 306 source = null; 307 308 return destination; 309 } 310 311 immutable(T)[] assumeUnique (T) (ref const(T)[] array) 312 { 313 auto result = cast(immutable(T)[]) array; 314 array = null; 315 316 return result; 317 } 318 319 immutable(T)[] assumeUnique (T) (const(T)[] array) 320 { 321 return array.assumeUnique; 322 } 323 324 T[] toMutable (T) (const(T)[] array) 325 { 326 return cast(T[]) array; 327 }