|
|
@@ -1,6 +1,6 @@
|
|
|
// zlib open source license
|
|
|
//
|
|
|
-// Copyright (c) 2017 to 2019 David Forsgren Piuva
|
|
|
+// Copyright (c) 2019 to 2020 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
|
|
|
@@ -21,11 +21,32 @@
|
|
|
// 3. This notice may not be removed or altered from any source
|
|
|
// distribution.
|
|
|
|
|
|
-#include "Buffer.h"
|
|
|
#include <cstdlib>
|
|
|
+#include "bufferAPI.h"
|
|
|
#include "../math/scalar.h"
|
|
|
|
|
|
-using namespace dsr;
|
|
|
+namespace dsr {
|
|
|
+
|
|
|
+// Hidden type
|
|
|
+
|
|
|
+class BufferImpl {
|
|
|
+public:
|
|
|
+ // A Buffer cannot have a name, because each String contains a buffer
|
|
|
+ const int64_t size; // The actually used data
|
|
|
+ const int64_t bufferSize; // The accessible data
|
|
|
+ uint8_t *data;
|
|
|
+ std::function<void(uint8_t *)> destructor;
|
|
|
+public:
|
|
|
+ explicit BufferImpl(int64_t newSize);
|
|
|
+ BufferImpl(int64_t newSize, uint8_t *newData);
|
|
|
+ ~BufferImpl();
|
|
|
+public:
|
|
|
+ // No implicit copies, only pass using the Buffer handle
|
|
|
+ BufferImpl(const BufferImpl&) = delete;
|
|
|
+ BufferImpl& operator=(const BufferImpl&) = delete;
|
|
|
+};
|
|
|
+
|
|
|
+// Internal methods
|
|
|
|
|
|
// buffer_alignment must be a power of two for buffer_alignment_mask to work
|
|
|
static const int buffer_alignment = 16;
|
|
|
@@ -34,14 +55,14 @@ static const uintptr_t buffer_alignment_mask = ~((uintptr_t)(buffer_alignment -
|
|
|
// If this C++ version additionally includes the C11 features then we may assume that aligned_alloc is available
|
|
|
#ifdef _ISOC11_SOURCE
|
|
|
// Allocate data of newSize and write the corresponding destructor function to targetDestructor
|
|
|
- static uint8_t* buffer_allocate(int32_t newSize, std::function<void(uint8_t *)>& targetDestructor) {
|
|
|
+ static uint8_t* buffer_allocate(int64_t newSize, std::function<void(uint8_t *)>& targetDestructor) {
|
|
|
uint8_t* allocation = (uint8_t*)aligned_alloc(buffer_alignment, newSize);
|
|
|
targetDestructor = [](uint8_t *data) { free(data); };
|
|
|
return allocation;
|
|
|
}
|
|
|
#else
|
|
|
// Allocate data of newSize and write the corresponding destructor function to targetDestructor
|
|
|
- static uint8_t* buffer_allocate(int32_t newSize, std::function<void(uint8_t *)>& targetDestructor) {
|
|
|
+ static uint8_t* buffer_allocate(int64_t newSize, std::function<void(uint8_t *)>& targetDestructor) {
|
|
|
uintptr_t padding = buffer_alignment - 1;
|
|
|
uint8_t* allocation = (uint8_t*)malloc(newSize + padding);
|
|
|
uint8_t* aligned = (uint8_t*)(((uintptr_t)allocation + padding) & buffer_alignment_mask);
|
|
|
@@ -51,39 +72,50 @@ static const uintptr_t buffer_alignment_mask = ~((uintptr_t)(buffer_alignment -
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-Buffer::Buffer(int32_t newSize) :
|
|
|
+BufferImpl::BufferImpl(int64_t newSize) :
|
|
|
size(newSize),
|
|
|
bufferSize(roundUp(newSize, buffer_alignment)) {
|
|
|
this->data = buffer_allocate(this->bufferSize, this->destructor);
|
|
|
- this->set(0);
|
|
|
+ memset(this->data, 0, this->bufferSize);
|
|
|
}
|
|
|
|
|
|
-Buffer::Buffer(int32_t newSize, uint8_t *newData)
|
|
|
+BufferImpl::BufferImpl(int64_t newSize, uint8_t *newData)
|
|
|
: size(newSize), bufferSize(newSize), data(newData), destructor([](uint8_t *data) { free(data); }) {}
|
|
|
|
|
|
-Buffer::~Buffer() {
|
|
|
+BufferImpl::~BufferImpl() {
|
|
|
this->destructor(this->data);
|
|
|
}
|
|
|
|
|
|
-void Buffer::replaceDestructor(const std::function<void(uint8_t *)>& newDestructor) {
|
|
|
- this->destructor = newDestructor;
|
|
|
+// API
|
|
|
+
|
|
|
+Buffer buffer_clone(Buffer buffer) {
|
|
|
+ Buffer newBuffer = std::make_shared<BufferImpl>(buffer->size);
|
|
|
+ memcpy(newBuffer->data, buffer->data, buffer->size);
|
|
|
+ return newBuffer;
|
|
|
}
|
|
|
|
|
|
-void Buffer::set(uint8_t value) {
|
|
|
- memset(this->data, value, this->bufferSize);
|
|
|
+Buffer buffer_create(int64_t newSize) {
|
|
|
+ return std::make_shared<BufferImpl>(newSize);
|
|
|
}
|
|
|
|
|
|
-std::shared_ptr<Buffer> Buffer::clone() const {
|
|
|
- std::shared_ptr<Buffer> newBuffer = std::make_shared<Buffer>(this->size);
|
|
|
- memcpy(newBuffer->data, this->data, this->size);
|
|
|
- return newBuffer;
|
|
|
+Buffer buffer_create(int64_t newSize, uint8_t *newData) {
|
|
|
+ return std::make_shared<BufferImpl>(newSize, newData);
|
|
|
}
|
|
|
|
|
|
-std::shared_ptr<Buffer> Buffer::create(int32_t newSize) {
|
|
|
- return std::make_shared<Buffer>(newSize);
|
|
|
+void buffer_replaceDestructor(Buffer buffer, const std::function<void(uint8_t *)>& newDestructor) {
|
|
|
+ buffer->destructor = newDestructor;
|
|
|
}
|
|
|
|
|
|
-std::shared_ptr<Buffer> Buffer::create(int32_t newSize, uint8_t *newData) {
|
|
|
- return std::make_shared<Buffer>(newSize, newData);
|
|
|
+int64_t buffer_getSize(Buffer buffer) {
|
|
|
+ return buffer->size;
|
|
|
}
|
|
|
|
|
|
+uint8_t* buffer_dangerous_getUnsafeData(Buffer buffer) {
|
|
|
+ return buffer->data;
|
|
|
+}
|
|
|
+
|
|
|
+void buffer_setBytes(Buffer buffer, uint8_t value) {
|
|
|
+ memset(buffer->data, value, buffer->bufferSize);
|
|
|
+}
|
|
|
+
|
|
|
+}
|