added slice

cpp
Avril 3 years ago
parent 68e54805af
commit b16d7c6a87
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -4,8 +4,9 @@
#include <memory>
#include "slice.hpp"
struct Cow {
struct Cow : public Slice<unsigned char> {
struct Fake;
Cow() = delete;
@ -15,13 +16,13 @@ struct 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 void* area() override { return cow_ptr(get_raw()); }
inline const void* area() const override { return cow_ptr_of(const void, get_raw()); }
/// Get the size of the mapped area.
///
/// Note: This calls into `_inner`'s internals. To skip the call on non-LTO builds, use `size_unsafe()`.
size_t size() const;
size_t size() const override;
/// Get the size by assuming the ABI layout of cow_t to be correct. Potentially faster but ABI sensitive.
/// This shouldn't be a problem if all build static assertions passed.
///
@ -31,18 +32,6 @@ struct Cow {
/// XXX: Deprecated function for now. It seems `size()` offers better codegen on LTO and non-LTO enabled builds.
[[deprecated]] inline size_t size_unsafe() const { return _cow_size_unsafe(get_raw()); }
inline unsigned char* as_bytes() { return (unsigned char*)area(); }
inline const unsigned char* as_bytes() const { return (const unsigned char*)area(); }
inline unsigned char& operator[](size_t index) {
if(index >= size()) throw "Size too large";
return as_bytes()[index];
}
inline const unsigned char& operator[](size_t index) const {
if(index >= size()) throw "Size too large";
return as_bytes()[index];
}
static Cow from_raw(cow_t* owned);
private:
@ -56,7 +45,7 @@ struct Cow {
};
struct Cow::Fake : Cow {
struct Cow::Fake : public Cow {
Fake() = delete;
Fake(const Cow& real);
Fake(const Fake& copy);

@ -0,0 +1,33 @@
#pragma once
template<typename T>
struct Slice {
virtual const void* area() const =0;
virtual void* area() = 0;
virtual size_t size() const = 0;
inline T* ptr() { return (T*)area(); }
inline const T* ptr() const { return (const T*)area(); }
inline size_t size_bytes() const { return size() * sizeof(T); }
inline unsigned char* as_bytes() { return (unsigned char*)area(); }
inline const unsigned char* as_bytes() const { return (const unsigned char*)area(); }
inline T& operator[](size_t index) {
if(index >= size()) throw "Size too large";
return ptr()[index];
}
inline const T& operator[](size_t index) const {
if(index >= size()) throw "Size too large";
return ptr()[index];
}
template<typename U>
inline U* area_as() requires(sizeof(T) % sizeof(U) == 0) { return (U*)area(); }
template<typename U>
inline const U* area_as() const requires(sizeof(T) % sizeof(U) == 0) { return (U*)area(); }
template<typename U>
size_t size_as() const requires(sizeof(T) % sizeof(U) == 0) { return size_bytes() / sizeof(U); }
};

@ -1,18 +1,34 @@
#include <cow.hpp>
#include <cstdio>
#include <cstring>
void write_fake(Cow& clone, const char* string)
{
strncpy(clone.area_as<char>(), string, clone.size_as<char>()-1);
}
void read_fake(const Cow& clone)
{
printf("read_fake: %s\n", clone.area_as<char>());
}
int main()
{
Cow real(4096);
write_fake(real, "Hello world");
read_fake(real);
Cow::Fake clone = real;
printf("Fake size: %lu\n", clone.size());
printf("Fake ptr: %p\n", clone.area());
printf("Fast size: %lu, slow size: %lu\n", real.size_unsafe(), real.size());
read_fake(clone);
write_fake(clone, "hello fake!");
read_fake(clone);
read_fake(real);
Cow::Fake clone = real;
{
Cow::Fake clone2 = clone;
}
if(0) cow_size_unsafe(NULL);
printf("First byte of: real = %x, fake = %x\n", real[0], clone[0]);
return 0;
}

Loading…
Cancel
Save