Buffer.cpp 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. // zlib open source license
  2. //
  3. // Copyright (c) 2017 to 2019 David Forsgren Piuva
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any damages
  7. // arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it
  11. // freely, subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented; you must not
  14. // claim that you wrote the original software. If you use this software
  15. // in a product, an acknowledgment in the product documentation would be
  16. // appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such, and must not be
  19. // misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source
  22. // distribution.
  23. #include "Buffer.h"
  24. #include <cstdlib>
  25. #include "../math/scalar.h"
  26. using namespace dsr;
  27. // buffer_alignment must be a power of two for buffer_alignment_mask to work
  28. static const int buffer_alignment = 16;
  29. static const uintptr_t buffer_alignment_mask = ~((uintptr_t)(buffer_alignment - 1));
  30. // If this C++ version additionally includes the C11 features then we may assume that aligned_alloc is available
  31. #ifdef _ISOC11_SOURCE
  32. // Allocate data of newSize and write the corresponding destructor function to targetDestructor
  33. static uint8_t* buffer_allocate(int32_t newSize, std::function<void(uint8_t *)>& targetDestructor) {
  34. uint8_t* allocation = (uint8_t*)aligned_alloc(buffer_alignment, newSize);
  35. targetDestructor = [](uint8_t *data) { free(data); };
  36. return allocation;
  37. }
  38. #else
  39. // Allocate data of newSize and write the corresponding destructor function to targetDestructor
  40. static uint8_t* buffer_allocate(int32_t newSize, std::function<void(uint8_t *)>& targetDestructor) {
  41. uintptr_t padding = buffer_alignment - 1;
  42. uint8_t* allocation = (uint8_t*)malloc(newSize + padding);
  43. uint8_t* aligned = (uint8_t*)(((uintptr_t)allocation + padding) & buffer_alignment_mask);
  44. uintptr_t offset = allocation - aligned;
  45. targetDestructor = [offset](uint8_t *data) { free(data - offset); };
  46. return aligned;
  47. }
  48. #endif
  49. Buffer::Buffer(int32_t newSize) :
  50. size(newSize),
  51. bufferSize(roundUp(newSize, buffer_alignment)) {
  52. this->data = buffer_allocate(this->bufferSize, this->destructor);
  53. this->set(0);
  54. }
  55. Buffer::Buffer(int32_t newSize, uint8_t *newData)
  56. : size(newSize), bufferSize(newSize), data(newData), destructor([](uint8_t *data) { free(data); }) {}
  57. Buffer::~Buffer() {
  58. this->destructor(this->data);
  59. }
  60. void Buffer::replaceDestructor(const std::function<void(uint8_t *)>& newDestructor) {
  61. this->destructor = newDestructor;
  62. }
  63. void Buffer::set(uint8_t value) {
  64. memset(this->data, value, this->bufferSize);
  65. }
  66. std::shared_ptr<Buffer> Buffer::clone() const {
  67. std::shared_ptr<Buffer> newBuffer = std::make_shared<Buffer>(this->size);
  68. memcpy(newBuffer->data, this->data, this->size);
  69. return newBuffer;
  70. }
  71. std::shared_ptr<Buffer> Buffer::create(int32_t newSize) {
  72. return std::make_shared<Buffer>(newSize);
  73. }
  74. std::shared_ptr<Buffer> Buffer::create(int32_t newSize, uint8_t *newData) {
  75. return std::make_shared<Buffer>(newSize, newData);
  76. }