Mercurial > projects > dstep
comparison dstep/internal/collection/Array.d @ 16:19885b43130e
Huge update, the bridge actually works now
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Sun, 03 Jan 2010 22:06:11 +0100 |
parents | 033d260cfc9b |
children |
comparison
equal
deleted
inserted
replaced
15:7ff919f595d5 | 16:19885b43130e |
---|---|
4 * Version: Initial created: 2008 | 4 * Version: Initial created: 2008 |
5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) | 5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) |
6 */ | 6 */ |
7 module dstep.internal.collection.Array; | 7 module dstep.internal.collection.Array; |
8 | 8 |
9 public import mambo.collection.Array; | 9 version (Tango) |
10 { | |
11 static import tango.core.Array; | |
12 import tango.stdc.string : memmove; | |
13 static import tango.text.Util; | |
14 } | |
15 | |
16 else | |
17 { | |
18 version = Phobos; | |
19 | |
20 import std.c.string : memmove; | |
21 } | |
22 | |
23 /** | |
24 * Inserts the specified element at the specified position in the array. Shifts the | |
25 * element currently at that position (if any) and any subsequent elements to the right. | |
26 * | |
27 * Params: | |
28 * arr = the array to insert the element into | |
29 * index = the index at which the specified element is to be inserted | |
30 * element = the element to be inserted | |
31 * | |
32 * Returns: the modified array | |
33 * | |
34 * Throws: AssertException if the length of the array is 0 | |
35 * Throws: AssertException if the $(D_PARAM index) argument is | |
36 * greater than the length of this array. | |
37 */ | |
38 T[] insert (T, U = size_t) (ref T[] arr, U index, T element) | |
39 in | |
40 { | |
41 assert(arr.length > 0, "dstep.internal.collection.Array.insert: The length of the array was 0"); | |
42 assert(index <= arr.length, "dstep.internal.collection.Array.insert: The index was greater than the length of the array"); | |
43 } | |
44 body | |
45 { | |
46 if (index == arr.length) | |
47 { | |
48 arr ~= element; | |
49 return arr; | |
50 } | |
51 | |
52 else if (index == 0) | |
53 arr = element ~ arr; | |
54 | |
55 else | |
56 arr = arr[0 .. index] ~ element ~ arr[index .. $]; | |
57 | |
58 return arr; | |
59 } | |
60 | |
61 /** | |
62 * Inserts the specified elements at the specified position in the array. Shifts the | |
63 * element currently at that position (if any) and any subsequent elements to the right. | |
64 * | |
65 * Params: | |
66 * arr = the array to insert the element into | |
67 * index = the index at which the specified element is to be inserted | |
68 * element = the element to be inserted | |
69 * | |
70 * Returns: the modified array | |
71 * | |
72 * Throws: AssertException if the length of the array is 0 | |
73 * Throws: AssertException if the $(D_PARAM index) argument is | |
74 * not less or equal than the length of this array. | |
75 */ | |
76 T[] insert (T, U = size_t) (ref T[] arr, U index, T[] element) | |
77 in | |
78 { | |
79 assert(arr.length > 0, "dstep.internal.collection.Array.insert: The length of the array was 0"); | |
80 assert(index <= arr.length, "dstep.internal.collection.Array.insert: The index was greater than the length of the array"); | |
81 } | |
82 body | |
83 { | |
84 if (index == arr.length) | |
85 { | |
86 arr ~= element; | |
87 return arr; | |
88 } | |
89 | |
90 else if (index == 0) | |
91 arr = element ~ arr; | |
92 | |
93 else | |
94 arr = arr[0 .. index] ~ element ~ arr[index .. $]; | |
95 | |
96 return arr; | |
97 } | |
98 | |
99 /** | |
100 * Inserts the specified element at the specified position in the array. Shifts the | |
101 * element currently at that position (if any) and any subsequent elements to the right. | |
102 * | |
103 * Params: | |
104 * arr = the array to add the element to | |
105 * index = the index at which the specified element is to be inserted | |
106 * element = the element to be inserted | |
107 * | |
108 * Returns: the modified array | |
109 * | |
110 * Throws: AssertException if the length of the array is 0 | |
111 * Throws: AssertException if the $(D_PARAM index) argument is | |
112 * not less than the length of this array. | |
113 */ | |
114 T[] add (T, U = size_t) (ref T[] arr, U index, T element) | |
115 in | |
116 { | |
117 assert(arr.length > 0, "dstep.internal.collection.Array.add: The length of the array was 0"); | |
118 assert(index <= arr.length, "dstep.internal.collection.Array.add: The index was greater than the length of the array"); | |
119 } | |
120 body | |
121 { | |
122 return insert(arr, index, element); | |
123 } | |
124 | |
125 /** | |
126 * Appends the specified element to the end of the array. | |
127 * | |
128 * Params: | |
129 * arr = the array to add the element to | |
130 * element = element to be appended to this list | |
131 * | |
132 * Returns: the modified array | |
133 */ | |
134 T[] add (T) (ref T[] arr, T element) | |
135 { | |
136 return arr ~= element; | |
137 } | |
138 | |
139 /** | |
140 * Removes the element at the specified position in the array if it could find it and | |
141 * returns it. Shifts any subsequent elements to the left. | |
142 * | |
143 * Params: | |
144 * arr = the array to remove the element from | |
145 * index = the index of the element to be removed | |
146 * | |
147 * Returns: the element that was removed | |
148 * | |
149 * Throws: AssertException if the length of the array is 0 | |
150 * Throws: AssertException if the $(D_PARAM index) argument is | |
151 * not less than the length of this array. | |
152 */ | |
153 T remove (T, U = size_t) (ref T[] arr, U index) | |
154 in | |
155 { | |
156 assert(arr.length > 0, "dstep.internal.collection.Array.remove: The length of the array was 0"); | |
157 assert(index < arr.length, "dstep.internal.collection.Array.remove: The index was greater than the length of the array"); | |
158 } | |
159 body | |
160 { | |
161 T ret = arr[index]; | |
162 | |
163 if (index == 0) | |
164 arr = arr[1 .. $]; | |
165 | |
166 else if (index == arr.length - 1) | |
167 arr = arr[0 .. $ - 1]; | |
168 | |
169 else | |
170 { | |
171 if (index < arr.length - 1) | |
172 memmove(&arr[index], &arr[index + 1], T.sizeof * (arr.length - index - 1)); | |
173 | |
174 arr.length = arr.length - 1; | |
175 } | |
176 | |
177 return ret; | |
178 } | |
179 | |
180 /** | |
181 * Removes the specified element from the array if it could find it and returns it. | |
182 * Shifts any subsequent elements to the left. | |
183 * | |
184 * Params: | |
185 * arr = the array to remove the element from | |
186 * element = the element to be removed | |
187 * | |
188 * Returns: the element that was removed or T.max | |
189 * | |
190 * Throws: AssertException if the length of the array is 0 | |
191 */ | |
192 T remove (T) (ref T[] arr, T element) | |
193 in | |
194 { | |
195 assert(arr.length > 0, "dstep.internal.collection.Array.remove: The length of the array was 0"); | |
196 } | |
197 out (result) | |
198 { | |
199 assert(result is element); | |
200 } | |
201 body | |
202 { | |
203 size_t index = arr.indexOf(element); | |
204 | |
205 if (index == size_t.max) | |
206 return T.max; | |
207 | |
208 return arr.remove(index); | |
209 } | |
210 | |
211 /** | |
212 * Returns the index of the first occurrence of the specified element in the array, or | |
213 * U.max if the array does not contain the element. | |
214 * | |
215 * Params: | |
216 * arr = the array to get the index of the element from | |
217 * element = the element to find | |
218 * start = the index where to begin the search | |
219 * | |
220 * Returns: the index of the element or U.max if it's not in the array | |
221 * | |
222 * Throws: AssertException if the length of the array is 0 | |
223 * Throws: AssertException if the return value is greater or | |
224 * equal to the length of the array. | |
225 */ | |
226 U indexOf (T, U = size_t) (T[] arr, T element, U start = 0) | |
227 in | |
228 { | |
229 assert(arr.length > 0, "dstep.internal.collection.Array.indexOf: The length of the array was 0"); | |
230 assert(start >= 0, "dstep.internal.collection.Array.indexOf: The start index was less than 0"); | |
231 } | |
232 body | |
233 { | |
234 version (Tango) | |
235 { | |
236 U index = tango.text.Util.locate(arr, element, start); | |
237 | |
238 if (index == arr.length) | |
239 index = U.max; | |
240 | |
241 return index; | |
242 } | |
243 | |
244 else | |
245 { | |
246 if (start > arr.length) | |
247 start = arr.length; | |
248 | |
249 for (U i = start; i < arr.length; i++) | |
250 if (arr[i] == element) | |
251 return i; | |
252 | |
253 return U.max; | |
254 } | |
255 } | |
256 | |
257 /** | |
258 * Returns $(D_KEYWORD true) if the array contains the specified element. | |
259 * | |
260 * Params: | |
261 * arr = the array to check if it contains the element | |
262 * element = the element whose presence in the array is to be tested | |
263 * | |
264 * Returns: $(D_KEYWORD true) if the array contains the specified element | |
265 * | |
266 * Throws: AssertException if the length of the array is 0 | |
267 */ | |
268 bool contains (T) (T[] arr, T element) | |
269 in | |
270 { | |
271 assert(arr.length > 0, "dstep.internal.collection.Array.contains: The length of the array was 0"); | |
272 } | |
273 body | |
274 { | |
275 return arr.indexOf!(T, size_t)(element) < size_t.max; | |
276 } | |
277 | |
278 /** | |
279 * Returns $(D_KEYWORD true) if this array contains no elements. | |
280 * | |
281 * Params: | |
282 * arr = the array to check if it's empty | |
283 * | |
284 * Returns: $(D_KEYWORD true) if this array contains no elements | |
285 */ | |
286 bool isEmpty (T) (T[] arr) | |
287 { | |
288 return arr.length == 0; | |
289 } | |
290 | |
291 /** | |
292 * Returns $(D_KEYWORD true) if this array contains no elements. | |
293 * | |
294 * Params: | |
295 * arr = the array to check if it's empty | |
296 * | |
297 * Returns: $(D_KEYWORD true) if this array contains no elements | |
298 */ | |
299 alias isEmpty empty; | |
300 | |
301 /** | |
302 * Removes all of the elements from this array. The array will be empty after this call | |
303 * returns. | |
304 * | |
305 * Params: | |
306 * arr = the array to clear | |
307 * | |
308 * Returns: the cleared array | |
309 * | |
310 * Throws: AssertException if length of the return array isn't 0 | |
311 */ | |
312 T[] clear (T) (T[] arr) | |
313 out (result) | |
314 { | |
315 assert(result.length == 0, "dstep.internal.collection.Array.clear: The length of the resulting array was not 0"); | |
316 } | |
317 body | |
318 { | |
319 return arr.length = 0; | |
320 } | |
321 | |
322 /** | |
323 * Returns the element at the specified position in the array. | |
324 * | |
325 * Params: | |
326 * arr = the array to get the element from | |
327 * index = index of the element to return | |
328 * | |
329 * Returns: the element at the specified position in the array | |
330 * | |
331 * Throws: AssertException if the length of the array is 0 | |
332 * Throws: AssertException if the $(D_PARAM index) argument is | |
333 * not less than the length of this array. | |
334 */ | |
335 T get (T, U = size_t) (T[] arr, U index) | |
336 in | |
337 { | |
338 assert(arr.length > 0, "dstep.internal.collection.Array.get: The length of the array was 0"); | |
339 assert(index < arr.length, "dstep.internal.collection.Array.get: The index was greater than the length of the array"); | |
340 } | |
341 body | |
342 { | |
343 return arr[index]; | |
344 } | |
345 | |
346 /** | |
347 * Returns the index of the last occurrence of the specifed element | |
348 * | |
349 * Params: | |
350 * arr = the array to get the index of the element from | |
351 * element = the element to find the index of | |
352 * | |
353 * Returns: the index of the last occurrence of the element in the | |
354 * specified array, or U.max | |
355 * if the element does not occur. | |
356 * | |
357 * Throws: AssertException if the length of the array is 0 | |
358 * Throws: AssertException if the return value is less than -1 or | |
359 * greater than the length of the array - 1. | |
360 */ | |
361 U lastIndexOf (T, U = size_t) (T[] arr, T element) | |
362 in | |
363 { | |
364 assert(arr.length > 0, "dstep.internal.collection.Array.lastIndexOf: The length of the array was 0"); | |
365 } | |
366 body | |
367 { | |
368 version (Tango) | |
369 { | |
370 U index = tango.text.Util.locatePrior(arr, element); | |
371 | |
372 if (index == arr.length) | |
373 return U.max; | |
374 | |
375 return index; | |
376 } | |
377 | |
378 else | |
379 { | |
380 foreach_reverse (i, e ; arr) | |
381 if (e is element) | |
382 return i; | |
383 | |
384 return U.max; | |
385 } | |
386 } | |
387 | |
388 /** | |
389 * Returns the number of elements in the specified array. | |
390 * | |
391 * Params: | |
392 * arr = the array to get the number of elements from | |
393 * | |
394 * Returns: the number of elements in this list | |
395 */ | |
396 U size (T, U = size_t) (T[] arr) | |
397 { | |
398 return arr.length; | |
399 } | |
400 | |
401 /** | |
402 * Finds the first occurence of element in arr | |
403 * | |
404 * Params: | |
405 * arr = the array to find the element in | |
406 * element = the element to find | |
407 * start = at which position to start finding | |
408 * | |
409 * Returns: the index of the first match or U.max if no match was found. | |
410 */ | |
411 alias indexOf find; | |
412 | |
413 /** | |
414 * Replaces a section of $(D_PARAM arr) with elements starting at $(D_PARAM pos) ending | |
415 * $(D_PARAM n) elements after | |
416 * | |
417 * Params: | |
418 * arr = the array to do the replace in | |
419 * pos = position within the array of the first element of the section to be replaced | |
420 * n = length of the section to be replaced within the array | |
421 * elements = the elements to replace with | |
422 * | |
423 * Throws: | |
424 * AssertException if pos is greater than the length of the array | |
425 * | |
426 * Returns: the array | |
427 */ | |
428 T[] replace (T, U = size_t) (ref T[] arr, U pos, U n, T[] elements) | |
429 in | |
430 { | |
431 assert(pos <= arr.length, "dstep.internal.collection.Array.replace: The position was greter than the length of the array"); | |
432 } | |
433 body | |
434 { | |
435 U i; | |
436 U nr = n; | |
437 | |
438 if (nr > arr.length) | |
439 nr = arr.length - 1; | |
440 | |
441 if (nr == elements.length) | |
442 { | |
443 U eIndex; | |
444 | |
445 for (i = pos, eIndex = 0; i <= nr; i++, eIndex++) | |
446 arr[i] = elements[eIndex]; | |
447 | |
448 return arr; | |
449 } | |
450 | |
451 else if (elements.length == 0) | |
452 { | |
453 U index = pos + n; | |
454 | |
455 if (index >= arr.length) | |
456 index = arr.length; | |
457 | |
458 return arr = arr[0 .. pos] ~ arr[index .. $]; | |
459 } | |
460 | |
461 else | |
462 { | |
463 U eIndex; | |
464 | |
465 for (i = pos, eIndex = 0; eIndex < nr && i < arr.length && eIndex < elements.length; i++, eIndex++) | |
466 arr[i] = elements[eIndex]; | |
467 | |
468 // no positions left and elements are left in elements, insert elements | |
469 if (eIndex < elements.length) | |
470 return arr = arr[0 .. i] ~ elements[eIndex .. $] ~ arr[i .. $]; | |
471 | |
472 // positions left to replace but no elements, remove those positions | |
473 else if (nr > eIndex) | |
474 { | |
475 U index = pos + nr; | |
476 | |
477 if (index >= arr.length) | |
478 index = arr.length; | |
479 | |
480 return arr = arr[0 .. pos + eIndex] ~ arr[index .. $]; | |
481 } | |
482 | |
483 } | |
484 | |
485 return arr; | |
486 } | |
487 | |
488 /** | |
489 * Erases a part of the array content, shortening the length of the array. | |
490 * | |
491 * Params: | |
492 * arr = the array to erase elements from | |
493 * start = the position within the array of the first element to be erased | |
494 * n = amount of elements to be removed. It may remove less elements if the | |
495 * end of the array is reached before the n elements have been erased. | |
496 * The default value of n indicates that all the elements until the end | |
497 * of the array should be erased. | |
498 * | |
499 * Throws: | |
500 * AssertException if pos is greater than the length of the array | |
501 * | |
502 * Returns: the array | |
503 */ | |
504 T[] erase (T, U = size_t) (ref T[] arr, U start = 0, U n = U.max) | |
505 in | |
506 { | |
507 assert(start <= arr.length, "dstep.internal.collection.Array.erase: The start position was greater than the length of the array"); | |
508 } | |
509 body | |
510 { | |
511 U end; | |
512 | |
513 if (n == U.max) | |
514 end = arr.length; | |
515 | |
516 else | |
517 { | |
518 end = start + n; | |
519 | |
520 if (end > arr.length) | |
521 end = arr.length; | |
522 } | |
523 | |
524 return arr = arr[0 .. start] ~ arr[end .. $]; | |
525 } | |
526 | |
527 /** | |
528 * Compares to arrays. Returns 0 if the content matches, less than zero | |
529 * if a is "less" than b, or greater than zero where a is "bigger". | |
530 * | |
531 * Params: | |
532 * a = the first array | |
533 * b = the second array | |
534 * end = the index where the comparision will end | |
535 * | |
536 * Returns: Returns 0 if the content matches, less than zero if a is | |
537 * "less" than b, or greater than zero where a is "bigger". | |
538 */ | |
539 int compare (T, U = size_t) (T[] a, T[] b, U end = U.max) | |
540 { | |
541 U ia = end; | |
542 U ib = end; | |
543 | |
544 if (ia > a.length) | |
545 ia = a.length; | |
546 | |
547 if (ib > b.length) | |
548 ib = b.length; | |
549 | |
550 return typeid(T[]).compare(&a[0 .. ia], &b[0 .. ib]); | |
551 } | |
552 | |
553 /** | |
554 * Compares the content of the given array to the content of a comparing | |
555 * array, which is formed according to the arguments passed. | |
556 * | |
557 * The function returns 0 if all the elements in the compared contents compare | |
558 * equal, a negative value if the first element that does not match compares to | |
559 * less in the array than in the comparing array, and a positive value in | |
560 * the opposite case. | |
561 * | |
562 * Params: | |
563 * a = the first array to compare with | |
564 * 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. | |
565 * n = length of the compared slice. | |
566 * b = array with the content to be used as comparing array. | |
567 * | |
568 * 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). | |
569 * | |
570 * Throws: AssertException if pos is specified with a position greater than the length of the corresponding array | |
571 */ | |
572 int compare (T, U = size_t) (T[] a, size_t pos, size_t n, T[] b) | |
573 in | |
574 { | |
575 assert(pos <= b.length); | |
576 } | |
577 body | |
578 { | |
579 U end = pos + n; | |
580 | |
581 if (end > b.length) | |
582 end = b.length; | |
583 | |
584 return typeid(T[]).compare(&b[pos .. end], &a[0 .. $]); | |
585 } | |
586 | |
587 /** | |
588 * Reserves the given amount of allocated storage for the given array. | |
589 * | |
590 * Params: | |
591 * a = the array to reserve allocated storage for | |
592 * capacity = the amount of allocated storage to be reserved | |
593 */ | |
594 void reserve (T) (ref T[] a, size_t amount = 0) | |
595 { | |
596 a = (new T[amount])[0 .. 0]; | |
597 } |