Mercurial > projects > orange
view orange/util/collection/Array.d @ 27:fc315d786f24 experimental
Added unit testing.
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Fri, 19 Nov 2010 11:14:55 +0100 |
parents | 99c52d46822a |
children | 511d1ef4e299 |
line wrap: on
line source
/** * Copyright: Copyright (c) 2008-2009 Jacob Carlborg. All rights reserved. * Authors: Jacob Carlborg * Version: Initial created: 2008 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) * */ module orange.util.collection.Array; version (Tango) { static import tango.core.Array; import tango.stdc.string : memmove; static import tango.text.Util; } else { version = Phobos; import std.c.string : memmove; } import orange.core.string; import orange.util.Traits; /** * Inserts the specified element at the specified position in the array. Shifts the * element currently at that position (if any) and any subsequent elements to the right. * * Params: * arr = the array to insert the element into * index = the index at which the specified element is to be inserted * element = the element to be inserted * * Returns: the modified array * * Throws: AssertException if the length of the array is 0 * Throws: AssertException if the $(D_PARAM index) argument is * greater than the length of this array. */ T[] insert (T, U = size_t) (ref T[] arr, U index, T element) in { assert(arr.length > 0, "mambo.collection.Array.insert: The length of the array was 0"); assert(index <= arr.length, "mambo.collection.Array.insert: The index was greater than the length of the array"); } body { if (index == arr.length) { arr ~= element; return arr; } else if (index == 0) arr = element ~ arr; else arr = arr[0 .. index] ~ element ~ arr[index .. $]; return arr; } /** * Inserts the specified elements at the specified position in the array. Shifts the * element currently at that position (if any) and any subsequent elements to the right. * * Params: * arr = the array to insert the element into * index = the index at which the specified element is to be inserted * element = the element to be inserted * * Returns: the modified array * * Throws: AssertException if the length of the array is 0 * Throws: AssertException if the $(D_PARAM index) argument is * not less or equal than the length of this array. */ T[] insert (T, U = size_t) (ref T[] arr, U index, T[] element) in { assert(arr.length > 0, "mambo.collection.Array.insert: The length of the array was 0"); assert(index <= arr.length, "mambo.collection.Array.insert: The index was greater than the length of the array"); } body { if (index == arr.length) { arr ~= element; return arr; } else if (index == 0) arr = element ~ arr; else arr = arr[0 .. index] ~ element ~ arr[index .. $]; return arr; } /** * Inserts the specified element at the specified position in the array. Shifts the * element currently at that position (if any) and any subsequent elements to the right. * * Params: * arr = the array to add the element to * index = the index at which the specified element is to be inserted * element = the element to be inserted * * Returns: the modified array * * Throws: AssertException if the length of the array is 0 * Throws: AssertException if the $(D_PARAM index) argument is * not less than the length of this array. */ T[] add (T, U = size_t) (ref T[] arr, U index, T element) in { assert(arr.length > 0, "mambo.collection.Array.add: The length of the array was 0"); assert(index <= arr.length, "mambo.collection.Array.add: The index was greater than the length of the array"); } body { return insert(arr, index, element); } /** * Appends the specified element to the end of the array. * * Params: * arr = the array to add the element to * element = element to be appended to this list * * Returns: the modified array */ T[] add (T) (ref T[] arr, T element) { return arr ~= element; } /** * Removes the element at the specified position in the array if it could find it and * returns it. Shifts any subsequent elements to the left. * * Params: * arr = the array to remove the element from * index = the index of the element to be removed * * Returns: the element that was removed * * Throws: AssertException if the length of the array is 0 * Throws: AssertException if the $(D_PARAM index) argument is * not less than the length of this array. */ T remove (T, U = size_t) (ref T[] arr, U index) in { assert(arr.length > 0, "mambo.collection.Array.remove: The length of the array was 0"); assert(index < arr.length, "mambo.collection.Array.remove: The index was greater than the length of the array"); } body { T ret = arr[index]; if (index == 0) arr = arr[1 .. $]; else if (index == arr.length - 1) arr = arr[0 .. $ - 1]; else { if (index < arr.length - 1) memmove(&arr[index], &arr[index + 1], T.sizeof * (arr.length - index - 1)); arr.length = arr.length - 1; } return ret; } /** * Removes the specified element from the array if it could find it and returns it. * Shifts any subsequent elements to the left. * * Params: * arr = the array to remove the element from * element = the element to be removed * * Returns: the element that was removed or T.max * * Throws: AssertException if the length of the array is 0 */ T remove (T) (ref T[] arr, T element) in { assert(arr.length > 0, "mambo.collection.Array.remove: The length of the array was 0"); } out (result) { assert(result is element); } body { size_t index = arr.indexOf(element); if (index == size_t.max) return T.max; return arr.remove(index); } /** * Returns the index of the first occurrence of the specified element in the array, or * U.max if the array does not contain the element. * * Params: * arr = the array to get the index of the element from * element = the element to find * start = the index where to begin the search * * Returns: the index of the element or U.max if it's not in the array * * Throws: AssertException if the length of the array is 0 * Throws: AssertException if the return value is greater or * equal to the length of the array. */ U indexOf (T, U = size_t) (T[] arr, T element, U start = 0) in { assert(start >= 0, "mambo.collection.Array.indexOf: The start index was less than 0"); } body { version (Tango) { U index = tango.text.Util.locate(arr, element, start); if (index == arr.length) index = U.max; return index; } else { if (start > arr.length) start = arr.length; for (U i = start; i < arr.length; i++) if (arr[i] == element) return i; return U.max; } } /** * Returns $(D_KEYWORD true) if the array contains the specified element. * * Params: * arr = the array to check if it contains the element * element = the element whose presence in the array is to be tested * * Returns: $(D_KEYWORD true) if the array contains the specified element * * Throws: AssertException if the length of the array is 0 */ bool contains (T) (T[] arr, T element) in { assert(arr.length > 0, "mambo.collection.Array.contains: The length of the array was 0"); } body { return arr.indexOf!(T, size_t)(element) < size_t.max; } /** * Returns $(D_KEYWORD true) if the array contains the given pattern. * * Params: * arr = the array to check if it contains the element * pattern = the pattern whose presence in the array is to be tested * * Returns: $(D_KEYWORD true) if the array contains the given pattern */ bool contains (T) (T[] arr, T[] pattern) { static if (isChar!(T)) { version (Tango) return tango.text.Util.containsPattern(arr, pattern); else return stdString.indexOf(arr, element) != -1; } else { version (Tango) return tango.core.Array.contains(arr, pattern); else return !algorithm.find(arr, pattern).empty; } } /** * Returns $(D_KEYWORD true) if this array contains no elements. * * Params: * arr = the array to check if it's empty * * Returns: $(D_KEYWORD true) if this array contains no elements */ bool isEmpty (T) (T[] arr) { return arr.length == 0; } /** * Returns $(D_KEYWORD true) if this array contains no elements. * * Params: * arr = the array to check if it's empty * * Returns: $(D_KEYWORD true) if this array contains no elements */ alias isEmpty empty; /** * Removes all of the elements from this array. The array will be empty after this call * returns. * * Params: * arr = the array to clear * * Returns: the cleared array * * Throws: AssertException if length of the return array isn't 0 */ T[] clear (T) (T[] arr) out (result) { assert(result.length == 0, "mambo.collection.Array.clear: The length of the resulting array was not 0"); } body { return arr.length = 0; } /** * Returns the element at the specified position in the array. * * Params: * arr = the array to get the element from * index = index of the element to return * * Returns: the element at the specified position in the array * * Throws: AssertException if the length of the array is 0 * Throws: AssertException if the $(D_PARAM index) argument is * not less than the length of this array. */ T get (T, U = size_t) (T[] arr, U index) in { assert(arr.length > 0, "mambo.collection.Array.get: The length of the array was 0"); assert(index < arr.length, "mambo.collection.Array.get: The index was greater than the length of the array"); } body { return arr[index]; } /** * Returns the index of the last occurrence of the specifed element * * Params: * arr = the array to get the index of the element from * element = the element to find the index of * * Returns: the index of the last occurrence of the element in the * specified array, or U.max * if the element does not occur. * * Throws: AssertException if the length of the array is 0 * Throws: AssertException if the return value is less than -1 or * greater than the length of the array - 1. */ version (Tango) { U lastIndexOf (T, U = size_t) (in T[] arr, T element) in { assert(arr.length > 0, "mambo.collection.Array.lastIndexOf: The length of the array was 0"); } body { U index = tango.text.Util.locatePrior(arr, element); if (index == arr.length) return U.max; return index; } } else { U lastIndexOf (T, U = size_t) (in T[] arr, dchar element) in { assert(arr.length > 0, "mambo.collection.Array.lastIndexOf: The length of the array was 0"); } body { foreach_reverse (i, dchar e ; arr) if (e is element) return i; return U.max; } } /** * Returns the number of elements in the specified array. * * Params: * arr = the array to get the number of elements from * * Returns: the number of elements in this list */ U size (T, U = size_t) (T[] arr) { return arr.length; } /** * Finds the first occurence of element in arr * * Params: * arr = the array to find the element in * element = the element to find * start = at which position to start finding * * Returns: the index of the first match or U.max if no match was found. */ alias indexOf find; /** * Replaces a section of $(D_PARAM arr) with elements starting at $(D_PARAM pos) ending * $(D_PARAM n) elements after * * Params: * arr = the array to do the replace in * pos = position within the array of the first element of the section to be replaced * n = length of the section to be replaced within the array * elements = the elements to replace with * * Throws: * AssertException if pos is greater than the length of the array * * Returns: the array */ /*T[] replace (T, U = size_t) (ref T[] arr, U pos, U n, T[] elements) in { assert(pos <= arr.length, "mambo.collection.Array.replace: The position was greter than the length of the array"); } body { U i; U nr = n; if (nr > arr.length) nr = arr.length - 1; if (nr == elements.length) { U eIndex; for (i = pos, eIndex = 0; i <= nr; i++, eIndex++) arr[i] = elements[eIndex]; return arr; } else if (elements.length == 0) { U index = pos + n; if (index >= arr.length) index = arr.length; return arr = arr[0 .. pos] ~ arr[index .. $]; } else { U eIndex; for (i = pos, eIndex = 0; eIndex < nr && i < arr.length && eIndex < elements.length; i++, eIndex++) arr[i] = elements[eIndex]; // no positions left and elements are left in elements, insert elements if (eIndex < elements.length) return arr = arr[0 .. i] ~ elements[eIndex .. $] ~ arr[i .. $]; // positions left to replace but no elements, remove those positions else if (nr > eIndex) { U index = pos + nr; if (index >= arr.length) index = arr.length; return arr = arr[0 .. pos + eIndex] ~ arr[index .. $]; } } return arr; }*/ /** * Replaces all the occurences of $(D_PARAM pattern) with $(D_PARAM replacement) * * Params: * arr = the array to do the raplce in * pattern = the pattern to match * replacement = the values to subsitute * * Returns: the passed in array with all the patterns subsituted */ T[] replace (T : wchar) (T[] arr, dchar pattern, dchar replacement) { foreach (i, dchar e ; arr) if (e == pattern) arr[i] = replacement; return arr; } /** * Replaces all the occurences of $(D_PARAM pattern) with $(D_PARAM replacement) * * Params: * arr = the array to do the raplce in * pattern = the pattern to match * replacement = the values to subsitute * * Returns: the passed in array with all the patterns subsituted */ /*T[] replace (T) (T[] arr, T pattern, T replacement) { version (Tango) tango.core.Array.replace(arr, pattern, replacement); else { foreach (ref e ; arr) if (e == pattern) e = replacement; } return arr; }*/ /** * Erases a part of the array content, shortening the length of the array. * * Params: * arr = the array to erase elements from * start = the position within the array of the first element to be erased * n = amount of elements to be removed. It may remove less elements if the * end of the array is reached before the n elements have been erased. * The default value of n indicates that all the elements until the end * of the array should be erased. * * Throws: * AssertException if pos is greater than the length of the array * * Returns: the array */ T[] erase (T, U = size_t) (ref T[] arr, U start = 0, U n = U.max) in { assert(start <= arr.length, "mambo.collection.Array.erase: The start position was greater than the length of the array"); } body { U end; if (n == U.max) end = arr.length; else { end = start + n; if (end > arr.length) end = arr.length; } return arr = arr[0 .. start] ~ arr[end .. $]; } /** * Compares to arrays. Returns 0 if the content matches, less than zero * if a is "less" than b, or greater than zero where a is "bigger". * * Params: * a = the first array * b = the second array * end = the index where the comparision will end * * Returns: Returns 0 if the content matches, less than zero if a is * "less" than b, or greater than zero where a is "bigger". */ int compare (T, U = size_t) (T[] a, T[] b, U end = U.max) { U ia = end; U ib = end; if (ia > a.length) ia = a.length; if (ib > b.length) ib = b.length; return typeid(T[]).compare(&a[0 .. ia], &b[0 .. ib]); } /** * Compares the content of the given array to the content of a comparing * array, which is formed according to the arguments passed. * * The function returns 0 if all the elements in the compared contents compare * equal, a negative value if the first element that does not match compares to * less in the array than in the comparing array, and a positive value in * the opposite case. * * Params: * a = the first array to compare with * pos = position of the beginning of the compared slice, i.e. the first element in the array (in a) to be compared against the comparing array. * n = length of the compared slice. * b = array with the content to be used as comparing array. * * Returns: 0 if the compared array are equal, otherwise a number different from 0 is returned, with its sign indicating whether the array is considered greater than the comparing array passed as parameter (positive sign), or smaller (negative sign). * * Throws: AssertException if pos is specified with a position greater than the length of the corresponding array */ int compare (T, U = size_t) (T[] a, size_t pos, size_t n, T[] b) in { assert(pos <= b.length); } body { U end = pos + n; if (end > b.length) end = b.length; return typeid(T[]).compare(&b[pos .. end], &a[0 .. $]); } /** * Reserves the given amount of allocated storage for the given array. * * Params: * a = the array to reserve allocated storage for * capacity = the amount of allocated storage to be reserved */ void reserve (T) (ref T[] a, size_t amount = 0) { a = (new T[amount])[0 .. 0]; } /** * Returns true if a begins with b * * Params: * a = the array to * b = * * Returns: true if a begins with b, otherwise false */ bool beginsWith (T) (T[] a, T[] b) { return a.length > b.length && a[0 .. b.length] == b; } /** * Returns true if a ends with b * * Params: * a = the array to * b = * * Returns: true if a ends with b, otherwise false */ bool endsWith (T) (T[] a, T[] b) { return a.length > b.length && a[$ - b.length .. $] == b; }