117 lines
2.5 KiB
C++
117 lines
2.5 KiB
C++
#ifndef RAII_BINARY_HPP
|
|
#define RAII_BINARY_HPP
|
|
|
|
#include <cstdlib> //size_t
|
|
#include <utility> //move
|
|
#include <cstring> //memcpy
|
|
#include <new>
|
|
|
|
namespace raii{
|
|
|
|
namespace detail{
|
|
|
|
template<size_t Alignment>
|
|
struct default_binary_allocator{
|
|
static void free(void* data){
|
|
::operator delete(data);
|
|
}
|
|
static void* allocate(size_t size){
|
|
return ::operator new(size, std::align_val_t(Alignment));
|
|
}
|
|
static void* copy(const void* c, size_t size){
|
|
char* tmp = reinterpret_cast<char*>(allocate(size));
|
|
memcpy(tmp, c, size);
|
|
return tmp;
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
class binary_base
|
|
{
|
|
protected:
|
|
char* m_data = nullptr;
|
|
size_t m_size = 0;
|
|
size_t m_cap = 0;
|
|
public:
|
|
constexpr binary_base(void) = default;
|
|
constexpr binary_base(char* data, size_t size):
|
|
m_data(data), m_size(size){}
|
|
protected:
|
|
template<class Allocator>
|
|
binary_base(const binary_base& b):
|
|
m_data(Allocator::copy(b.m_data, b.m_cap)),
|
|
m_size(b.m_size),
|
|
m_cap(b.m_cap){}
|
|
binary_base(binary_base&&);
|
|
public:
|
|
~binary_base(void) = default;
|
|
|
|
char* release(void);
|
|
|
|
constexpr size_t size(void)const{return m_size;}
|
|
constexpr size_t capacity(void)const{return m_cap;}
|
|
constexpr char* get(void){return m_data;}
|
|
constexpr const char* get(void)const{return m_data;}
|
|
constexpr operator bool(void)const{return m_data;}
|
|
|
|
char& operator[](size_t i);
|
|
const char& operator[](size_t i)const;
|
|
|
|
};
|
|
template<class Allocator = detail::default_binary_allocator<0>>
|
|
class binary : public binary_base
|
|
{
|
|
public:
|
|
constexpr binary(void) = default;
|
|
binary(char* data, size_t size):
|
|
binary_base(Allocator::copy(data, size), size){}
|
|
binary(size_t size):
|
|
binary_base(Allocator::allocate(size), size){}
|
|
binary(const binary& b):
|
|
binary_base(b)
|
|
{
|
|
m_data = Allocator::copy(b.m_data, b.m_cap);
|
|
}
|
|
binary(binary&& b):
|
|
binary_base(std::move(b)){}
|
|
~binary(void){
|
|
Allocator::free(m_data);
|
|
}
|
|
binary& operator=(const binary& b){
|
|
binary tmp(b);
|
|
return (*this = std::move(tmp));
|
|
}
|
|
binary& operator=(binary&& b){
|
|
m_size = b.m_size;
|
|
m_cap = b.m_cap;
|
|
std::swap(m_data, b.m_data);
|
|
return *this;
|
|
}
|
|
void reset(void){
|
|
Allocator::free(m_data);
|
|
m_data = nullptr;
|
|
m_cap = m_size = 0;
|
|
}
|
|
void reset(char* val, size_t cap, size_t size = 0){
|
|
Allocator::free(m_data);
|
|
m_data = val;
|
|
m_cap = cap;
|
|
m_size = size;
|
|
}
|
|
bool resize(size_t newsize){
|
|
if(newsize < m_cap)
|
|
return false;
|
|
binary tmp(newsize);
|
|
if(!tmp)
|
|
return false;
|
|
memcpy(tmp.m_data, m_data, m_size);
|
|
*this = std::move(tmp);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|