Wolfgang Thallergcc16 merge934c3885 months agoHistory
185 lines · 4.9 KB · D
RawDownload
/** This module contains support for controlling dynamic arrays' concatenation  Copyright: Copyright Digital Mars 2000 - 2019.  License: Distributed under the       $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).     (See accompanying file LICENSE)  Source: $(DRUNTIMESRC core/internal/_array/_concatenation.d)*/module core.internal.array.concatenation; /** * Concatenate the arrays inside of `froms`. * `_d_arraycatnTX(a, b, c)` means `a ~ b ~ c`. * * Params: *      froms = Arrays to be concatenated. * Returns: *      A newly allocated array that contains all the elements from `froms`. */Tret _d_arraycatnTX(Tret: Tret_El[], Tret_El, Tarr...)(auto ref Tarr froms) @trusted{    import core.exception : onOutOfMemoryError;    import core.internal.array.utils : __arrayAlloc;    import core.internal.traits : hasElaborateCopyConstructor, Unqual;    import core.lifetime : copyEmplace;    import core.stdc.string : memcpy;     Tret res;    size_t totalLen;     alias T = typeof(res[0]); // Element type of the result array    alias UnqT = Unqual!T;    // Unqualified version of T (strips const/immutable)    enum elemSize = T.sizeof; // Size of each element    enum hasPostblit = __traits(hasPostblit, T); // Whether T has a postblit constructor     // Compute total length of the resulting array    static foreach (from; froms)        static if (is(typeof(from) : T))            totalLen++; // Single element contributes one to length        else            totalLen += from.length; // Arrays contribute their full length     if (totalLen == 0)        return res; // Return an empty array if no elements are present     // Allocate memory for mutable arrays using __arrayAlloc    res = (cast(Tret_El*) &__arrayAlloc!(UnqT)(elemSize * totalLen)[0])[0 .. totalLen];     if (res.ptr is null)        onOutOfMemoryError(); // Abort if allocation fails     static if (hasElaborateCopyConstructor!T && !hasPostblit)    {        size_t i = 0;        foreach (ref from; froms)            static if (is(typeof(from) : T))                copyEmplace(cast(T) from, res[i++]);            else            {                if (from.length)                    foreach (ref elem; from)                        copyEmplace(cast(T) elem, res[i++]);            }    }    else    {        auto resptr = cast(UnqT *) res;        foreach (ref from; froms)            static if (is (typeof(from) : T))                memcpy(resptr++, cast(UnqT *) &from, elemSize);            else            {                const len = from.length;                if (len)                {                    memcpy(resptr, cast(UnqT *) from, len * elemSize);                    resptr += len;                }            }         static if (hasPostblit)            foreach (ref elem; res)                (cast() elem).__xpostblit();    }     return res;} // postblit@safe unittest{    int counter;    struct S    {        int val;        this(this)        {            counter++;        }    }     S[] arr1 = [S(0), S(1), S(2)];    S[] arr2 = [];    S[] arr3 = [S(6), S(7), S(8)];    S elem = S(9);    S[] result = _d_arraycatnTX!(S[])(arr1, arr2, arr3, elem);     assert(counter == 7);    assert(result == [S(0), S(1), S(2), S(6), S(7), S(8), S(9)]);} // copy constructor@safe unittest{    int counter;    struct S    {        int val;        this(ref return scope S rhs)        {            val = rhs.val;            counter++;        }    }     S[] arr1 = [S(0), S(1), S(2)];    S[] arr2 = [S(3), S(4), S(5)];    S[] arr3 = [S(6), S(7), S(8)];    S elem = S(9);    S[] result = _d_arraycatnTX!(S[])(arr1, elem, arr2, arr3);     assert(counter == 10);    assert(result == [S(0), S(1), S(2), S(9), S(3), S(4), S(5), S(6), S(7), S(8)]);} // throwing@safe unittest{    int counter;    bool didThrow;    struct S    {        int val;        this(this)        {            counter++;            if (counter == 4)                throw new Exception("");        }    }     try    {        S[] arr1 = [S(0), S(1), S(2)];        S[] arr2 = [S(3), S(4), S(5)];        _d_arraycatnTX!(S[])(arr1, arr2);    }    catch (Exception)    {        didThrow = true;    }     assert(counter == 4);    assert(didThrow);} version (D_ProfileGC){    /**    * TraceGC wrapper around $(REF _d_arraycatnTX, core,internal,array,concatenation).    */    Tret _d_arraycatnTXTrace(Tret, Tarr...)(scope auto ref Tarr froms, string file = __FILE__, int line = __LINE__, string funcname = __FUNCTION__) @trusted    {        version (D_TypeInfo)        {            import core.internal.array.utils: TraceHook, gcStatsPure, accumulatePure;            mixin(TraceHook!("Tarr", "_d_arraycatnTX"));             import core.lifetime: forward;            return _d_arraycatnTX!Tret(forward!froms);        }        else            assert(0, "Cannot concatenate arrays if compiling without support for runtime type information!");    }}

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