/** * Array utilities. * * Copyright: Denis Shelomovskij 2013 * License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0). * Authors: Denis Shelomovskij * Source: $(DRUNTIMESRC core/internal/util/_array.d) */ module core.internal.util.array; import core.internal.string; import core.stdc.stdint; // TLS storage shared for all error messages. private align(2 * size_t.sizeof) char[256] _store; private char[] errorMessage(Args...)(scope const(char*) format, const char[] action, Args args) @trusted { import core.stdc.stdio : snprintf; snprintf(&_store[0], _store.sizeof, format, &action[0], args); return _store; } @safe /* pure dmd @@@BUG11461@@@ */ nothrow: void enforceTypedArraysConformable(T)(const char[] action, const T[] a1, const T[] a2, const bool allowOverlap = false) { _enforceSameLength(action, a1.length, a2.length); if (!allowOverlap) _enforceNoOverlap(action, arrayToPtr(a1), arrayToPtr(a2), T.sizeof * a1.length); } void enforceRawArraysConformable(const char[] action, const size_t elementSize, const void[] a1, const void[] a2, const bool allowOverlap = false) { _enforceSameLength(action, a1.length, a2.length); if (!allowOverlap) _enforceNoOverlap(action, arrayToPtr(a1), arrayToPtr(a2), elementSize * a1.length); } private void _enforceSameLength(const char[] action, const size_t length1, const size_t length2) { if (length1 == length2) return; UnsignedStringBuf tmpBuff = void; string msg = "Array lengths don't match for "; msg ~= action; msg ~= ": "; msg ~= length1.unsignedToTempString(tmpBuff); msg ~= " != "; msg ~= length2.unsignedToTempString(tmpBuff); assert(0, msg); } private void _enforceNoOverlap(const char[] action, uintptr_t ptr1, uintptr_t ptr2, const size_t bytes) { const d = ptr1 > ptr2 ? ptr1 - ptr2 : ptr2 - ptr1; if (d >= bytes) return; const overlappedBytes = bytes - d; UnsignedStringBuf tmpBuff = void; string msg = "Overlapping arrays in "; msg ~= action; msg ~= ": "; msg ~= overlappedBytes.unsignedToTempString(tmpBuff); msg ~= " byte(s) overlap of "; msg ~= bytes.unsignedToTempString(tmpBuff); assert(0, msg); } void enforceTypedArraysConformableNogc(T)(const char[] action, const T[] a1, const T[] a2, const bool allowOverlap = false) { _enforceSameLengthNogc(action, a1.length, a2.length); if (!allowOverlap) _enforceNoOverlapNogc(action, arrayToPtr(a1), arrayToPtr(a2), T.sizeof * a1.length); } void enforceRawArraysConformableNogc(const char[] action, const size_t elementSize, const void[] a1, const void[] a2, const bool allowOverlap = false) { _enforceSameLengthNogc(action, a1.length, a2.length); if (!allowOverlap) _enforceNoOverlapNogc(action, arrayToPtr(a1), arrayToPtr(a2), elementSize * a1.length); } private void _enforceNoOverlapNogc(const ref char[] action, uintptr_t ptr1, uintptr_t ptr2, const size_t bytes) { const d = ptr1 > ptr2 ? ptr1 - ptr2 : ptr2 - ptr1; if (d >= bytes) return; const overlappedBytes = bytes - d; assert(0, errorMessage("Overlapping arrays in %s: %zu byte(s) overlap of %zu", action, overlappedBytes, bytes)); } private void _enforceSameLengthNogc(const ref char[] action, const size_t length1, const size_t length2) { if (length1 == length2) return; assert(0, errorMessage("Array lengths don't match for %s: %zu != %zu", action, length1, length2)); } private uintptr_t arrayToPtr(const void[] array) @trusted { // Ok because the user will never dereference the pointer return cast(uintptr_t)array.ptr; }