// =====================================================================================================================
// 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