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.
libcow/src/cow.cpp

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*>(&copy)){}
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";
}