Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 1898

Show
Ignore:
Timestamp:
08/19/10 00:53:05 (14 years ago)
Author:
dsimcha
Message:

Bug 4346: More flexible std.array.array. Also improve std.array.array to work better with immutable narrow strings and use emplace() instead of placement new.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/docsrc/changelog.dd

    r1897 r1898  
    2727    $(LI $(BUGZILLA 3312): std.string.count should use const(char)[], not immutable.) 
    2828    $(LI $(BUGZILLA 3348): Documentation for many std.process functions has disappeared) 
    2929    $(LI $(BUGZILLA 3361): code in std.zlib concatenates void[] arrays ) 
    3030    $(LI $(BUGZILLA 3877): std.range.chain do not manage infinite ranges correctly) 
    3131    $(LI $(BUGZILLA 3894): std.range.Stride!R requires R.front() and R.back() to return by reference) 
    3232    $(LI $(BUGZILLA 3946): schwartzSort - SwapStrategy always unstable) 
    3333    $(LI $(BUGZILLA 4402): std.range.Zip doesn't work w/ non-lvalue ranges.) 
    3434    $(LI $(BUGZILLA 4408): Ambiguity when using std.algorithm.splitter with generic ranges.) 
    3535    $(LI $(BUGZILLA 4292): CommonType fails for singular alias value.) 
    3636    $(LI $(BUGZILLA 4345): std.range.take!string: "Nonsensical finite range with slicing but no length".) 
     37    $(LI $(BUGZILLA 4345): More flexible std.array.array.) 
    3738    $(LI $(BUGZILLA 4363): Some phobos ranges are not forward ranges (but should be).) 
    3839    $(LI $(BUGZILLA 4381): Length attribute for std.typecons.Tuple.) 
    3940    $(LI $(BUGZILLA 4387): std.range.Cycle assumes lvalue elements.) 
    4041    $(LI $(BUGZILLA 4388): std.range.Radial assumes lvalue elements.) 
    4142    $(LI $(BUGZILLA 4403): std.range.FrontTransversal assumes lvalue elements.) 
    4243    $(LI $(BUGZILLA 4404): std.range.Transversal assumes lvalue elements.) 
    4344    $(LI $(BUGZILLA 4455): Taking the sqrt of an integer shouldn't require an explicit cast.) 
    4445    $(LI $(BUGZILLA 4464):  std.range.take does not always return Take!R.) 
    4546    ) 
    4647) 
  • trunk/phobos/std/array.d

    r1813 r1898  
    1212*/ 
    1313module std.array; 
    1414 
    1515import std.c.stdio; 
    1616import core.memory; 
    1717import std.algorithm, std.conv, std.encoding, std.exception, std.range, 
    1818    std.string, std.traits, std.typecons, std.utf; 
    1919version(unittest) private import std.stdio; 
    2020 
    2121/** 
    22 Returns a newly-allocated array consisting of a copy of the input 
    23 range $(D r). 
     22Returns a newly-allocated dynamic array consisting of a copy of the input 
     23range, static array, dynamic array, or class or struct with an $(D opApply) 
     24function $(D r).  Note that narrow strings are handled 
     25as a special case in an overload. 
    2426 
    2527Example: 
    2628 
    2729---- 
    2830auto a = array([1, 2, 3, 4, 5][]); 
    2931assert(a == [ 1, 2, 3, 4, 5 ]); 
    3032---- 
    3133 */ 
    32 ElementType!Range[] array(Range)(Range r) if (isInputRange!Range) 
    33 
    34     alias ElementType!Range E; 
     34ForeachType!Range[] array(Range)(Range r) 
     35if (isIterable!Range && !isNarrowString!Range) 
     36
     37    alias ForeachType!Range E; 
    3538    static if (hasLength!Range) 
    3639    { 
    3740        if (r.empty) return null; 
    3841 
    3942        // Determines whether the GC should scan the array. 
    4043        auto blkInfo = (typeid(E).flags & 1) ? 
    4144                       cast(GC.BlkAttr) 0 : 
    4245                       GC.BlkAttr.NO_SCAN; 
    4346 
    4447        auto result = (cast(E*) enforce(GC.malloc(r.length * E.sizeof, blkInfo), 
    4548                text("Out of memory while allocating an array of ", r.length, 
    4649                        " objects of type ", E.stringof)))[0 .. r.length]; 
    47         foreach (ref e; result) 
     50        size_t i = 0; 
     51        foreach (e; r) 
    4852        { 
    4953            // hacky 
    50             static if (is(typeof(&e.opAssign))) 
     54            static if (is(typeof(e.opAssign(e)))) 
    5155            { 
    5256                // this should be in-place construction 
    53                 new(&e) E(r.front); 
     57                auto voidArr = (cast(void*) (result.ptr + i))[0..E.sizeof]; 
     58                emplace!E(voidArr, e); 
    5459            } 
    5560            else 
    5661            { 
    57                 e = r.front
     62                result[i] = e
    5863            } 
    59             r.popFront
     64            i++
    6065        } 
    6166        return result; 
    6267    } 
    6368    else 
    6469    { 
    6570        auto a = appender!(E[])(); 
    6671        foreach (e; r) 
    6772        { 
    6873            a.put(e); 
    6974        } 
     
    97102    //     { 
    98103    //         result[constructedElements] = src; 
    99104    //     } 
    100105    //     ++constructedElements; 
    101106    // } 
    102107    // // 3. Success constructing all elements, type the array and return it 
    103108    // setTypeInfo(typeid(E), result); 
    104109    // return result[0 .. constructedElements]; 
    105110} 
    106111 
     112/** 
     113Convert a narrow string to an array type that fully supports random access. 
     114This is handled as a special case and always returns a $(D dchar[]), 
     115$(D const(dchar)[]), or $(D immutable(dchar)[]) depending on the constness of 
     116the input. 
     117*/ 
     118ElementType!String[] array(String)(String str) if(isNarrowString!String) 
     119{ 
     120    static if(is(typeof(return) == immutable)) 
     121    { 
     122        return to!(immutable(dchar)[])(str); 
     123    } 
     124    else static if(is(typeof(return) == const)) 
     125    { 
     126        return to!(const(dchar)[])(str); 
     127    } 
     128    else 
     129    { 
     130        return to!(dchar[])(str); 
     131    } 
     132} 
     133 
    107134version(unittest) 
    108135{ 
    109136    struct TestArray { int x; string toString() { return .to!string(x); } } 
     137 
     138    struct OpAssign 
     139    { 
     140        uint num; 
     141        this(uint num) { this.num = num; } 
     142 
     143        // Templating opAssign to make sure the bugs with opAssign being 
     144        // templated are fixed. 
     145        void opAssign(T)(T rhs) { this.num = rhs.num; } 
     146    } 
     147 
     148    struct OpApply 
     149    { 
     150        int opApply(int delegate(ref int) dg) 
     151        { 
     152            int res; 
     153            foreach(i; 0..10) 
     154            { 
     155                res = dg(i); 
     156                if(res) break; 
     157            } 
     158 
     159            return res; 
     160        } 
     161    } 
    110162} 
    111163 
    112164unittest 
    113165{ 
    114166    auto a = array([1, 2, 3, 4, 5][]); 
    115167    //writeln(a); 
    116168    assert(a == [ 1, 2, 3, 4, 5 ]); 
    117169 
    118170    auto b = array([TestArray(1), TestArray(2)][]); 
    119171    //writeln(b); 
     
    123175        int x; 
    124176        this(int y) { x = y; } 
    125177        override string toString() { return .to!string(x); } 
    126178    } 
    127179    auto c = array([new C(1), new C(2)][]); 
    128180    //writeln(c); 
    129181 
    130182    auto d = array([1., 2.2, 3][]); 
    131183    assert(is(typeof(d) == double[])); 
    132184    //writeln(d); 
     185 
     186    auto e = [OpAssign(1), OpAssign(2)]; 
     187    auto f = array(e); 
     188    assert(e == f); 
     189 
     190    assert(array(OpApply.init) == [0,1,2,3,4,5,6,7,8,9]); 
     191    assert(array("ABC") == "ABC"d); 
     192    assert(array("ABC".dup) == "ABC"d.dup); 
    133193} 
    134194 
    135195template IndexType(C : T[], T) 
    136196{ 
    137197    alias size_t IndexType; 
    138198} 
    139199 
    140200unittest 
    141201{ 
    142202    static assert(is(IndexType!(double[]) == size_t));