diff --git a/cow.o b/cow.o new file mode 100644 index 0000000..dd48963 Binary files /dev/null and b/cow.o differ diff --git a/include/cow.h b/include/cow.h index 6652cb2..af9fc4f 100644 --- a/include/cow.h +++ b/include/cow.h @@ -3,6 +3,7 @@ #ifdef __cplusplus #define restrict __restrict__ +extern "C" { #endif #include @@ -35,6 +36,7 @@ size_t cow_size(const cow_t* cow); #ifdef __cplusplus #undef restrict +} #endif #endif /* _COW_H */ diff --git a/include/cow.hpp b/include/cow.hpp index 4baa852..467fbf4 100644 --- a/include/cow.hpp +++ b/include/cow.hpp @@ -5,34 +5,52 @@ #include struct Cow { + struct Fake; Cow() = delete; Cow(size_t size); Cow(Cow&& m); virtual ~Cow(); + + virtual Fake clone() const; + + inline void* area() { return cow_ptr(get_raw()); } + inline const void* area() const { return cow_ptr_of(const void, get_raw()); } + inline size_t size() const { return cow_size(get_raw()); } - static Cow from_raw(cow_t* owned); + inline unsigned char* as_bytes() { return (unsigned char*)area(); } + inline const unsigned char* as_bytes() const { return (const unsigned char*)area(); } - struct Fake; + unsigned char& operator[](size_t index); + const unsigned char& operator[](size_t index) const; + + static Cow from_raw(cow_t* owned); private: struct _inner; Cow(cow_t* raw); + protected: - const std::shared_ptr<_inner> super; Cow(const Cow& c); + const std::shared_ptr<_inner> super; + virtual cow_t* get_raw() const; + }; struct Cow::Fake : Cow { Fake() = delete; + Fake(const Fake& copy); + Fake(Fake&& move); + ~Fake(); - Fake(const Fake& c); - Fake(Fake&& m); + Fake clone() const override; - ~Fake(); - static Fake from_parent(const Cow& parent); + static Fake from_real(const Cow& real); + + protected: + cow_t* get_raw() const override; private: - Fake(const Cow& parent); - cow_t* fake; -}; + Fake(const Cow& real); + cow_t* const fake; +}; diff --git a/src/cow.cpp b/src/cow.cpp index 212265d..a6cd5b8 100644 --- a/src/cow.cpp +++ b/src/cow.cpp @@ -24,16 +24,36 @@ Cow::_inner::_inner(cow_t* ptr) : ptr(ptr){} Cow::Cow(size_t size) : super(std::make_shared<_inner>(size)){} Cow::Cow(cow_t* raw) : super(std::make_shared<_inner>(raw)){} -Cow::~Cow(){} + Cow::Cow(Cow&& m) : super(std::move(*const_cast*>(&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::Fake(const Cow& parent) : Cow(parent), fake(cow_clone(parent.super->ptr)){} -Cow::Fake::~Fake() { if(fake) { cow_free(fake); *const_cast(&fake) = nullptr; } } -Cow::Fake Cow::Fake::from_parent(const Cow& parent) { return Fake(parent); } +Cow::Fake Cow::clone() const { return Fake::from_real(*this); } +cow_t* Cow::get_raw() const { return super->ptr; } +Cow::Fake::Fake(const Cow& copy) : Cow(copy), fake(cow_clone(copy.super->ptr)){} +Cow::Fake::Fake(const Fake& copy) : Fake(*static_cast(©)){} Cow::Fake::Fake(Fake&& move) : Cow(std::move(move)), fake(move.fake) { - *const_cast(&fake) = nullptr; + *const_cast(&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(*this); } +cow_t* Cow::Fake::get_raw() const { return fake; } + +// Operators + +unsigned char& Cow::operator[](size_t index) { + if(index >= size()) throw "Size too large"; + return as_bytes()[index]; +} +const unsigned char& Cow::operator[](size_t index) const { + if(index >= size()) throw "Size too large"; + return as_bytes()[index]; } diff --git a/src/test/main.cpp b/src/test/main.cpp new file mode 100644 index 0000000..3e18238 --- /dev/null +++ b/src/test/main.cpp @@ -0,0 +1,12 @@ +#include + +int main() +{ + Cow real(4096); + + Cow::Fake clone = real.clone(); + { + Cow::Fake clone2 = clone.clone(); + } + return 0; +}