aarch64: Fix sve/acle/general/ldff1_8.c failures
[gcc.git] / libphobos / libdruntime / core / internal / array / concatenation.d
blob3063c4c0ea063ac02c65e7e0b3a0e6aed230f1fa
1 /**
2 This module contains support for controlling dynamic arrays' concatenation
3 Copyright: Copyright Digital Mars 2000 - 2019.
4 License: Distributed under the
5 $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
6 (See accompanying file LICENSE)
7 Source: $(DRUNTIMESRC core/internal/_array/_concatenation.d)
8 */
9 module core.internal.array.concatenation;
11 /**
12 * Concatenate the arrays inside of `froms`.
13 * `_d_arraycatnTX(a, b, c)` means `a ~ b ~ c`.
15 * Params:
16 * froms = Arrays to be concatenated.
17 * Returns:
18 * A newly allocated array that contains all the elements from `froms`.
20 Tret _d_arraycatnTX(Tret, Tarr...)(auto ref Tarr froms) @trusted
22 import core.internal.array.capacity : _d_arraysetlengthTImpl;
23 import core.internal.traits : hasElaborateCopyConstructor, Unqual;
24 import core.lifetime : copyEmplace;
25 import core.stdc.string : memcpy;
27 Tret res;
28 size_t totalLen;
30 alias T = typeof(res[0]);
31 enum elemSize = T.sizeof;
32 enum hasPostblit = __traits(hasPostblit, T);
34 static foreach (from; froms)
35 static if (is (typeof(from) : T))
36 totalLen++;
37 else
38 totalLen += from.length;
40 if (totalLen == 0)
41 return res;
43 // We cannot use this, because it refuses to work if the array type has disabled default construction.
44 // res.length = totalLen;
45 // Call the runtime function directly instead.
46 // TODO: once `__arrayAlloc` is templated, call that instead.
47 version (D_ProfileGC)
49 // TODO: forward file, line, name from _d_arraycatnTXTrace
50 _d_arraysetlengthTImpl!(typeof(res))._d_arraysetlengthTTrace(
51 __FILE__, __LINE__, "_d_arraycatnTX", res, totalLen);
53 else
55 _d_arraysetlengthTImpl!(typeof(res))._d_arraysetlengthT(res, totalLen);
58 /* Currently, if both a postblit and a cpctor are defined, the postblit is
59 * used. If this changes, the condition below will have to be adapted.
61 static if (hasElaborateCopyConstructor!T && !hasPostblit)
63 size_t i = 0;
64 foreach (ref from; froms)
65 static if (is(typeof(from) : T))
66 copyEmplace(cast(T) from, res[i++]);
67 else
69 if (from.length)
70 foreach (ref elem; from)
71 copyEmplace(cast(T) elem, res[i++]);
74 else
76 auto resptr = cast(Unqual!T *) res;
77 foreach (ref from; froms)
78 static if (is (typeof(from) : T))
79 memcpy(resptr++, cast(Unqual!T *) &from, elemSize);
80 else
82 const len = from.length;
83 if (len)
85 memcpy(resptr, cast(Unqual!T *) from, len * elemSize);
86 resptr += len;
90 static if (hasPostblit)
91 foreach (ref elem; res)
92 (cast() elem).__xpostblit();
95 return res;
98 // postblit
99 @safe unittest
101 int counter;
102 struct S
104 int val;
105 this(this)
107 counter++;
111 S[] arr1 = [S(0), S(1), S(2)];
112 S[] arr2 = [];
113 S[] arr3 = [S(6), S(7), S(8)];
114 S elem = S(9);
115 S[] result = _d_arraycatnTX!(S[])(arr1, arr2, arr3, elem);
117 assert(counter == 7);
118 assert(result == [S(0), S(1), S(2), S(6), S(7), S(8), S(9)]);
121 // copy constructor
122 @safe unittest
124 int counter;
125 struct S
127 int val;
128 this(ref return scope S rhs)
130 val = rhs.val;
131 counter++;
135 S[] arr1 = [S(0), S(1), S(2)];
136 S[] arr2 = [S(3), S(4), S(5)];
137 S[] arr3 = [S(6), S(7), S(8)];
138 S elem = S(9);
139 S[] result = _d_arraycatnTX!(S[])(arr1, elem, arr2, arr3);
141 assert(counter == 10);
142 assert(result == [S(0), S(1), S(2), S(9), S(3), S(4), S(5), S(6), S(7), S(8)]);
145 // throwing
146 @safe unittest
148 int counter;
149 bool didThrow;
150 struct S
152 int val;
153 this(this)
155 counter++;
156 if (counter == 4)
157 throw new Exception("");
163 S[] arr1 = [S(0), S(1), S(2)];
164 S[] arr2 = [S(3), S(4), S(5)];
165 _d_arraycatnTX!(S[])(arr1, arr2);
167 catch (Exception)
169 didThrow = true;
172 assert(counter == 4);
173 assert(didThrow);
176 version (D_ProfileGC)
179 * TraceGC wrapper around $(REF _d_arraycatnTX, core,internal,array,concatenation).
181 Tret _d_arraycatnTXTrace(Tret, Tarr...)(string file, int line, string funcname, scope auto ref Tarr froms) @trusted
183 version (D_TypeInfo)
185 import core.internal.array.utils: TraceHook, gcStatsPure, accumulatePure;
186 mixin(TraceHook!(Tarr.stringof, "_d_arraycatnTX"));
188 import core.lifetime: forward;
189 return _d_arraycatnTX!Tret(forward!froms);
191 else
192 assert(0, "Cannot concatenate arrays if compiling without support for runtime type information!");