Daily bump.
[gcc.git] / libphobos / libdruntime / core / internal / array / casting.d
blob4366da829c982518149b204a3acd418ab4260559
1 /**
2 This module contains compiler support for casting dynamic arrays
4 Copyright: Copyright Digital Mars 2000 - 2019.
5 License: Distributed under the
6 $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
7 (See accompanying file LICENSE)
8 Source: $(DRUNTIMESRC core/internal/_array/_casting.d)
9 */
10 module core.internal.array.casting;
12 /**
13 Used by `__ArrayCast` to emit a descriptive error message.
15 It is a template so it can be used by `__ArrayCast` in -betterC
16 builds. It is separate from `__ArrayCast` to minimize code
17 bloat.
19 Params:
20 fromType = name of the type being cast from
21 fromSize = total size in bytes of the array being cast from
22 fromLength = length of array being cast from
23 toType = name of the type being cast to
24 toElemSize = element size of array being cast to
26 private void onArrayCastError()(string fromType, size_t fromSize, size_t fromLength, string toType, size_t toElemSize) @trusted
28 import core.internal.string : unsignedToTempString;
29 import core.memory : pureMalloc;
31 // convert discontiguous `msgComponents` to contiguous string on the C heap
32 enum msgLength = 2048;
33 // note: never freed!
34 char* msg = cast(char *)pureMalloc(msgLength);
36 size_t index = 0;
37 void add(const(char)[] m)
39 import core.stdc.string : memcpy;
41 auto N = msgLength - 1 - index;
42 if (N > m.length)
43 N = m.length;
44 // prevent superfluous and betterC-unfriendly checks via direct memcpy
45 memcpy(msg + index, m.ptr, N);
46 index += N;
49 add("`");
50 add(fromType);
51 add("[]` of length ");
52 auto s = unsignedToTempString(fromLength);
53 add(s[]);
54 add(" cannot be cast to `");
55 add(toType);
56 add("[]` as its length in bytes (");
57 s = unsignedToTempString(fromSize);
58 add(s[]);
59 add(") is not a multiple of `");
60 add(toType);
61 add(".sizeof` (");
62 s = unsignedToTempString(toElemSize);
63 add(s[]);
64 add(").");
65 msg[index] = '\0'; // null-termination
67 // first argument must evaluate to `false` at compile-time to maintain memory safety in release builds
68 assert(false, msg[0 .. index]);
71 /**
72 The compiler lowers expressions of `cast(TTo[])TFrom[]` to
73 this implementation. Note that this does not detect alignment problems.
75 Params:
76 from = the array to reinterpret-cast
78 Returns:
79 `from` reinterpreted as `TTo[]`
81 TTo[] __ArrayCast(TFrom, TTo)(return scope TFrom[] from) @nogc pure @trusted
83 const fromSize = from.length * TFrom.sizeof;
84 const toLength = fromSize / TTo.sizeof;
86 if ((fromSize % TTo.sizeof) != 0)
88 onArrayCastError(TFrom.stringof, fromSize, from.length, TTo.stringof, TTo.sizeof);
91 struct Array
93 size_t length;
94 void* ptr;
96 auto a = cast(Array*)&from;
97 a.length = toLength; // jam new length
98 return *cast(TTo[]*)a;
101 @safe @nogc pure nothrow unittest
103 byte[int.sizeof * 3] b = cast(byte) 0xab;
104 int[] i;
105 short[] s;
107 i = __ArrayCast!(byte, int)(b);
108 assert(i.length == 3);
109 foreach (v; i)
110 assert(v == cast(int) 0xabab_abab);
112 s = __ArrayCast!(byte, short)(b);
113 assert(s.length == 6);
114 foreach (v; s)
115 assert(v == cast(short) 0xabab);
117 s = __ArrayCast!(int, short)(i);
118 assert(s.length == 6);
119 foreach (v; s)
120 assert(v == cast(short) 0xabab);
123 @system nothrow unittest
125 string msg;
128 auto str = "hello";
129 auto wstr = cast(wstring) str;
131 catch (Throwable t)
132 msg = t.msg;
134 static immutable expected = "`immutable(char)[]` of length 5 cannot be cast to `immutable(wchar)[]` as " ~
135 "its length in bytes (5) is not a multiple of `immutable(wchar).sizeof` (2).";
137 if (msg != expected)
139 import core.stdc.stdio;
140 printf("Expected: |%.*s|\n", cast(int) expected.length, expected.ptr);
141 printf("Actual : |%.*s|\n", cast(int) msg.length, msg.ptr);
142 assert(false);