Changeset 787

Show
Ignore:
Timestamp:
07/07/08 23:03:22 (5 months ago)
Author:
andrei
Message:

$(LI Added module $(B std.array) containing array operations: $(B insert), $(B erase), and $(B replace).)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/phobos/std/array.d

    r398 r787  
    44 
    55private import std.c.stdio; 
    6 import std.contracts; 
     6private import std.contracts; 
     7private import std.traits; 
     8private import std.gc; 
     9private import std.string; 
     10private import std.algorithm; 
     11version(unittest) private import std.stdio; 
    712 
    813class ArrayBoundsError : Error 
     
    4045    throw a; 
    4146} 
     47 
     48/* 
     49Returns an array consisting of $(D elements). 
     50 
     51Example: 
     52 
     53---- 
     54auto a = array(1, 2, 3); 
     55assert(is(typeof(a) == int[])); 
     56assert(a == [ 1, 2, 3 ]); 
     57auto b = array(1, 2.2, 3); 
     58assert(is(typeof(b) == double[])); 
     59assert(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 
     129template IndexType(C : T[], T) 
     130{ 
     131    alias size_t IndexType; 
     132} 
     133 
     134unittest 
     135{ 
     136    static assert(is(IndexType!(double[]) == size_t)); 
     137    static assert(!is(IndexType!(double) == size_t)); 
     138} 
     139 
     140/** 
     141Inserts $(D stuff) in $(D container) at position $(D pos). 
     142 */ 
     143void 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 
     185unittest 
     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/** 
     195Erases elements from $(D array) with indices ranging from $(D from) 
     196(inclusive) to $(D to) (exclusive). 
     197 */ 
     198void 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 
     208unittest 
     209{ 
     210    int[] a = [1, 2, 3, 4, 5]; 
     211    erase(a, 1u, 3u); 
     212    assert(a == [1, 4, 5]); 
     213} 
     214 
     215/** 
     216Replaces elements from $(D array) with indices ranging from $(D from) 
     217(inclusive) to $(D to) (exclusive) with the range $(D stuff). Expands 
     218or shrinks the array as needed. 
     219 */ 
     220void 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 
     248unittest 
     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