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 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 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 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 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 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 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 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 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 }