diff --git a/std/array.d b/std/array.d index 53ffb06905f..01d66974687 100644 --- a/std/array.d +++ b/std/array.d @@ -88,6 +88,25 @@ import std.traits; import std.range.primitives; public import std.range.primitives : save, empty, popFront, popBack, front, back; +import std.algorithm.mutation : move; + + + + + + +/** + * Method to verify if a constructor is of move-only type or not + */ + +private template needsMove(T) +{ + enum bool hasPostblit = __traits(hasMember, T, "__postblit"); + static if (hasPostblit) + enum needsMove = __traits(isDisabled, T.__postblit); + else + enum needsMove = false; +} /** * Allocates an array and initializes it with copies of the elements * of range `r`. @@ -308,6 +327,10 @@ if (is(Range == U*, U) && isIterable!U && !isAutodecodableString!Range && !isInf } } + + + + /** Convert a narrow autodecoding string to an array type that fully supports random access. This is handled as a special case and always returns an array @@ -1421,7 +1444,10 @@ private void copyBackwards(T)(T[] src, T[] dest) immutable len = src.length; for (size_t i = len; i-- > 0;) { - dest[i] = src[i]; + static if(needsMove!T) + move(dest[i],src[i]); + else + dest[i] = src[i]; } } } @@ -1521,17 +1547,29 @@ if (isSomeString!(T[]) && allSatisfy!(isCharOrStringOrDcharRange, U)) static if (T.sizeof == char.sizeof) { case 4: - ptr[3] = buf[3]; + static if(needsMove!T) + move(ptr[3],buf[3]); + else + ptr[3] = buf[3]; goto case; case 3: - ptr[2] = buf[2]; + static if(needsMove!T) + move(ptr[2],buf[2]); + else + ptr[2] = buf[2]; goto case; } case 2: - ptr[1] = buf[1]; + static if(needsMove!T) + move(ptr[1],buf[1]); + else + ptr[1] = buf[1]; goto case; case 1: - ptr[0] = buf[0]; + static if(needsMove!T) + move(ptr[0],buf[0]); + else + ptr[0] = buf[0]; } ptr += len; return ptr; @@ -1551,7 +1589,10 @@ if (isSomeString!(T[]) && allSatisfy!(isCharOrStringOrDcharRange, U)) if (__ctfe) { for (size_t i = arr.length - gap; i; --i) - arr[gap + i - 1] = arr[i - 1]; + static if(needsMove!T) + move(arr[gap+i-1],arr[i-1]); + else + arr[gap + i - 1] = arr[i - 1]; } else memmove(arr.ptr + gap, arr.ptr, (arr.length - gap) * T.sizeof); @@ -1931,6 +1972,7 @@ if (isDynamicArray!S) immutable len = s.length, nlen = n * len; for (size_t i = 0; i < nlen; i += len) { + r[i .. i + len] = s[]; } } @@ -3774,6 +3816,70 @@ if (isDynamicArray!A) assert(app2[] == [ 1, 2, 3, 4, 5, 6 ]); } +//https://github.com/dlang/phobos/pull/8789 issue for InPLaceAppenders +@safe pure nothrow unittest +{ + import std.array : appender; + + // Append characters one by one + auto a = appender!string(); + foreach (c; "Dlang") + a.put(c); + assert(a[] == "Dlang"); +} + +@safe pure nothrow unittest +{ + import std.array : appender; + + // Append full strings + auto a = appender!string(); + a.put("Hello"); + a.put(", "); + a.put("world!"); + assert(a[] == "Hello, world!"); +} + + + +@safe pure nothrow unittest +{ + import std.array : appender; + + // Append special characters + auto a = appender!string(); + a.put("€"); // Euro sign (3 bytes in UTF-8) + a.put("✓"); + assert(a[] == "€✓"); +} + +@safe pure nothrow unittest +{ + import std.array : appender; + + // Append with escape sequences + auto a = appender!string(); + a.put("Line1\n"); + a.put("Line2\tTabbed"); + assert(a[] == "Line1\nLine2\tTabbed"); +} + +@safe pure nothrow unittest +{ + import std.array : appender; + + // Append empty strings + auto a = appender!string(); + a.put(""); + a.put("non-empty"); + a.put(""); + assert(a[] == "non-empty"); +} + + + + + package(std) struct InPlaceAppender(A) if (isDynamicArray!A) { @@ -5169,7 +5275,10 @@ if (isInputRange!T && is(ElementType!T : U)) Unqual!U[n] ret; for (auto iter = a.take(n); !iter.empty; iter.popFront()) { - ret[i] = iter.front; + static if(needsMove!T) + move(ret[i],iter.front); + else + ret[i] = iter.front; i++; } @@ -5321,3 +5430,4 @@ version (StdUnittest) private void checkStaticArray(T, T1, T2)(T1 a, T2 b) nothr static assert(is(T1 == T[T1.length])); assert(a == b, "a must be equal to b"); } + diff --git a/std/container/array.d b/std/container/array.d index ad120c1c74f..b107167daea 100644 --- a/std/container/array.d +++ b/std/container/array.d @@ -2792,4 +2792,4 @@ if (is(immutable T == immutable bool)) Array!int empty; assert(empty.data == []); -} +} \ No newline at end of file