1 /**
2 * Array utilities.
3 *
4 * Copyright: Denis Shelomovskij 2013
5 * License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
6 * Authors: Denis Shelomovskij
7 * Source: $(DRUNTIMESRC core/internal/util/_array.d)
8 */
9 module core.internal.util.array;
10
11
12 import core.internal.string;
13 import core.stdc.stdint;
14
15
16 // TLS storage shared for all error messages.
17 private align(2 * size_t.sizeof) char[256] _store;
18
errorMessage(Args...)19 private char[] errorMessage(Args...)(scope const(char*) format,
20 const char[] action, Args args) @trusted
21 {
22 import core.stdc.stdio : snprintf;
23 snprintf(&_store[0], _store.sizeof, format, &action[0], args);
24 return _store;
25 }
26
27 @safe /* pure dmd @@@BUG11461@@@ */ nothrow:
28
enforceTypedArraysConformable(T)29 void enforceTypedArraysConformable(T)(const char[] action,
30 const T[] a1, const T[] a2, const bool allowOverlap = false)
31 {
32 _enforceSameLength(action, a1.length, a2.length);
33 if (!allowOverlap)
34 _enforceNoOverlap(action, arrayToPtr(a1), arrayToPtr(a2), T.sizeof * a1.length);
35 }
36
37 void enforceRawArraysConformable(const char[] action, const size_t elementSize,
38 const void[] a1, const void[] a2, const bool allowOverlap = false)
39 {
40 _enforceSameLength(action, a1.length, a2.length);
41 if (!allowOverlap)
42 _enforceNoOverlap(action, arrayToPtr(a1), arrayToPtr(a2), elementSize * a1.length);
43 }
44
_enforceSameLength(const char[]action,const size_t length1,const size_t length2)45 private void _enforceSameLength(const char[] action,
46 const size_t length1, const size_t length2)
47 {
48 if (length1 == length2)
49 return;
50
51 UnsignedStringBuf tmpBuff = void;
52 string msg = "Array lengths don't match for ";
53 msg ~= action;
54 msg ~= ": ";
55 msg ~= length1.unsignedToTempString(tmpBuff);
56 msg ~= " != ";
57 msg ~= length2.unsignedToTempString(tmpBuff);
58 assert(0, msg);
59 }
60
_enforceNoOverlap(const char[]action,uintptr_t ptr1,uintptr_t ptr2,const size_t bytes)61 private void _enforceNoOverlap(const char[] action,
62 uintptr_t ptr1, uintptr_t ptr2, const size_t bytes)
63 {
64 const d = ptr1 > ptr2 ? ptr1 - ptr2 : ptr2 - ptr1;
65 if (d >= bytes)
66 return;
67 const overlappedBytes = bytes - d;
68
69 UnsignedStringBuf tmpBuff = void;
70 string msg = "Overlapping arrays in ";
71 msg ~= action;
72 msg ~= ": ";
73 msg ~= overlappedBytes.unsignedToTempString(tmpBuff);
74 msg ~= " byte(s) overlap of ";
75 msg ~= bytes.unsignedToTempString(tmpBuff);
76 assert(0, msg);
77 }
78
enforceTypedArraysConformableNogc(T)79 void enforceTypedArraysConformableNogc(T)(const char[] action,
80 const T[] a1, const T[] a2, const bool allowOverlap = false)
81 {
82 _enforceSameLengthNogc(action, a1.length, a2.length);
83 if (!allowOverlap)
84 _enforceNoOverlapNogc(action, arrayToPtr(a1), arrayToPtr(a2), T.sizeof * a1.length);
85 }
86
87 void enforceRawArraysConformableNogc(const char[] action, const size_t elementSize,
88 const void[] a1, const void[] a2, const bool allowOverlap = false)
89 {
90 _enforceSameLengthNogc(action, a1.length, a2.length);
91 if (!allowOverlap)
92 _enforceNoOverlapNogc(action, arrayToPtr(a1), arrayToPtr(a2), elementSize * a1.length);
93 }
94
_enforceNoOverlapNogc(const ref char[]action,uintptr_t ptr1,uintptr_t ptr2,const size_t bytes)95 private void _enforceNoOverlapNogc(const ref char[] action,
96 uintptr_t ptr1, uintptr_t ptr2, const size_t bytes)
97 {
98 const d = ptr1 > ptr2 ? ptr1 - ptr2 : ptr2 - ptr1;
99 if (d >= bytes)
100 return;
101 const overlappedBytes = bytes - d;
102
103 assert(0, errorMessage("Overlapping arrays in %s: %zu byte(s) overlap of %zu",
104 action, overlappedBytes, bytes));
105 }
106
_enforceSameLengthNogc(const ref char[]action,const size_t length1,const size_t length2)107 private void _enforceSameLengthNogc(const ref char[] action,
108 const size_t length1, const size_t length2)
109 {
110 if (length1 == length2)
111 return;
112
113 assert(0, errorMessage("Array lengths don't match for %s: %zu != %zu",
114 action, length1, length2));
115 }
116
arrayToPtr(const void[]array)117 private uintptr_t arrayToPtr(const void[] array) @trusted
118 {
119 // Ok because the user will never dereference the pointer
120 return cast(uintptr_t)array.ptr;
121 }
122