| | 47 | |
|---|
| | 48 | /* |
|---|
| | 49 | Returns an array consisting of $(D elements). |
|---|
| | 50 | |
|---|
| | 51 | Example: |
|---|
| | 52 | |
|---|
| | 53 | ---- |
|---|
| | 54 | auto a = array(1, 2, 3); |
|---|
| | 55 | assert(is(typeof(a) == int[])); |
|---|
| | 56 | assert(a == [ 1, 2, 3 ]); |
|---|
| | 57 | auto b = array(1, 2.2, 3); |
|---|
| | 58 | assert(is(typeof(b) == double[])); |
|---|
| | 59 | assert(b == [ 1.0, 2.2, 3 ]); |
|---|
| | 60 | ---- |
|---|
| | 61 | */ |
|---|
| | 62 | // CommonType!(Ts)[] array(Ts...)(Ts elements) |
|---|
| | 63 | // { |
|---|
| | 64 | // alias CommonType!(Ts) E; |
|---|
| | 65 | // alias typeof(return) R; |
|---|
| | 66 | // // 1. Allocate untyped memory |
|---|
| | 67 | // auto result = cast(E*) enforce(std.gc.malloc(elements.length * R.sizeof), |
|---|
| | 68 | // text("Out of memory while allocating an array of ", |
|---|
| | 69 | // elements.length, " objects of type ", E.stringof)); |
|---|
| | 70 | // // 2. Initialize the memory |
|---|
| | 71 | // size_t constructedElements = 0; |
|---|
| | 72 | // scope(failure) |
|---|
| | 73 | // { |
|---|
| | 74 | // // Deconstruct only what was constructed |
|---|
| | 75 | // foreach_reverse (i; 0 .. constructedElements) |
|---|
| | 76 | // { |
|---|
| | 77 | // try |
|---|
| | 78 | // { |
|---|
| | 79 | // //result[i].~E(); |
|---|
| | 80 | // } |
|---|
| | 81 | // catch (Exception e) |
|---|
| | 82 | // { |
|---|
| | 83 | // } |
|---|
| | 84 | // } |
|---|
| | 85 | // // free the entire array |
|---|
| | 86 | // std.gc.realloc(result, 0); |
|---|
| | 87 | // } |
|---|
| | 88 | // foreach (src; elements) |
|---|
| | 89 | // { |
|---|
| | 90 | // static if (is(typeof(new(result + constructedElements) E(src)))) |
|---|
| | 91 | // { |
|---|
| | 92 | // new(result + constructedElements) E(src); |
|---|
| | 93 | // } |
|---|
| | 94 | // else |
|---|
| | 95 | // { |
|---|
| | 96 | // result[constructedElements] = src; |
|---|
| | 97 | // } |
|---|
| | 98 | // ++constructedElements; |
|---|
| | 99 | // } |
|---|
| | 100 | // // 3. Success constructing all elements, type the array and return it |
|---|
| | 101 | // setTypeInfo(typeid(E), result); |
|---|
| | 102 | // return result[0 .. constructedElements]; |
|---|
| | 103 | // } |
|---|
| | 104 | |
|---|
| | 105 | // unittest |
|---|
| | 106 | // { |
|---|
| | 107 | // auto a = array(1, 2, 3, 4, 5); |
|---|
| | 108 | // writeln(a); |
|---|
| | 109 | // assert(a == [ 1, 2, 3, 4, 5 ]); |
|---|
| | 110 | |
|---|
| | 111 | // struct S { int x; string toString() { return .toString(x); } } |
|---|
| | 112 | // auto b = array(S(1), S(2)); |
|---|
| | 113 | // writeln(b); |
|---|
| | 114 | |
|---|
| | 115 | // class C |
|---|
| | 116 | // { |
|---|
| | 117 | // int x; |
|---|
| | 118 | // this(int y) { x = y; } |
|---|
| | 119 | // string toString() { return .toString(x); } |
|---|
| | 120 | // } |
|---|
| | 121 | // auto c = array(new C(1), new C(2)); |
|---|
| | 122 | // writeln(c); |
|---|
| | 123 | |
|---|
| | 124 | // auto d = array(1, 2.2, 3); |
|---|
| | 125 | // assert(is(typeof(d) == double[])); |
|---|
| | 126 | // writeln(d); |
|---|
| | 127 | // } |
|---|
| | 128 | |
|---|
| | 129 | template IndexType(C : T[], T) |
|---|
| | 130 | { |
|---|
| | 131 | alias size_t IndexType; |
|---|
| | 132 | } |
|---|
| | 133 | |
|---|
| | 134 | unittest |
|---|
| | 135 | { |
|---|
| | 136 | static assert(is(IndexType!(double[]) == size_t)); |
|---|
| | 137 | static assert(!is(IndexType!(double) == size_t)); |
|---|
| | 138 | } |
|---|
| | 139 | |
|---|
| | 140 | /** |
|---|
| | 141 | Inserts $(D stuff) in $(D container) at position $(D pos). |
|---|
| | 142 | */ |
|---|
| | 143 | void insert(T, Range)(ref T[] array, size_t pos, Range stuff) |
|---|
| | 144 | { |
|---|
| | 145 | static if (is(typeof(stuff[0]))) |
|---|
| | 146 | { |
|---|
| | 147 | // presumably an array |
|---|
| | 148 | alias stuff toInsert; |
|---|
| | 149 | assert(!overlap(array, toInsert)); |
|---|
| | 150 | } |
|---|
| | 151 | else |
|---|
| | 152 | { |
|---|
| | 153 | // presumably only one element |
|---|
| | 154 | auto toInsert = (&stuff)[0 .. 1]; |
|---|
| | 155 | } |
|---|
| | 156 | |
|---|
| | 157 | // @@@BUG 2130@@@ |
|---|
| | 158 | // invariant |
|---|
| | 159 | // size_t delta = toInsert.length, |
|---|
| | 160 | // size_t oldLength = array.length, |
|---|
| | 161 | // size_t newLength = oldLength + delta; |
|---|
| | 162 | invariant |
|---|
| | 163 | delta = toInsert.length, |
|---|
| | 164 | oldLength = array.length, |
|---|
| | 165 | newLength = oldLength + delta; |
|---|
| | 166 | |
|---|
| | 167 | // Reallocate the array to make space for new content |
|---|
| | 168 | array = cast(T[]) realloc(array.ptr, newLength * array[0].sizeof); |
|---|
| | 169 | assert(array.length == newLength); |
|---|
| | 170 | |
|---|
| | 171 | // Move data in pos .. pos + stuff.length to the end of the array |
|---|
| | 172 | foreach_reverse (i; pos .. oldLength) |
|---|
| | 173 | { |
|---|
| | 174 | // This will be guaranteed to not throw |
|---|
| | 175 | move(array[i], array[i + delta]); |
|---|
| | 176 | } |
|---|
| | 177 | |
|---|
| | 178 | // Copy stuff into array |
|---|
| | 179 | foreach (e; toInsert) |
|---|
| | 180 | { |
|---|
| | 181 | array[pos++] = e; |
|---|
| | 182 | } |
|---|
| | 183 | } |
|---|
| | 184 | |
|---|
| | 185 | unittest |
|---|
| | 186 | { |
|---|
| | 187 | int[] a = ([1, 4, 5]).dup; |
|---|
| | 188 | insert(a, 1u, [2, 3]); |
|---|
| | 189 | assert(a == [1, 2, 3, 4, 5]); |
|---|
| | 190 | insert(a, 1u, 99); |
|---|
| | 191 | assert(a == [1, 99, 2, 3, 4, 5]); |
|---|
| | 192 | } |
|---|
| | 193 | |
|---|
| | 194 | /** |
|---|
| | 195 | Erases elements from $(D array) with indices ranging from $(D from) |
|---|
| | 196 | (inclusive) to $(D to) (exclusive). |
|---|
| | 197 | */ |
|---|
| | 198 | void erase(T)(ref T[] array, size_t from, size_t to) |
|---|
| | 199 | { |
|---|
| | 200 | invariant newLength = array.length - (to - from); |
|---|
| | 201 | foreach (i; to .. array.length) |
|---|
| | 202 | { |
|---|
| | 203 | move(array[i], array[from++]); |
|---|
| | 204 | } |
|---|
| | 205 | array.length = newLength; |
|---|
| | 206 | } |
|---|
| | 207 | |
|---|
| | 208 | unittest |
|---|
| | 209 | { |
|---|
| | 210 | int[] a = [1, 2, 3, 4, 5]; |
|---|
| | 211 | erase(a, 1u, 3u); |
|---|
| | 212 | assert(a == [1, 4, 5]); |
|---|
| | 213 | } |
|---|
| | 214 | |
|---|
| | 215 | /** |
|---|
| | 216 | Replaces elements from $(D array) with indices ranging from $(D from) |
|---|
| | 217 | (inclusive) to $(D to) (exclusive) with the range $(D stuff). Expands |
|---|
| | 218 | or shrinks the array as needed. |
|---|
| | 219 | */ |
|---|
| | 220 | void replace(T, Range)(ref T[] array, size_t from, size_t to, |
|---|
| | 221 | Range stuff) |
|---|
| | 222 | { |
|---|
| | 223 | // container = container[0 .. from] ~ stuff ~ container[to .. $]; |
|---|
| | 224 | if (overlap(array, stuff)) |
|---|
| | 225 | { |
|---|
| | 226 | // use slower/conservative method |
|---|
| | 227 | array = array[0 .. from] ~ stuff ~ array[to .. $]; |
|---|
| | 228 | } |
|---|
| | 229 | else if (stuff.length <= to - from) |
|---|
| | 230 | { |
|---|
| | 231 | // replacement reduces length |
|---|
| | 232 | // BUG 2128 |
|---|
| | 233 | //invariant stuffEnd = from + stuff.length; |
|---|
| | 234 | auto stuffEnd = from + stuff.length; |
|---|
| | 235 | array[from .. stuffEnd] = stuff; |
|---|
| | 236 | erase(array, stuffEnd, to); |
|---|
| | 237 | } |
|---|
| | 238 | else |
|---|
| | 239 | { |
|---|
| | 240 | // replacement increases length |
|---|
| | 241 | // @@@TODO@@@: optimize this |
|---|
| | 242 | invariant replaceLen = to - from; |
|---|
| | 243 | array[from .. to] = stuff[0 .. replaceLen]; |
|---|
| | 244 | insert(array, to, stuff[replaceLen .. $]); |
|---|
| | 245 | } |
|---|
| | 246 | } |
|---|
| | 247 | |
|---|
| | 248 | unittest |
|---|
| | 249 | { |
|---|
| | 250 | int[] a = [1, 4, 5]; |
|---|
| | 251 | replace(a, 1u, 2u, [2, 3, 4]); |
|---|
| | 252 | assert(a == [1, 2, 3, 4, 5]); |
|---|
| | 253 | } |
|---|
| | 254 | |
|---|