Wolfgang Thallergcc16 merge934c3885 months agoHistory
5152 lines · 144.7 KB · D
RawDownload
// Written in the D programming language./**Functions and types that manipulate built-in arrays and associative arrays. This module provides all kinds of functions to create, manipulate or convert arrays: $(SCRIPT inhibitQuickIndex = 1;)$(DIVC quickindex,$(BOOKTABLE ,$(TR $(TH Function Name) $(TH Description))    $(TR $(TD $(LREF array))        $(TD Returns a copy of the input in a newly allocated dynamic array.    ))    $(TR $(TD $(LREF appender))        $(TD Returns a new $(LREF Appender) or $(LREF RefAppender) initialized with a given array.    ))    $(TR $(TD $(LREF assocArray))        $(TD Returns a newly allocated associative array from a range/ranges of keys and values.    ))    $(TR $(TD $(LREF byPair))        $(TD Construct a range iterating over an associative array by key/value tuples.    ))    $(TR $(TD $(LREF insertInPlace))        $(TD Inserts into an existing array at a given position.    ))    $(TR $(TD $(LREF join))        $(TD Concatenates a range of ranges into one array.    ))    $(TR $(TD $(LREF minimallyInitializedArray))        $(TD Returns a new array of type `T`.    ))    $(TR $(TD $(LREF replace))        $(TD Returns a new array with all occurrences of a certain subrange replaced.    ))    $(TR $(TD $(LREF replaceFirst))        $(TD Returns a new array with the first occurrence of a certain subrange replaced.    ))    $(TR $(TD $(LREF replaceInPlace))        $(TD Replaces all occurrences of a certain subrange and puts the result into a given array.    ))    $(TR $(TD $(LREF replaceInto))        $(TD Replaces all occurrences of a certain subrange and puts the result into an output range.    ))    $(TR $(TD $(LREF replaceLast))        $(TD Returns a new array with the last occurrence of a certain subrange replaced.    ))    $(TR $(TD $(LREF replaceSlice))        $(TD Returns a new array with a given slice replaced.    ))    $(TR $(TD $(LREF replicate))        $(TD Creates a new array out of several copies of an input array or range.    ))    $(TR $(TD $(LREF sameHead))        $(TD Checks if the initial segments of two arrays refer to the same        place in memory.    ))    $(TR $(TD $(LREF sameTail))        $(TD Checks if the final segments of two arrays refer to the same place        in memory.    ))    $(TR $(TD $(LREF split))        $(TD Eagerly split a range or string into an array.    ))    $(TR $(TD $(LREF staticArray))        $(TD Creates a new static array from given data.    ))    $(TR $(TD $(LREF uninitializedArray))        $(TD Returns a new array of type `T` without initializing its elements.    )))) Copyright: Copyright Andrei Alexandrescu 2008- and Jonathan M Davis 2011-. License:   $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0). Authors:   $(HTTP erdani.org, Andrei Alexandrescu) and           $(HTTP jmdavisprog.com, Jonathan M Davis) Source: $(PHOBOSSRC std/array.d)*/module std.array; import std.functional;import std.meta;import std.traits; import std.range.primitives;public import std.range.primitives : save, empty, popFront, popBack, front, back; /** * Allocates an array and initializes it with copies of the elements * of range `r`. * * Narrow strings are handled as follows: * - If autodecoding is turned on (default), then they are handled as a separate overload. * - If autodecoding is turned off, then this is equivalent to duplicating the array. * * Params: *      r = range (or aggregate with `opApply` function) whose elements are copied into the allocated array * Returns: *      allocated and initialized array */ForeachType!Range[] array(Range)(Range r)if (isIterable!Range && !isAutodecodableString!Range && !isInfinite!Range){    if (__ctfe)    {        // Compile-time version to avoid memcpy calls.        // Also used to infer attributes of array().        typeof(return) result;        foreach (e; r)            result ~= e;        return result;    }     alias E = ForeachType!Range;    static if (hasLength!Range)    {        const length = r.length;        if (length == 0)            return null;         import core.internal.lifetime : emplaceRef;         auto result = (() @trusted => uninitializedArray!(Unqual!E[])(length))();         // Every element of the uninitialized array must be initialized        size_t cnt; //Number of elements that have been initialized        try        {            foreach (e; r)            {                emplaceRef!E(result[cnt], e);                ++cnt;            }        } catch (Exception e)        {            //https://issues.dlang.org/show_bug.cgi?id=22185            //Make any uninitialized elements safely destructible.            foreach (ref elem; result[cnt..$])            {                import core.internal.lifetime : emplaceInitializer;                emplaceInitializer(elem);            }            throw e;        }        /*            https://issues.dlang.org/show_bug.cgi?id=22673             We preallocated an array, we should ensure that enough range elements            were gathered such that every slot in the array is filled. If not, the GC            will collect the allocated array, leading to the `length - cnt` left over elements            being collected too - despite their contents having no guarantee of destructibility.         */        assert(length == cnt,               "Range .length property was not equal to the length yielded by the range before becoming empty");        return (() @trusted => cast(E[]) result)();    }    else    {        auto a = appender!(E[])();        foreach (e; r)        {            a.put(e);        }        return a.data;    }} /// dittoForeachType!(typeof((*Range).init))[] array(Range)(Range r)if (is(Range == U*, U) && isIterable!U && !isAutodecodableString!Range && !isInfinite!Range){    return array(*r);} ///@safe pure nothrow unittest{    auto a = array([1, 2, 3, 4, 5][]);    assert(a == [ 1, 2, 3, 4, 5 ]);} @safe pure nothrow unittest{    import std.algorithm.comparison : equal;    struct Foo    {        int a;    }    auto a = array([Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)][]);    assert(equal(a, [Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)]));} @safe pure nothrow unittest{    struct MyRange    {        enum front = 123;        enum empty = true;        void popFront() {}    }     auto arr = (new MyRange).array;    assert(arr.empty);} @safe pure nothrow unittest{    immutable int[] a = [1, 2, 3, 4];    auto b = (&a).array;    assert(b == a);} @safe pure nothrow unittest{    import std.algorithm.comparison : equal;    struct Foo    {        int a;        noreturn opAssign(Foo)        {            assert(0);        }        auto opEquals(Foo foo)        {            return a == foo.a;        }    }    auto a = array([Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)][]);    assert(equal(a, [Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)]));} // https://issues.dlang.org/show_bug.cgi?id=12315@safe pure nothrow unittest{    static struct Bug12315 { immutable int i; }    enum bug12315 = [Bug12315(123456789)].array();    static assert(bug12315[0].i == 123456789);} @safe pure nothrow unittest{    import std.range;    static struct S{int* p;}    auto a = array(immutable(S).init.repeat(5));    assert(a.length == 5);} // https://issues.dlang.org/show_bug.cgi?id=18995@system unittest{    import core.memory : __delete;    int nAlive = 0;    struct S    {        bool alive;        this(int) { alive = true; ++nAlive; }        this(this) { nAlive += alive; }        ~this() { nAlive -= alive; alive = false; }    }     import std.algorithm.iteration : map;    import std.range : iota;     auto arr = iota(3).map!(a => S(a)).array;    assert(nAlive == 3);     // No good way to ensure the GC frees this, just call the lifetime function    // directly.    __delete(arr);     assert(nAlive == 0);} @safe pure nothrow @nogc unittest{    //Turn down infinity:    static assert(!is(typeof(        repeat(1).array()    )));} // https://issues.dlang.org/show_bug.cgi?id=20937@safe pure nothrow unittest{    struct S {int* x;}    struct R    {        immutable(S) front;        bool empty;        @safe pure nothrow void popFront(){empty = true;}    }    R().array;} // Test that `array(scope InputRange r)` returns a non-scope array// https://issues.dlang.org/show_bug.cgi?id=23300@safe pure nothrow unittest{    @safe int[] fun()    {        import std.algorithm.iteration : map;        int[3] arr = [1, 2, 3];        scope r = arr[].map!(x => x + 3);        return r.array;    }} /**Convert a narrow autodecoding string to an array type that fully supportsrandom access.  This is handled as a special case and always returns an arrayof `dchar` NOTE: This function is never used when autodecoding is turned off. Params:    str = `isNarrowString` to be converted to an array of `dchar`Returns:    a `dchar[]`, `const(dchar)[]`, or `immutable(dchar)[]` depending on the constness of    the input.*/CopyTypeQualifiers!(ElementType!String,dchar)[] array(String)(scope String str)if (isAutodecodableString!String){    import std.utf : toUTF32;    auto temp = str.toUTF32;    /* Unsafe cast. Allowed because toUTF32 makes a new array       and copies all the elements.     */    return () @trusted { return cast(CopyTypeQualifiers!(ElementType!String, dchar)[]) temp; } ();} ///@safe pure nothrow unittest{    import std.range.primitives : isRandomAccessRange;    import std.traits : isAutodecodableString;     // note that if autodecoding is turned off, `array` will not transcode these.    static if (isAutodecodableString!string)        assert("Hello D".array == "Hello D"d);    else        assert("Hello D".array == "Hello D");     static if (isAutodecodableString!wstring)        assert("Hello D"w.array == "Hello D"d);    else        assert("Hello D"w.array == "Hello D"w);     static assert(isRandomAccessRange!dstring == true);} @safe unittest{    import std.conv : to;     static struct TestArray { int x; string toString() @safe { return to!string(x); } }     static struct OpAssign    {        uint num;        this(uint num) { this.num = num; }         // Templating opAssign to make sure the bugs with opAssign being        // templated are fixed.        void opAssign(T)(T rhs) { this.num = rhs.num; }    }     static struct OpApply    {        int opApply(scope int delegate(ref int) @safe dg)        {            int res;            foreach (i; 0 .. 10)            {                res = dg(i);                if (res) break;            }             return res;        }    }     auto a = array([1, 2, 3, 4, 5][]);    assert(a == [ 1, 2, 3, 4, 5 ]);     auto b = array([TestArray(1), TestArray(2)][]);    assert(b == [TestArray(1), TestArray(2)]);     class C    {        int x;        this(int y) { x = y; }        override string toString() const @safe { return to!string(x); }    }    auto c = array([new C(1), new C(2)][]);    assert(c[0].x == 1);    assert(c[1].x == 2);     auto d = array([1.0, 2.2, 3][]);    assert(is(typeof(d) == double[]));    assert(d == [1.0, 2.2, 3]);     auto e = [OpAssign(1), OpAssign(2)];    auto f = array(e);    assert(e == f);     assert(array(OpApply.init) == [0,1,2,3,4,5,6,7,8,9]);    static if (isAutodecodableString!string)    {        assert(array("ABC") == "ABC"d);        assert(array("ABC".dup) == "ABC"d.dup);    }} // https://issues.dlang.org/show_bug.cgi?id=8233@safe pure nothrow unittest{    assert(array("hello world"d) == "hello world"d);    immutable a = [1, 2, 3, 4, 5];    assert(array(a) == a);    const b = a;    assert(array(b) == a);     //To verify that the opAssign branch doesn't get screwed up by using Unqual.    //EDIT: array no longer calls opAssign.    struct S    {        ref S opAssign(S)(const ref S rhs)        {            assert(0);        }         int i;    }     static foreach (T; AliasSeq!(S, const S, immutable S))    {{        auto arr = [T(1), T(2), T(3), T(4)];        assert(array(arr) == arr);    }}} // https://issues.dlang.org/show_bug.cgi?id=9824@safe pure nothrow unittest{    static struct S    {        @disable void opAssign(S);        int i;    }    auto arr = [S(0), S(1), S(2)];    arr.array();} // https://issues.dlang.org/show_bug.cgi?id=10220@safe pure nothrow unittest{    import std.algorithm.comparison : equal;    import std.exception;    import std.range : repeat;     static struct S    {        int val;         @disable this();        this(int v) { val = v; }    }    assertCTFEable!(    {        auto r = S(1).repeat(2).array();        assert(equal(r, [S(1), S(1)]));    });}//https://issues.dlang.org/show_bug.cgi?id=22673@system unittest{    struct LyingRange    {        enum size_t length = 100;        enum theRealLength = 50;        size_t idx = 0;        bool empty()        {            return idx <= theRealLength;        }        void popFront()        {            ++idx;        }        size_t front()        {            return idx;        }    }    static assert(hasLength!LyingRange);    LyingRange rng;

Lines 1–500 of 5152.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t