You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
80 lines
2.3 KiB
80 lines
2.3 KiB
#include <cow.hpp>
|
|
|
|
#include <utility>
|
|
|
|
#include "macros.h"
|
|
#include "cow_t.h"
|
|
|
|
|
|
struct Cow::_inner {
|
|
cow_t cow;
|
|
|
|
// NOTE: We can assume cow isn't poisoned here, since the constructors throw if it is.
|
|
inline const cow_t* ptr() const { return &cow; }
|
|
inline cow_t* ptr() { return &cow; }
|
|
|
|
~_inner();
|
|
_inner(size_t sz);
|
|
_inner(int fd, size_t sz);
|
|
_inner(cow_t* ptr);
|
|
|
|
_inner(const _inner& copy) = delete;
|
|
_inner(_inner&& move) = delete;
|
|
_inner() = delete;
|
|
};
|
|
Cow::_inner::~_inner() {
|
|
if(UNLIKELY(cow.poisoned)) return;
|
|
|
|
_cow_free_unboxed(ptr());
|
|
cow.poisoned=true;
|
|
}
|
|
Cow::_inner::_inner(int fd, size_t sz) : cow(_cow_create_unboxed(fd, sz)){
|
|
|
|
if(UNLIKELY(cow.poisoned)) throw CowException(cow_err());
|
|
}
|
|
Cow::_inner::_inner(size_t sz) : _inner(-1, sz) {}
|
|
|
|
Cow::_inner::_inner(cow_t* ptr) : cow(*ptr)
|
|
{
|
|
free(ptr);
|
|
if(UNLIKELY(cow.poisoned)) throw CowException(cow_err());
|
|
}
|
|
|
|
Cow::Cow(size_t size) : super(std::make_shared<_inner>(size)){}
|
|
Cow::Cow(int fd, size_t size) : super(std::make_shared<_inner>(fd, size)){}
|
|
Cow::Cow(cow_t* raw) : super(std::make_shared<_inner>(raw)){}
|
|
|
|
Cow::Cow(Cow&& m) : super(std::move(*const_cast<std::shared_ptr<_inner>*>(&m.super))){}
|
|
Cow::Cow(const Cow& c) : super(c.super){}
|
|
Cow::~Cow(){}
|
|
|
|
Cow Cow::from_raw(cow_t* owned) { if(cow_is_fake(owned)) throw "Trying to create real from fake raw"; else return Cow(owned); }
|
|
|
|
Cow::Fake Cow::clone() const { return Fake::from_real(*this); }
|
|
cow_t* Cow::get_raw() const { return super ? super->ptr() : nullptr; }
|
|
|
|
size_t Cow::size() const { return super ? super->cow.size : 0; }
|
|
|
|
cow_t* Cow::raw() const { return super ? &super->cow : nullptr; }
|
|
|
|
Cow::Fake::Fake(const Cow& copy) : Cow(copy), fake(cow_clone(copy.super->ptr())){}
|
|
Cow::Fake::Fake(const Fake& copy) : Cow(copy), fake(cow_clone(copy.fake)){}//Fake(*static_cast<const Cow*>(©)){}
|
|
Cow::Fake::Fake(Fake&& move) : Cow(std::move(move)), fake(move.fake)
|
|
{
|
|
*const_cast<cow_t**>(&move.fake) = nullptr;
|
|
}
|
|
Cow::Fake::~Fake() { if(fake) cow_free(fake); }
|
|
|
|
Cow::Fake Cow::Fake::Fake::from_real(const Cow& real) { return Fake(real); }
|
|
|
|
Cow::Fake Cow::Fake::clone() const { return Fake(*static_cast<const Fake*>(this)); }
|
|
cow_t* Cow::Fake::get_raw() const { return fake; }
|
|
|
|
// Error
|
|
|
|
const char* CowException::what() const noexcept {
|
|
auto str = cow_err_msg(kind);
|
|
if(str && *str) return *str;
|
|
else return "Unknown error";
|
|
}
|