Browse Source

Created a Buffer API to allow using it directly in projects.

David Piuva 5 years ago
parent
commit
2145807c87

+ 53 - 21
Source/DFPSR/base/Buffer.cpp → Source/DFPSR/api/bufferAPI.cpp

@@ -1,6 +1,6 @@
 // zlib open source license
 // 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
 // This software is provided 'as-is', without any express or implied
 // warranty. In no event will the authors be held liable for any damages
 // 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
 //    3. This notice may not be removed or altered from any source
 //    distribution.
 //    distribution.
 
 
-#include "Buffer.h"
 #include <cstdlib>
 #include <cstdlib>
+#include "bufferAPI.h"
 #include "../math/scalar.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
 // buffer_alignment must be a power of two for buffer_alignment_mask to work
 static const int buffer_alignment = 16;
 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
 // If this C++ version additionally includes the C11 features then we may assume that aligned_alloc is available
 #ifdef _ISOC11_SOURCE
 #ifdef _ISOC11_SOURCE
 	// Allocate data of newSize and write the corresponding destructor function to targetDestructor
 	// 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);
 		uint8_t* allocation = (uint8_t*)aligned_alloc(buffer_alignment, newSize);
 		targetDestructor = [](uint8_t *data) { free(data); };
 		targetDestructor = [](uint8_t *data) { free(data); };
 		return allocation;
 		return allocation;
 	}
 	}
 #else
 #else
 	// Allocate data of newSize and write the corresponding destructor function to targetDestructor
 	// 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;
 		uintptr_t padding = buffer_alignment - 1;
 		uint8_t* allocation = (uint8_t*)malloc(newSize + padding);
 		uint8_t* allocation = (uint8_t*)malloc(newSize + padding);
 		uint8_t* aligned = (uint8_t*)(((uintptr_t)allocation + padding) & buffer_alignment_mask);
 		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
 #endif
 
 
-Buffer::Buffer(int32_t newSize) :
+BufferImpl::BufferImpl(int64_t newSize) :
   size(newSize),
   size(newSize),
   bufferSize(roundUp(newSize, buffer_alignment)) {
   bufferSize(roundUp(newSize, buffer_alignment)) {
 	this->data = buffer_allocate(this->bufferSize, this->destructor);
 	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); }) {}
 : size(newSize), bufferSize(newSize), data(newData), destructor([](uint8_t *data) { free(data); }) {}
 
 
-Buffer::~Buffer() {
+BufferImpl::~BufferImpl() {
 	this->destructor(this->data);
 	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);
+}
+
+}

+ 76 - 0
Source/DFPSR/api/bufferAPI.h

@@ -0,0 +1,76 @@
+// zlib open source license
+//
+// Copyright (c) 2018 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
+// 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.
+
+#ifndef DFPSR_API_BUFFER
+#define DFPSR_API_BUFFER
+
+#include <stdint.h>
+#include <memory>
+#include <functional>
+#include "../base/SafePointer.h"
+
+namespace dsr {
+	// A safer replacement for raw memory allocation when you don't need to resize the content.
+	// Guarantees that internal addresses will not be invalidated during its lifetime.
+	//   Just remember to always keep a handle together with any pointers to the data to prevent the buffer from being freed.
+	class BufferImpl;
+	using Buffer = std::shared_ptr<BufferImpl>;
+
+	// Creates a new buffer of newSize bytes.
+	Buffer buffer_create(int64_t newSize);
+
+	// Creates a new buffer of newSize bytes inheriting ownership of newData.
+	//   If the given data cannot be freed as a C allocation, replaceDestructor must be called with the special destructor.
+	Buffer buffer_create(int64_t newSize, uint8_t *newData);
+
+	// Sets the allocation's destructor, to be called when there are no more reference counted pointers to the buffer.
+	void buffer_replaceDestructor(Buffer buffer, const std::function<void(uint8_t *)>& newDestructor);
+
+	// Returns true iff the handle points to a buffer
+	inline bool buffer_exists(Buffer buffer) {
+		return buffer.get() != nullptr;
+	}
+
+	// Returns a clone of the buffer.
+	Buffer buffer_clone(Buffer buffer);
+
+	// Returns the buffer's size in bytes, as given when allocating it excluding allocation padding
+	int64_t buffer_getSize(Buffer buffer);
+
+	// Returns a raw pointer to the data.
+	uint8_t* buffer_dangerous_getUnsafeData(Buffer buffer);
+
+	// A wrapper for getting a bound-checked pointer of the correct element type.
+	//   Only cast to trivially packed types with power of two dimensions so that the compiler does not add padding.
+	// The name must be an ansi encoded constant literal, because each String contains a Buffer which would cause a cyclic dependency.
+	template <typename T>
+	SafePointer<T> buffer_getSafeData(Buffer buffer, const char* name) {
+		uint8_t *data = buffer_dangerous_getUnsafeData(buffer);
+		return SafePointer<T>(name, (T*)data, buffer_getSize(buffer), (T*)data);
+	}
+
+	// Set all bytes to the same value
+	void buffer_setBytes(Buffer buffer, uint8_t value);
+}
+
+#endif

+ 4 - 4
Source/DFPSR/api/imageAPI.cpp

@@ -718,16 +718,16 @@ SafePointer<uint8_t> dsr::image_getSafePointer_channels(const ImageRgbaU8& image
 }
 }
 
 
 void dsr::image_dangerous_replaceDestructor(ImageU8& image, const std::function<void(uint8_t *)>& newDestructor) {
 void dsr::image_dangerous_replaceDestructor(ImageU8& image, const std::function<void(uint8_t *)>& newDestructor) {
-	if (image) { return image->buffer->replaceDestructor(newDestructor); }
+	if (image) { return buffer_replaceDestructor(image->buffer, newDestructor); }
 }
 }
 void dsr::image_dangerous_replaceDestructor(ImageU16& image, const std::function<void(uint8_t *)>& newDestructor) {
 void dsr::image_dangerous_replaceDestructor(ImageU16& image, const std::function<void(uint8_t *)>& newDestructor) {
-	if (image) { return image->buffer->replaceDestructor(newDestructor); }
+	if (image) { return buffer_replaceDestructor(image->buffer, newDestructor); }
 }
 }
 void dsr::image_dangerous_replaceDestructor(ImageF32& image, const std::function<void(uint8_t *)>& newDestructor) {
 void dsr::image_dangerous_replaceDestructor(ImageF32& image, const std::function<void(uint8_t *)>& newDestructor) {
-	if (image) { return image->buffer->replaceDestructor(newDestructor); }
+	if (image) { return buffer_replaceDestructor(image->buffer, newDestructor); }
 }
 }
 void dsr::image_dangerous_replaceDestructor(ImageRgbaU8& image, const std::function<void(uint8_t *)>& newDestructor) {
 void dsr::image_dangerous_replaceDestructor(ImageRgbaU8& image, const std::function<void(uint8_t *)>& newDestructor) {
-	if (image) { return image->buffer->replaceDestructor(newDestructor); }
+	if (image) { return buffer_replaceDestructor(image->buffer, newDestructor); }
 }
 }
 
 
 uint8_t* dsr::image_dangerous_getData(const ImageU8& image) {
 uint8_t* dsr::image_dangerous_getData(const ImageU8& image) {

+ 0 - 81
Source/DFPSR/base/Buffer.h

@@ -1,81 +0,0 @@
-// zlib open source license
-//
-// Copyright (c) 2017 to 2019 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.
-
-#ifndef DFPSR_BUFFER
-#define DFPSR_BUFFER
-
-#include <stdint.h>
-#include <memory>
-#include <functional>
-#include "SafePointer.h"
-
-namespace dsr {
-
-class Buffer {
-public:
-	const int32_t size; // The actually used data
-	const int32_t bufferSize; // The accessible data
-private:
-	uint8_t *data;
-	std::function<void(uint8_t *)> destructor;
-public:
-	explicit Buffer(int32_t newSize);
-	Buffer(int32_t newSize, uint8_t *newData);
-	~Buffer();
-public:
-	void replaceDestructor(const std::function<void(uint8_t *)>& newDestructor);
-	// Set all bytes to the same value
-	void set(uint8_t value);
-	// Get a dangerous pointer to the raw data
-	uint8_t *getUnsafeData() {
-		return this->data;
-	}
-	const uint8_t *getUnsafeData() const {
-		return this->data;
-	}
-	// Get a safe pointer to the raw data
-	template <typename T>
-	SafePointer<T> getSafeData(const char *name) {
-		return SafePointer<T>(name, (T*)this->data, this->bufferSize, (T*)this->data);
-	}
-	template <typename T>
-	const SafePointer<T> getSafeData(const char *name) const {
-		return SafePointer<T>(name, (T*)this->data, this->bufferSize, (T*)this->data);
-	}
-	// Get a part of the buffer
-	template <typename T>
-	SafePointer<T> getSafeSlice(const char *name, int offset, int size) {
-		return SafePointer<T>(name, (T*)this->data, this->bufferSize, (T*)this->data).slice(name, offset, size);
-	}
-	std::shared_ptr<Buffer> clone() const;
-	static std::shared_ptr<Buffer> create(int32_t newSize);
-	static std::shared_ptr<Buffer> create(int32_t newSize, uint8_t *newData);
-	// No implicit copies, only pass by reference or pointer
-	Buffer(const Buffer&) = delete;
-	Buffer& operator=(const Buffer&) = delete;
-};
-
-}
-
-#endif
-

+ 27 - 9
Source/DFPSR/base/text.cpp

@@ -1,6 +1,6 @@
 // zlib open source license
 // zlib open source license
 //
 //
-// Copyright (c) 2017 to 2019 David Forsgren Piuva
+// Copyright (c) 2017 to 2020 David Forsgren Piuva
 // 
 // 
 // This software is provided 'as-is', without any express or implied
 // This software is provided 'as-is', without any express or implied
 // warranty. In no event will the authors be held liable for any damages
 // warranty. In no event will the authors be held liable for any damages
@@ -468,14 +468,14 @@ String dsr::string_loadFromMemory(const Buffer &fileContent) {
 	UTF32WriterFunction measurer = [&characterCount](DsrChar character) {
 	UTF32WriterFunction measurer = [&characterCount](DsrChar character) {
 		characterCount++;
 		characterCount++;
 	};
 	};
-	feedStringFromFileBuffer(measurer, fileContent.getUnsafeData(), fileContent.size);
+	feedStringFromFileBuffer(measurer, buffer_dangerous_getUnsafeData(fileContent), buffer_getSize(fileContent));
 	// Pre-allocate the correct amount of memory based on the simulation
 	// Pre-allocate the correct amount of memory based on the simulation
 	result.reserve(characterCount);
 	result.reserve(characterCount);
 	// Stream output to the result string
 	// Stream output to the result string
 	UTF32WriterFunction reciever = [&result](DsrChar character) {
 	UTF32WriterFunction reciever = [&result](DsrChar character) {
 		result.appendChar(character);
 		result.appendChar(character);
 	};
 	};
-	feedStringFromFileBuffer(reciever, fileContent.getUnsafeData(), fileContent.size);
+	feedStringFromFileBuffer(reciever, buffer_dangerous_getUnsafeData(fileContent), buffer_getSize(fileContent));
 	return result;
 	return result;
 }
 }
 
 
@@ -643,6 +643,7 @@ static void encodeText(const ByteWriterFunction &receiver, String content) {
 		} \
 		} \
 	}
 	}
 
 
+// TODO: Encoding to a buffer first and sending it all at once will be faster on certain operating systems
 void dsr::string_save(const ReadableString& filename, const ReadableString& content, CharacterEncoding characterEncoding, LineEncoding lineEncoding) {
 void dsr::string_save(const ReadableString& filename, const ReadableString& content, CharacterEncoding characterEncoding, LineEncoding lineEncoding) {
 	// TODO: Load files using Unicode filenames
 	// TODO: Load files using Unicode filenames
 	TO_RAW_ASCII(asciiFilename, filename);
 	TO_RAW_ASCII(asciiFilename, filename);
@@ -658,6 +659,23 @@ void dsr::string_save(const ReadableString& filename, const ReadableString& cont
 	}
 	}
 }
 }
 
 
+/*
+void dsr::string_saveToMemory(Buffer &target, const ReadableString& content,
+  CharacterEncoding characterEncoding = CharacterEncoding::BOM_UTF8,
+  LineEncoding lineEncoding = LineEncoding::CrLf) {
+	int64_t byteCount = 0;
+	ByteWriterFunction counter = [&fileStream](uint8_t value) {
+		byteCount++;
+	};
+	
+	ENCODE_TEXT(receiver, content, characterEncoding, lineEncoding);
+	ByteWriterFunction receiver = [&fileStream](uint8_t value) {
+		fileStream.write((const char*)&value, 1);
+	};
+
+}
+*/
+
 const char32_t* dsr::file_separator() {
 const char32_t* dsr::file_separator() {
 	#ifdef _WIN32
 	#ifdef _WIN32
 		return U"\\";
 		return U"\\";
@@ -714,7 +732,7 @@ String::String(const std::string& source) { this->append(source); }
 String::String(const ReadableString& source) { this->append(source); }
 String::String(const ReadableString& source) { this->append(source); }
 String::String(const String& source) { this->append(source); }
 String::String(const String& source) { this->append(source); }
 
 
-String::String(std::shared_ptr<Buffer> buffer, DsrChar *content, int sectionLength)
+String::String(Buffer buffer, DsrChar *content, int sectionLength)
  : ReadableString(content, sectionLength), buffer(buffer), writeSection(content) {}
  : ReadableString(content, sectionLength), buffer(buffer), writeSection(content) {}
 
 
 int String::capacity() {
 int String::capacity() {
@@ -722,11 +740,11 @@ int String::capacity() {
 		return 0;
 		return 0;
 	} else {
 	} else {
 		// Get the parent allocation
 		// Get the parent allocation
-		uint8_t* parentBuffer = this->buffer->getUnsafeData();
+		uint8_t* parentBuffer = buffer_dangerous_getUnsafeData(this->buffer);
 		// Get the offset from the parent
 		// Get the offset from the parent
 		intptr_t offset = (uint8_t*)this->writeSection - parentBuffer;
 		intptr_t offset = (uint8_t*)this->writeSection - parentBuffer;
 		// Subtract offset from the buffer size to get the remaining space
 		// Subtract offset from the buffer size to get the remaining space
-		return (this->buffer->size - offset) / sizeof(DsrChar);
+		return (buffer_getSize(this->buffer) - offset) / sizeof(DsrChar);
 	}
 	}
 }
 }
 
 
@@ -781,10 +799,10 @@ static int32_t getNewBufferSize(int32_t minimumSize) {
 }
 }
 void String::reallocateBuffer(int32_t newLength, bool preserve) {
 void String::reallocateBuffer(int32_t newLength, bool preserve) {
 	// Holding oldData alive while copying to the new buffer
 	// Holding oldData alive while copying to the new buffer
-	std::shared_ptr<Buffer> oldBuffer = this->buffer;
+	Buffer oldBuffer = this->buffer;
 	const char32_t* oldData = this->readSection;
 	const char32_t* oldData = this->readSection;
-	this->buffer = std::make_shared<Buffer>(getNewBufferSize(newLength * sizeof(DsrChar)));
-	this->readSection = this->writeSection = reinterpret_cast<char32_t*>(this->buffer->getUnsafeData());
+	this->buffer = buffer_create(getNewBufferSize(newLength * sizeof(DsrChar)));
+	this->readSection = this->writeSection = reinterpret_cast<char32_t*>(buffer_dangerous_getUnsafeData(this->buffer));
 	if (preserve && oldData) {
 	if (preserve && oldData) {
 		memcpy(this->writeSection, oldData, this->sectionLength * sizeof(DsrChar));
 		memcpy(this->writeSection, oldData, this->sectionLength * sizeof(DsrChar));
 	}
 	}

+ 10 - 4
Source/DFPSR/base/text.h

@@ -1,6 +1,6 @@
 // zlib open source license
 // zlib open source license
 //
 //
-// Copyright (c) 2017 to 2019 David Forsgren Piuva
+// Copyright (c) 2017 to 2020 David Forsgren Piuva
 // 
 // 
 // This software is provided 'as-is', without any express or implied
 // This software is provided 'as-is', without any express or implied
 // warranty. In no event will the authors be held liable for any damages
 // warranty. In no event will the authors be held liable for any damages
@@ -31,7 +31,7 @@
 #include <iostream>
 #include <iostream>
 #include <sstream>
 #include <sstream>
 
 
-#include "Buffer.h"
+#include "../api/bufferAPI.h"
 #include "../collection/List.h"
 #include "../collection/List.h"
 
 
 namespace dsr {
 namespace dsr {
@@ -117,11 +117,11 @@ public:
 class String : public ReadableString {
 class String : public ReadableString {
 protected:
 protected:
 	// A reference counted pointer to the buffer, just to keep the allocation
 	// A reference counted pointer to the buffer, just to keep the allocation
-	std::shared_ptr<Buffer> buffer;
+	Buffer buffer;
 	// Same as readSection, but with write access
 	// Same as readSection, but with write access
 	char32_t* writeSection = nullptr;
 	char32_t* writeSection = nullptr;
 	// Internal constructor
 	// Internal constructor
-	String(std::shared_ptr<Buffer> buffer, DsrChar *content, int sectionLength);
+	String(Buffer buffer, DsrChar *content, int sectionLength);
 public:
 public:
 	// The number of DsrChar characters that can be contained in the allocation before reaching the buffer's end
 	// The number of DsrChar characters that can be contained in the allocation before reaching the buffer's end
 	//   This doesn't imply that it's always okay to write to the remaining space, because the buffer may be shared
 	//   This doesn't imply that it's always okay to write to the remaining space, because the buffer may be shared
@@ -312,6 +312,12 @@ void string_save(const ReadableString& filename, const ReadableString& content,
   CharacterEncoding characterEncoding = CharacterEncoding::BOM_UTF8,
   CharacterEncoding characterEncoding = CharacterEncoding::BOM_UTF8,
   LineEncoding lineEncoding = LineEncoding::CrLf
   LineEncoding lineEncoding = LineEncoding::CrLf
 );
 );
+/*
+void string_saveToMemory(Buffer &target, const ReadableString& content,
+  CharacterEncoding characterEncoding = CharacterEncoding::BOM_UTF8,
+  LineEncoding lineEncoding = LineEncoding::CrLf
+);
+*/
 
 
 // Post-condition: Returns true iff strings a and b are exactly equal.
 // Post-condition: Returns true iff strings a and b are exactly equal.
 bool string_match(const ReadableString& a, const ReadableString& b);
 bool string_match(const ReadableString& a, const ReadableString& b);

+ 2 - 2
Source/DFPSR/image/Image.cpp

@@ -25,12 +25,12 @@
 
 
 using namespace dsr;
 using namespace dsr;
 
 
-ImageImpl::ImageImpl(int32_t width, int32_t height, int32_t stride, int32_t pixelSize, std::shared_ptr<Buffer> buffer, intptr_t startOffset) :
+ImageImpl::ImageImpl(int32_t width, int32_t height, int32_t stride, int32_t pixelSize, Buffer buffer, intptr_t startOffset) :
   width(width), height(height), stride(stride), pixelSize(pixelSize), buffer(buffer), startOffset(startOffset), isSubImage(true) {
   width(width), height(height), stride(stride), pixelSize(pixelSize), buffer(buffer), startOffset(startOffset), isSubImage(true) {
 	this->validate();
 	this->validate();
 }
 }
 
 
 ImageImpl::ImageImpl(int32_t width, int32_t height, int32_t stride, int32_t pixelSize) :
 ImageImpl::ImageImpl(int32_t width, int32_t height, int32_t stride, int32_t pixelSize) :
-  width(width), height(height), stride(stride), pixelSize(pixelSize), buffer(Buffer::create(stride * height)), startOffset(0), isSubImage(false) {
+  width(width), height(height), stride(stride), pixelSize(pixelSize), buffer(buffer_create(stride * height)), startOffset(0), isSubImage(false) {
 	this->validate();
 	this->validate();
 }
 }

+ 3 - 3
Source/DFPSR/image/Image.h

@@ -27,7 +27,7 @@
 #include <cassert>
 #include <cassert>
 #include <stdint.h>
 #include <stdint.h>
 #include "../base/SafePointer.h"
 #include "../base/SafePointer.h"
-#include "../base/Buffer.h"
+#include "../api/bufferAPI.h"
 #include "../math/scalar.h"
 #include "../math/scalar.h"
 #include "../math/IRect.h"
 #include "../math/IRect.h"
 #include "PackOrder.h"
 #include "PackOrder.h"
@@ -39,7 +39,7 @@ namespace dsr {
 class ImageImpl {
 class ImageImpl {
 public:
 public:
 	const int32_t width, height, stride, pixelSize;
 	const int32_t width, height, stride, pixelSize;
-	std::shared_ptr<Buffer> buffer; // Content
+	Buffer buffer; // Content
 	const intptr_t startOffset; // Byte offset of the first pixel
 	const intptr_t startOffset; // Byte offset of the first pixel
 	bool isSubImage = false;
 	bool isSubImage = false;
 private:
 private:
@@ -53,7 +53,7 @@ private:
 	}
 	}
 public:
 public:
 	// Sub-images
 	// Sub-images
-	ImageImpl(int32_t width, int32_t height, int32_t stride, int32_t pixelSize, std::shared_ptr<Buffer> buffer, intptr_t startOffset);
+	ImageImpl(int32_t width, int32_t height, int32_t stride, int32_t pixelSize, Buffer buffer, intptr_t startOffset);
 	// New images
 	// New images
 	ImageImpl(int32_t width, int32_t height, int32_t stride, int32_t pixelSize);
 	ImageImpl(int32_t width, int32_t height, int32_t stride, int32_t pixelSize);
 };
 };

+ 2 - 2
Source/DFPSR/image/ImageF32.cpp

@@ -27,9 +27,9 @@
 
 
 using namespace dsr;
 using namespace dsr;
 
 
-ImageF32Impl::ImageF32Impl(int32_t newWidth, int32_t newHeight, int32_t newStride, std::shared_ptr<Buffer> buffer, intptr_t startOffset) :
+ImageF32Impl::ImageF32Impl(int32_t newWidth, int32_t newHeight, int32_t newStride, Buffer buffer, intptr_t startOffset) :
   ImageImpl(newWidth, newHeight, newStride, sizeof(float), buffer, startOffset) {
   ImageImpl(newWidth, newHeight, newStride, sizeof(float), buffer, startOffset) {
-	assert(buffer->size - startOffset >= imageInternal::getUsedBytes(this));
+	assert(buffer_getSize(buffer) - startOffset >= imageInternal::getUsedBytes(this));
 }
 }
 
 
 ImageF32Impl::ImageF32Impl(int32_t newWidth, int32_t newHeight, int32_t alignment) :
 ImageF32Impl::ImageF32Impl(int32_t newWidth, int32_t newHeight, int32_t alignment) :

+ 1 - 2
Source/DFPSR/image/ImageF32.h

@@ -34,7 +34,7 @@ public:
 	static const int32_t pixelSize = 4;
 	static const int32_t pixelSize = 4;
 	// Inherit constructors
 	// Inherit constructors
 	using ImageImpl::ImageImpl;
 	using ImageImpl::ImageImpl;
-	ImageF32Impl(int32_t newWidth, int32_t newHeight, int32_t newStride, std::shared_ptr<Buffer> buffer, intptr_t startOffset);
+	ImageF32Impl(int32_t newWidth, int32_t newHeight, int32_t newStride, Buffer buffer, intptr_t startOffset);
 	ImageF32Impl(int32_t newWidth, int32_t newHeight, int32_t alignment = 16);
 	ImageF32Impl(int32_t newWidth, int32_t newHeight, int32_t alignment = 16);
 	// Macro defined functions
 	// Macro defined functions
 	IMAGE_DECLARATION(ImageF32Impl, 1, float, float);
 	IMAGE_DECLARATION(ImageF32Impl, 1, float, float);
@@ -43,4 +43,3 @@ public:
 }
 }
 
 
 #endif
 #endif
-

+ 6 - 6
Source/DFPSR/image/ImageRgbaU8.cpp

@@ -30,9 +30,9 @@ using namespace dsr;
 
 
 IMAGE_DEFINITION(ImageRgbaU8Impl, 4, Color4xU8, uint8_t);
 IMAGE_DEFINITION(ImageRgbaU8Impl, 4, Color4xU8, uint8_t);
 
 
-ImageRgbaU8Impl::ImageRgbaU8Impl(int32_t newWidth, int32_t newHeight, int32_t newStride, std::shared_ptr<Buffer> buffer, intptr_t startOffset, PackOrder packOrder) :
+ImageRgbaU8Impl::ImageRgbaU8Impl(int32_t newWidth, int32_t newHeight, int32_t newStride, Buffer buffer, intptr_t startOffset, PackOrder packOrder) :
   ImageImpl(newWidth, newHeight, newStride, sizeof(Color4xU8), buffer, startOffset), packOrder(packOrder) {
   ImageImpl(newWidth, newHeight, newStride, sizeof(Color4xU8), buffer, startOffset), packOrder(packOrder) {
-	assert(buffer->size - startOffset >= imageInternal::getUsedBytes(this));
+	assert(buffer_getSize(buffer) - startOffset >= imageInternal::getUsedBytes(this));
 	this->initializeRgbaImage();
 	this->initializeRgbaImage();
 }
 }
 
 
@@ -209,7 +209,7 @@ void ImageRgbaU8Impl::generatePyramid() {
 		int32_t pixelSize = this->pixelSize;
 		int32_t pixelSize = this->pixelSize;
 		int32_t mipmaps = std::min(std::max(getSizeGroup(std::min(this->width, this->height)) - 1, 1), MIP_BIN_COUNT);
 		int32_t mipmaps = std::min(std::max(getSizeGroup(std::min(this->width, this->height)) - 1, 1), MIP_BIN_COUNT);
 		if (!this->texture.hasMipBuffer()) {
 		if (!this->texture.hasMipBuffer()) {
-			this->texture.pyramidBuffer = Buffer::create(getPyramidSize(this->width / 2, this->height / 2, pixelSize, mipmaps - 1));
+			this->texture.pyramidBuffer = buffer_create(getPyramidSize(this->width / 2, this->height / 2, pixelSize, mipmaps - 1));
 		}
 		}
 		// Point to the image's original buffer in mip level 0
 		// Point to the image's original buffer in mip level 0
 		SafePointer<uint8_t> currentStart = imageInternal::getSafeData<uint8_t>(*this);
 		SafePointer<uint8_t> currentStart = imageInternal::getSafeData<uint8_t>(*this);
@@ -218,7 +218,7 @@ void ImageRgbaU8Impl::generatePyramid() {
 		this->texture.mips[0] = TextureRgbaLayer(currentStart.getUnsafe(), currentWidth, currentHeight);
 		this->texture.mips[0] = TextureRgbaLayer(currentStart.getUnsafe(), currentWidth, currentHeight);
 		// Create smaller pyramid images in the extra buffer
 		// Create smaller pyramid images in the extra buffer
 		SafePointer<uint8_t> previousStart = currentStart;
 		SafePointer<uint8_t> previousStart = currentStart;
-		currentStart = this->texture.pyramidBuffer->getSafeData<uint8_t>("Pyramid generation target");
+		currentStart = buffer_getSafeData<uint8_t>(this->texture.pyramidBuffer, "Pyramid generation target");
 		for (int32_t m = 1; m < mipmaps; m++) {
 		for (int32_t m = 1; m < mipmaps; m++) {
 			currentWidth /= 2;
 			currentWidth /= 2;
 			currentHeight /= 2;
 			currentHeight /= 2;
@@ -238,9 +238,9 @@ void ImageRgbaU8Impl::generatePyramid() {
 
 
 void ImageRgbaU8Impl::removePyramid() {
 void ImageRgbaU8Impl::removePyramid() {
 	// Only try to remove if it has a pyramid
 	// Only try to remove if it has a pyramid
-	if (this->texture.pyramidBuffer.get() != nullptr) {
+	if (buffer_exists(this->texture.pyramidBuffer)) {
 		// Remove the pyramid's buffer
 		// Remove the pyramid's buffer
-		this->texture.pyramidBuffer = std::shared_ptr<Buffer>();
+		this->texture.pyramidBuffer = Buffer();
 		// Re-initialize
 		// Re-initialize
 		for (int32_t m = 0; m < MIP_BIN_COUNT; m++) {
 		for (int32_t m = 0; m < MIP_BIN_COUNT; m++) {
 			this->texture.mips[m] = TextureRgbaLayer(imageInternal::getSafeData<uint8_t>(*this).getUnsafe(), this->width, this->height);
 			this->texture.mips[m] = TextureRgbaLayer(imageInternal::getSafeData<uint8_t>(*this).getUnsafe(), this->width, this->height);

+ 2 - 3
Source/DFPSR/image/ImageRgbaU8.h

@@ -48,7 +48,7 @@ struct TextureRgbaLayer {
 
 
 // Pointing to the parent image using raw pointers for fast rendering. Not not separate from the image!
 // Pointing to the parent image using raw pointers for fast rendering. Not not separate from the image!
 struct TextureRgba {
 struct TextureRgba {
-	std::shared_ptr<Buffer> pyramidBuffer; // Storing the smaller mip levels
+	Buffer pyramidBuffer; // Storing the smaller mip levels
 	TextureRgbaLayer mips[MIP_BIN_COUNT]; // Pointing to all mip levels including the original image
 	TextureRgbaLayer mips[MIP_BIN_COUNT]; // Pointing to all mip levels including the original image
 	// Can it be sampled as a texture
 	// Can it be sampled as a texture
 	bool exists() const { return this->mips[0].exists(); }
 	bool exists() const { return this->mips[0].exists(); }
@@ -64,7 +64,7 @@ public:
 	// Macro defined functions
 	// Macro defined functions
 	IMAGE_DECLARATION(ImageRgbaU8Impl, 4, Color4xU8, uint8_t);
 	IMAGE_DECLARATION(ImageRgbaU8Impl, 4, Color4xU8, uint8_t);
 	// Constructors
 	// Constructors
-	ImageRgbaU8Impl(int32_t newWidth, int32_t newHeight, int32_t newStride, std::shared_ptr<Buffer> buffer, intptr_t startOffset, PackOrder packOrder);
+	ImageRgbaU8Impl(int32_t newWidth, int32_t newHeight, int32_t newStride, Buffer buffer, intptr_t startOffset, PackOrder packOrder);
 	ImageRgbaU8Impl(int32_t newWidth, int32_t newHeight, int32_t alignment = 16);
 	ImageRgbaU8Impl(int32_t newWidth, int32_t newHeight, int32_t alignment = 16);
 	// Native canvas constructor
 	// Native canvas constructor
 	ImageRgbaU8Impl(int32_t newWidth, int32_t newHeight, PackOrderIndex packOrderIndex);
 	ImageRgbaU8Impl(int32_t newWidth, int32_t newHeight, PackOrderIndex packOrderIndex);
@@ -96,4 +96,3 @@ public:
 }
 }
 
 
 #endif
 #endif
-

+ 2 - 2
Source/DFPSR/image/ImageU16.cpp

@@ -27,9 +27,9 @@
 
 
 using namespace dsr;
 using namespace dsr;
 
 
-ImageU16Impl::ImageU16Impl(int32_t newWidth, int32_t newHeight, int32_t newStride, std::shared_ptr<Buffer> buffer, intptr_t startOffset) :
+ImageU16Impl::ImageU16Impl(int32_t newWidth, int32_t newHeight, int32_t newStride, Buffer buffer, intptr_t startOffset) :
   ImageImpl(newWidth, newHeight, newStride, sizeof(uint16_t), buffer, startOffset) {
   ImageImpl(newWidth, newHeight, newStride, sizeof(uint16_t), buffer, startOffset) {
-	assert(buffer->size - startOffset >= imageInternal::getUsedBytes(this));
+	assert(buffer_getSize(buffer) - startOffset >= imageInternal::getUsedBytes(this));
 }
 }
 
 
 ImageU16Impl::ImageU16Impl(int32_t newWidth, int32_t newHeight, int32_t alignment) :
 ImageU16Impl::ImageU16Impl(int32_t newWidth, int32_t newHeight, int32_t alignment) :

+ 1 - 2
Source/DFPSR/image/ImageU16.h

@@ -35,7 +35,7 @@ public:
 	static const int32_t pixelSize = 2;
 	static const int32_t pixelSize = 2;
 	// Inherit constructors
 	// Inherit constructors
 	using ImageImpl::ImageImpl;
 	using ImageImpl::ImageImpl;
-	ImageU16Impl(int32_t newWidth, int32_t newHeight, int32_t newStride, std::shared_ptr<Buffer> buffer, intptr_t startOffset);
+	ImageU16Impl(int32_t newWidth, int32_t newHeight, int32_t newStride, Buffer buffer, intptr_t startOffset);
 	ImageU16Impl(int32_t newWidth, int32_t newHeight, int32_t alignment = 16);
 	ImageU16Impl(int32_t newWidth, int32_t newHeight, int32_t alignment = 16);
 	// Macro defined functions
 	// Macro defined functions
 	IMAGE_DECLARATION(ImageU16Impl, 1, uint16_t, uint16_t);
 	IMAGE_DECLARATION(ImageU16Impl, 1, uint16_t, uint16_t);
@@ -44,4 +44,3 @@ public:
 }
 }
 
 
 #endif
 #endif
-

+ 2 - 2
Source/DFPSR/image/ImageU8.cpp

@@ -27,9 +27,9 @@
 
 
 using namespace dsr;
 using namespace dsr;
 
 
-ImageU8Impl::ImageU8Impl(int32_t newWidth, int32_t newHeight, int32_t newStride, std::shared_ptr<Buffer> buffer, intptr_t startOffset) :
+ImageU8Impl::ImageU8Impl(int32_t newWidth, int32_t newHeight, int32_t newStride, Buffer buffer, intptr_t startOffset) :
   ImageImpl(newWidth, newHeight, newStride, sizeof(uint8_t), buffer, startOffset) {
   ImageImpl(newWidth, newHeight, newStride, sizeof(uint8_t), buffer, startOffset) {
-	assert(buffer->size - startOffset >= imageInternal::getUsedBytes(this));
+	assert(buffer_getSize(buffer) - startOffset >= imageInternal::getUsedBytes(this));
 }
 }
 
 
 ImageU8Impl::ImageU8Impl(int32_t newWidth, int32_t newHeight, int32_t alignment) :
 ImageU8Impl::ImageU8Impl(int32_t newWidth, int32_t newHeight, int32_t alignment) :

+ 1 - 2
Source/DFPSR/image/ImageU8.h

@@ -35,7 +35,7 @@ public:
 	// Inherit constructors
 	// Inherit constructors
 	using ImageImpl::ImageImpl;
 	using ImageImpl::ImageImpl;
 	// Constructors
 	// Constructors
-	ImageU8Impl(int32_t newWidth, int32_t newHeight, int32_t newStride, std::shared_ptr<Buffer> buffer, intptr_t startOffset);
+	ImageU8Impl(int32_t newWidth, int32_t newHeight, int32_t newStride, Buffer buffer, intptr_t startOffset);
 	ImageU8Impl(int32_t newWidth, int32_t newHeight, int32_t alignment = 16);
 	ImageU8Impl(int32_t newWidth, int32_t newHeight, int32_t alignment = 16);
 	// Macro defined functions
 	// Macro defined functions
 	IMAGE_DECLARATION(ImageU8Impl, 1, uint8_t, uint8_t);
 	IMAGE_DECLARATION(ImageU8Impl, 1, uint8_t, uint8_t);
@@ -44,4 +44,3 @@ public:
 }
 }
 
 
 #endif
 #endif
-

+ 2 - 2
Source/DFPSR/image/draw.cpp

@@ -266,11 +266,11 @@ struct ImageReader : public ImageDimensions {
 };
 };
 
 
 static ImageWriter getWriter(ImageImpl &image) {
 static ImageWriter getWriter(ImageImpl &image) {
-	return ImageWriter(ImageDimensions(image), image.buffer->getUnsafeData() + image.startOffset);
+	return ImageWriter(ImageDimensions(image), buffer_dangerous_getUnsafeData(image.buffer) + image.startOffset);
 }
 }
 
 
 static ImageReader getReader(const ImageImpl &image) {
 static ImageReader getReader(const ImageImpl &image) {
-	return ImageReader(ImageDimensions(image), image.buffer->getUnsafeData() + image.startOffset);
+	return ImageReader(ImageDimensions(image), buffer_dangerous_getUnsafeData(image.buffer) + image.startOffset);
 }
 }
 
 
 static ImageImpl getGenericSubImage(const ImageImpl &image, int32_t left, int32_t top, int32_t width, int32_t height) {
 static ImageImpl getGenericSubImage(const ImageImpl &image, int32_t left, int32_t top, int32_t width, int32_t height) {

+ 4 - 5
Source/DFPSR/image/internal/imageInternal.h

@@ -45,19 +45,18 @@ inline int32_t getUsedBytes(const ImageImpl *image) { return image ? getUsedByte
 inline int32_t getPixelSize(const ImageImpl *image) { return image ? image->pixelSize : 0; }
 inline int32_t getPixelSize(const ImageImpl *image) { return image ? image->pixelSize : 0; }
 //inline int32_t getStartOffset(const ImageImpl &image) { return image.startOffset; }
 //inline int32_t getStartOffset(const ImageImpl &image) { return image.startOffset; }
 inline int32_t getStartOffset(const ImageImpl *image) { return image ? image->startOffset : 0; }
 inline int32_t getStartOffset(const ImageImpl *image) { return image ? image->startOffset : 0; }
-inline std::shared_ptr<Buffer> getBuffer(const ImageImpl &image) { return image.buffer; }
-inline std::shared_ptr<Buffer> getBuffer(const ImageImpl *image) { return image ? getBuffer(*image) : std::shared_ptr<Buffer>(); }
+inline Buffer getBuffer(const ImageImpl &image) { return image.buffer; }
+inline Buffer getBuffer(const ImageImpl *image) { return image ? getBuffer(*image) : Buffer(); }
 inline IRect getBound(const ImageImpl &image) { return IRect(0, 0, image.width, image.height); }
 inline IRect getBound(const ImageImpl &image) { return IRect(0, 0, image.width, image.height); }
 inline IRect getBound(const ImageImpl *image) { return image ? getBound(*image) : IRect(); }
 inline IRect getBound(const ImageImpl *image) { return image ? getBound(*image) : IRect(); }
 inline PackOrder getPackOrder(const ImageRgbaU8Impl *image) { return image ? image->packOrder : PackOrder(); }
 inline PackOrder getPackOrder(const ImageRgbaU8Impl *image) { return image ? image->packOrder : PackOrder(); }
 
 
-
 // Get data
 // Get data
 //   The pointer has access to the whole parent buffer,
 //   The pointer has access to the whole parent buffer,
 //   to allow aligning SIMD vectors outside of the used region.
 //   to allow aligning SIMD vectors outside of the used region.
 template <typename T>
 template <typename T>
 static inline const SafePointer<T> getSafeData(const ImageImpl &image, int rowIndex = 0) {
 static inline const SafePointer<T> getSafeData(const ImageImpl &image, int rowIndex = 0) {
-	auto result = image.buffer->getSafeData<T>("Image buffer");
+	auto result = buffer_getSafeData<T>(image.buffer, "Image buffer");
 	result.increaseBytes(image.startOffset + image.stride * rowIndex);
 	result.increaseBytes(image.startOffset + image.stride * rowIndex);
 	return result;
 	return result;
 }
 }
@@ -67,7 +66,7 @@ inline const SafePointer<T> getSafeData(const ImageImpl *image, int rowIndex = 0
 }
 }
 template <typename T>
 template <typename T>
 static inline SafePointer<T> getSafeData(ImageImpl &image, int rowIndex = 0) {
 static inline SafePointer<T> getSafeData(ImageImpl &image, int rowIndex = 0) {
-	auto result = image.buffer->getSafeData<T>("Image buffer");
+	auto result = buffer_getSafeData<T>(image.buffer, "Image buffer");
 	result.increaseBytes(image.startOffset + image.stride * rowIndex);
 	result.increaseBytes(image.startOffset + image.stride * rowIndex);
 	return result;
 	return result;
 }
 }

+ 4 - 4
Source/DFPSR/image/internal/imageTemplate.h

@@ -37,11 +37,11 @@ namespace dsr {
 #define IMAGE_DEFINITION(IMAGE_TYPE,CHANNELS,COLOR_TYPE,ELEMENT_TYPE) \
 #define IMAGE_DEFINITION(IMAGE_TYPE,CHANNELS,COLOR_TYPE,ELEMENT_TYPE) \
 	void IMAGE_TYPE::writePixel(IMAGE_TYPE &image, int32_t x, int32_t y, COLOR_TYPE color) { \
 	void IMAGE_TYPE::writePixel(IMAGE_TYPE &image, int32_t x, int32_t y, COLOR_TYPE color) { \
 		if (x >= 0 && x < image.width && y >= 0 && y < image.height) { \
 		if (x >= 0 && x < image.width && y >= 0 && y < image.height) { \
-			*(COLOR_TYPE*)(image.buffer->getUnsafeData() + image.startOffset + (x * sizeof(COLOR_TYPE)) + (y * image.stride)) = color; \
+			*(COLOR_TYPE*)(buffer_dangerous_getUnsafeData(image.buffer) + image.startOffset + (x * sizeof(COLOR_TYPE)) + (y * image.stride)) = color; \
 		} \
 		} \
 	} \
 	} \
 	void IMAGE_TYPE::writePixel_unsafe(IMAGE_TYPE &image, int32_t x, int32_t y, COLOR_TYPE color) { \
 	void IMAGE_TYPE::writePixel_unsafe(IMAGE_TYPE &image, int32_t x, int32_t y, COLOR_TYPE color) { \
-		*(COLOR_TYPE*)(image.buffer->getUnsafeData() + image.startOffset + (x * sizeof(COLOR_TYPE)) + (y * image.stride)) = color; \
+		*(COLOR_TYPE*)(buffer_dangerous_getUnsafeData(image.buffer) + image.startOffset + (x * sizeof(COLOR_TYPE)) + (y * image.stride)) = color; \
 	} \
 	} \
 	COLOR_TYPE IMAGE_TYPE::readPixel_clamp(const IMAGE_TYPE &image, int32_t x, int32_t y) { \
 	COLOR_TYPE IMAGE_TYPE::readPixel_clamp(const IMAGE_TYPE &image, int32_t x, int32_t y) { \
 		if (image.width > 0 && image.height > 0) { \
 		if (image.width > 0 && image.height > 0) { \
@@ -49,14 +49,14 @@ namespace dsr {
 			if (y < 0) { y = 0; } \
 			if (y < 0) { y = 0; } \
 			if (x >= image.width) { x = image.width - 1; } \
 			if (x >= image.width) { x = image.width - 1; } \
 			if (y >= image.height) { y = image.height - 1; } \
 			if (y >= image.height) { y = image.height - 1; } \
-			return *(COLOR_TYPE*)(image.buffer->getUnsafeData() + image.startOffset + (x * sizeof(COLOR_TYPE)) + (y * image.stride)); \
+			return *(COLOR_TYPE*)(buffer_dangerous_getUnsafeData(image.buffer) + image.startOffset + (x * sizeof(COLOR_TYPE)) + (y * image.stride)); \
 		} else { \
 		} else { \
 			return COLOR_TYPE(); \
 			return COLOR_TYPE(); \
 		} \
 		} \
 	} \
 	} \
 	COLOR_TYPE IMAGE_TYPE::readPixel_unsafe(const IMAGE_TYPE &image, int32_t x, int32_t y) { \
 	COLOR_TYPE IMAGE_TYPE::readPixel_unsafe(const IMAGE_TYPE &image, int32_t x, int32_t y) { \
 		assert(x >= 0 && x < image.width && y >= 0 && y < image.height); \
 		assert(x >= 0 && x < image.width && y >= 0 && y < image.height); \
-		return *(COLOR_TYPE*)(image.buffer->getUnsafeData() + image.startOffset + (x * sizeof(COLOR_TYPE)) + (y * image.stride)); \
+		return *(COLOR_TYPE*)(buffer_dangerous_getUnsafeData(image.buffer) + image.startOffset + (x * sizeof(COLOR_TYPE)) + (y * image.stride)); \
 	}
 	}
 
 
 }
 }

+ 2 - 1
Source/DFPSR/includeFramework.h

@@ -21,6 +21,8 @@
 	#include "api/guiAPI.h" // Handling windows, interfaces and components
 	#include "api/guiAPI.h" // Handling windows, interfaces and components
 	#include "api/mediaMachineAPI.h" // A machine for running image functions
 	#include "api/mediaMachineAPI.h" // A machine for running image functions
 	#include "api/fontAPI.h" // Printing text to images
 	#include "api/fontAPI.h" // Printing text to images
+	// File API
+	#include "api/bufferAPI.h" // Printing text to images
 	// Convenient API
 	// Convenient API
 	#include "api/timeAPI.h" // Methods for time and delays
 	#include "api/timeAPI.h" // Methods for time and delays
 	#include "api/configAPI.h" // Making it easy to load your application's settings from configuration files
 	#include "api/configAPI.h" // Making it easy to load your application's settings from configuration files
@@ -29,4 +31,3 @@
 	#include "gui/VisualTheme.h" // Place in the gui API
 	#include "gui/VisualTheme.h" // Place in the gui API
 
 
 #endif
 #endif
-