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 enforceRawArraysConformable(const char[] action, const size_t elementSize, 30 const void[] a1, const void[] a2, const bool allowOverlap = false) 31 { 32 _enforceSameLength(action, a1.length, a2.length); 33 if (!allowOverlap) 34 _enforceNoOverlap(action, arrayToPtr(a1), arrayToPtr(a2), elementSize * a1.length); 35 } 36 37 private void _enforceSameLength(const char[] action, 38 const size_t length1, const size_t length2) 39 { 40 if (length1 == length2) 41 return; 42 43 UnsignedStringBuf tmpBuff = void; 44 string msg = "Array lengths don't match for "; 45 msg ~= action; 46 msg ~= ": "; 47 msg ~= length1.unsignedToTempString(tmpBuff); 48 msg ~= " != "; 49 msg ~= length2.unsignedToTempString(tmpBuff); 50 assert(0, msg); 51 } 52 53 private void _enforceNoOverlap(const char[] action, 54 uintptr_t ptr1, uintptr_t ptr2, const size_t bytes) 55 { 56 const d = ptr1 > ptr2 ? ptr1 - ptr2 : ptr2 - ptr1; 57 if (d >= bytes) 58 return; 59 const overlappedBytes = bytes - d; 60 61 UnsignedStringBuf tmpBuff = void; 62 string msg = "Overlapping arrays in "; 63 msg ~= action; 64 msg ~= ": "; 65 msg ~= overlappedBytes.unsignedToTempString(tmpBuff); 66 msg ~= " byte(s) overlap of "; 67 msg ~= bytes.unsignedToTempString(tmpBuff); 68 assert(0, msg); 69 } 70 71 void enforceRawArraysConformableNogc(const char[] action, const size_t elementSize, 72 const void[] a1, const void[] a2, const bool allowOverlap = false) 73 { 74 _enforceSameLengthNogc(action, a1.length, a2.length); 75 if (!allowOverlap) 76 _enforceNoOverlapNogc(action, arrayToPtr(a1), arrayToPtr(a2), elementSize * a1.length); 77 } 78 79 private void _enforceNoOverlapNogc(const ref char[] action, 80 uintptr_t ptr1, uintptr_t ptr2, const size_t bytes) 81 { 82 const d = ptr1 > ptr2 ? ptr1 - ptr2 : ptr2 - ptr1; 83 if (d >= bytes) 84 return; 85 const overlappedBytes = bytes - d; 86 87 assert(0, errorMessage("Overlapping arrays in %s: %zu byte(s) overlap of %zu", 88 action, overlappedBytes, bytes)); 89 } 90 91 private void _enforceSameLengthNogc(const ref char[] action, 92 const size_t length1, const size_t length2) 93 { 94 if (length1 == length2) 95 return; 96 97 assert(0, errorMessage("Array lengths don't match for %s: %zu != %zu", 98 action, length1, length2)); 99 } 100 101 private uintptr_t arrayToPtr(const void[] array) @trusted 102 { 103 // Ok because the user will never dereference the pointer 104 return cast(uintptr_t)array.ptr; 105 }