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 src/rt/util/_array.d)
8 */
9 module rt.util.array;
10 
11 
12 import core.internal.string;
13 import core.stdc.stdint;
14 
15 
16 @safe /* pure dmd @@@BUG11461@@@ */ nothrow:
17 
enforceTypedArraysConformable(T)18 void enforceTypedArraysConformable(T)(const char[] action,
19     const T[] a1, const T[] a2, in bool allowOverlap = false)
20 {
21     _enforceSameLength(action, a1.length, a2.length);
22     if (!allowOverlap)
23         _enforceNoOverlap(action, arrayToPtr(a1), arrayToPtr(a2), T.sizeof * a1.length);
24 }
25 
26 void enforceRawArraysConformable(const char[] action, in size_t elementSize,
27     const void[] a1, const void[] a2, in bool allowOverlap = false)
28 {
29     _enforceSameLength(action, a1.length, a2.length);
30     if (!allowOverlap)
31         _enforceNoOverlap(action, arrayToPtr(a1), arrayToPtr(a2), elementSize * a1.length);
32 }
33 
_enforceSameLength(const char[]action,in size_t length1,in size_t length2)34 private void _enforceSameLength(const char[] action,
35     in size_t length1, in size_t length2)
36 {
37     if (length1 == length2)
38         return;
39 
40     UnsignedStringBuf tmpBuff = void;
41     string msg = "Array lengths don't match for ";
42     msg ~= action;
43     msg ~= ": ";
44     msg ~= length1.unsignedToTempString(tmpBuff, 10);
45     msg ~= " != ";
46     msg ~= length2.unsignedToTempString(tmpBuff, 10);
47     throw new Error(msg);
48 }
49 
_enforceNoOverlap(const char[]action,uintptr_t ptr1,uintptr_t ptr2,in size_t bytes)50 private void _enforceNoOverlap(const char[] action,
51     uintptr_t ptr1, uintptr_t ptr2, in size_t bytes)
52 {
53     const d = ptr1 > ptr2 ? ptr1 - ptr2 : ptr2 - ptr1;
54     if (d >= bytes)
55         return;
56     const overlappedBytes = bytes - d;
57 
58     UnsignedStringBuf tmpBuff = void;
59     string msg = "Overlapping arrays in ";
60     msg ~= action;
61     msg ~= ": ";
62     msg ~= overlappedBytes.unsignedToTempString(tmpBuff, 10);
63     msg ~= " byte(s) overlap of ";
64     msg ~= bytes.unsignedToTempString(tmpBuff, 10);
65     throw new Error(msg);
66 }
67 
arrayToPtr(const void[]array)68 private uintptr_t arrayToPtr(const void[] array) @trusted
69 {
70     // Ok because the user will never dereference the pointer
71     return cast(uintptr_t)array.ptr;
72 }
73