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)
9 module core
.internal
.array
.concatenation
;
12 * Concatenate the arrays inside of `froms`.
13 * `_d_arraycatnTX(a, b, c)` means `a ~ b ~ c`.
16 * froms = Arrays to be concatenated.
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
;
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
))
38 totalLen
+= from
.length
;
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.
49 // TODO: forward file, line, name from _d_arraycatnTXTrace
50 _d_arraysetlengthTImpl
!(typeof(res
))._d_arraysetlengthTTrace(
51 __FILE__
, __LINE__
, "_d_arraycatnTX", res
, totalLen
);
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
)
64 foreach (ref from
; froms
)
65 static if (is(typeof(from
) : T
))
66 copyEmplace(cast(T
) from
, res
[i
++]);
70 foreach (ref elem
; from
)
71 copyEmplace(cast(T
) elem
, res
[i
++]);
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
);
82 const len
= from
.length
;
85 memcpy(resptr
, cast(Unqual
!T
*) from
, len
* elemSize
);
90 static if (hasPostblit
)
91 foreach (ref elem
; res
)
92 (cast() elem
).__xpostblit();
111 S
[] arr1
= [S(0), S(1), S(2)];
113 S
[] arr3
= [S(6), S(7), S(8)];
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)]);
128 this(ref return scope S rhs
)
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)];
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)]);
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
);
172 assert(counter
== 4);
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
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
);
192 assert(0, "Cannot concatenate arrays if compiling without support for runtime type information!");