// ===================================================================================================================== // open-cpp-utils, an open-source cpp library with data structures that extend the STL. // Copyright (C) 2024 Medusa Slockbower // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // ===================================================================================================================== #ifndef OPEN_CPP_UTILS_ALLOCATION_H #define OPEN_CPP_UTILS_ALLOCATION_H #include #include namespace open_cpp_utils { template> class allocation { public: using data_type = T; using reference = data_type&; using const_reference = const data_type&; using pointer = data_type*; using const_pointer = const data_type*; allocation(); allocation(size_t size); allocation(allocation&& alloc) noexcept; allocation(const allocation& alloc); ~allocation(); size_t size() const { return Size_; } bool operator()() const { return Buffer_ != nullptr; } void allocate(size_t size); void reallocate(size_t size); void free(); void clear(size_t offset, size_t size, const T& value); void copy(const allocation& other, size_t offset, size_t o_offset, size_t size); reference operator[](int i) { assert(i >= 0 && i < Size_); return Buffer_[i]; } const_reference operator[](int i) const { assert(i >= 0 && i < Size_); return Buffer_[i]; } operator pointer() { return Buffer_; } operator const_pointer() const { return Buffer_; } allocation& operator=(const allocation& other); allocation& operator=(allocation&& other) noexcept; pointer data() { return Buffer_; } const_pointer data() const { return Buffer_; } pointer begin() { return Buffer_; } pointer end() { return Buffer_ + Size_; } const_pointer begin() const { return Buffer_; } const_pointer end() const { return Buffer_ + Size_; } private: Alloc Alloc_; size_t Size_; T* Buffer_; }; template allocation::allocation() : Alloc_(), Size_(0), Buffer_(nullptr) { } template allocation::allocation(size_t size) : Alloc_(), Size_(size), Buffer_(Alloc_.allocate(Size_)) { } template allocation::allocation(allocation &&alloc) noexcept : Alloc_(), Size_(alloc.Size_), Buffer_(alloc.Buffer_) { } template allocation::allocation(const allocation &alloc) : Alloc_(), Size_(alloc.Size_), Buffer_(Alloc_.allocate(Size_)) { copy(alloc, 0, 0, Size_); } template allocation::~allocation() { Alloc_.deallocate(Buffer_, Size_); Buffer_ = nullptr; Size_ = 0; } template void allocation::allocate(size_t size) { assert(Buffer_ != nullptr); if(Buffer_ == nullptr) return; Buffer_ = Alloc_.allocate(size); } template void allocation::reallocate(size_t size) { // Assertions for debug mode assert(Buffer_ != nullptr); // Safety checks if(Buffer_ == nullptr) return; const allocation old_ = std::move(*this); std::construct_at(this, size); std::memcpy(Buffer_, old_.Buffer_, old_.Size_); } template void allocation::free() { Alloc_.deallocate(Buffer_, Size_); Buffer_ = nullptr; Size_ = 0; } template void allocation::clear(size_t offset, size_t size, const T &value) { // Safety checks if(Buffer_ == nullptr) return; size = std::min(size, Size_ - offset); for(pointer it = Buffer_ + offset; it != Buffer_ + size; ++it) { std::destroy_at(it); std::construct_at(it, value); } } template void allocation::copy(const allocation &other, size_t offset, size_t o_offset, size_t size) { // Assertions for debug mode assert(size <= Size_ - offset && size <= other.Size_ - o_offset); // Safety checks if(Buffer_ == nullptr || other.Buffer_ == nullptr) return; if(offset >= Size_ || o_offset >= other.Size_) return; size = std::min(size, Size_ - offset); size = std::min(size, other.Size_ - o_offset); std::memcpy(Buffer_ + offset, other.Buffer_ + o_offset, size * sizeof(data_type)); } template allocation & allocation::operator=(const allocation &other) { if(&other == this) return *this; Size_ = other.Size_; Buffer_ = Alloc_.allocate(Size_); copy(other, 0, 0, Size_); return *this; } template allocation & allocation::operator=(allocation &&other) noexcept { if(&other == this) return *this; Size_ = other.Size_; Buffer_ = other.Buffer_; return *this; } } #endif //ALLOCATION_H