// zlib open source license // // Copyright (c) 2019 to 2025 David Forsgren Piuva // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages // arising from the use of this software. // // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it // freely, subject to the following restrictions: // // 1. The origin of this software must not be misrepresented; you must not // claim that you wrote the original software. If you use this software // in a product, an acknowledgment in the product documentation would be // appreciated but is not required. // // 2. Altered source versions must be plainly marked as such, and must not be // misrepresented as being the original software. // // 3. This notice may not be removed or altered from any source // distribution. #include #include "bufferAPI.h" #include "stringAPI.h" #include "../implementation/math/scalar.h" #include "../base/SafePointer.h" #include "../base/heap.h" namespace dsr { Buffer buffer_create(intptr_t newSize) { if (newSize < 0) newSize = 0; // Allocate head and data. return handle_createArray(AllocationInitialization::Zeroed, (uintptr_t)newSize); } Buffer buffer_create(intptr_t newSize, uintptr_t paddToAlignment) { if (newSize < 0) newSize = 0; if (paddToAlignment > heap_getHeapAlignment()) { throwError(U"Maximum alignment exceeded when creating a buffer!\n"); return Handle(); } else { return handle_createArray(AllocationInitialization::Zeroed, memory_getPaddedSize((uintptr_t)newSize, paddToAlignment)); } } void buffer_replaceDestructor(Buffer &buffer, const HeapDestructor& newDestructor) { if (!buffer_exists(buffer)) { throwError(U"buffer_replaceDestructor: Cannot replace destructor for a buffer that don't exist.\n"); } else { heap_setAllocationDestructor(buffer.getUnsafe(), newDestructor); } } // TODO: Create clone and reallocation methods in heap.h to handle object lifetime in a reusable way. Buffer buffer_clone(const Buffer &buffer) { if (!buffer_exists(buffer)) { return Handle(); } else { uintptr_t size = buffer.getUsedSize(); if (size == 0) { // Buffers of zero elements are reused with reference counting. return buffer; } else { // Allocate new memory without setting it to zero, before cloning data into it. Buffer result = handle_createArray(AllocationInitialization::Uninitialized, size); SafePointer source = buffer_getSafeData(buffer, "Buffer cloning source"); SafePointer target = buffer_getSafeData(result, "Buffer cloning target"); safeMemoryCopy(target, source, size); return result; } } } intptr_t buffer_getSize(const Buffer &buffer) { return buffer.getUsedSize(); } intptr_t buffer_getUseCount(const Buffer &buffer) { return buffer.getUseCount(); } uint8_t* buffer_dangerous_getUnsafeData(const Buffer &buffer) { return buffer.getUnsafe(); } void buffer_setBytes(const Buffer &buffer, uint8_t value) { if (buffer.isNull()) { throwError(U"buffer_setBytes: Can not set bytes for a buffer that does not exist.\n"); } else { uintptr_t size = buffer.getUsedSize(); if (size > 0) { SafePointer target = buffer_getSafeData(buffer, "Buffer set target"); safeMemorySet(target, value, size); } } } }