Browse Source

implemented new structures

devel
Ludovic 'Archivist' Lagouardette 4 years ago
parent
commit
3fa4ac8b89
2 changed files with 340 additions and 0 deletions
  1. +191
    -0
      include/gp/pointers.hpp
  2. +149
    -0
      include/gp/vfs/channel_fs.hpp

+ 191
- 0
include/gp/pointers.hpp View File

@ -0,0 +1,191 @@
#pragma once
#include "gp/algorithm/move.hpp"
#include "gp/buffer.hpp"
#include "gp/function.hpp"
#include "gp/algorithm/modifiers.hpp"
template<typename T, typename allocator_t = void>
class unique_ptr;
template<typename T>
class unique_ptr<T, void> {
T* ptr;
gp::function<bool(T*)> deallocator;
public:
unique_ptr()
: ptr{nullptr}
{}
template<typename deal>
unique_ptr(T* _ptr, deal func)
: ptr{_ptr}
, deallocator{func}
{}
unique_ptr(unique_ptr&) = delete;
unique_ptr(unique_ptr&& oth)
: ptr{oth.ptr}
, deallocator{oth.deallocator}
{
oth.ptr = nullptr;
}
void operator=(unique_ptr&) = delete;
void operator=(unique_ptr&& oth) {
ptr = oth.ptr;
deallocator = oth.deallocator;
oth.ptr = nullptr;
}
operator bool() {
return ptr != nullptr;
}
T* operator->() {
return ptr;
}
T* operator*() {
return ptr;
}
~unique_ptr() {
if(ptr) {
ptr->~T();
gp_config::assertion(deallocator(ptr), "freeing unique_ptr failed");
}
}
};
template<typename T, typename allocator>
class unique_ptr<T, gp::reference_wrapper<allocator>>{
T* ptr;
gp::reference_wrapper<allocator> ref;
public:
unique_ptr()
: ptr{nullptr}
{}
template<typename ...Args>
unique_ptr(Args ...args, allocator& _ref)
: ref{_ref} {
auto p = ref.get().allocate(sizeof(T));
if(p)
{
ptr = new(p) T(args...);
} else {
ptr = nullptr;
}
}
unique_ptr(T* _ptr, allocator& _ref)
: ptr{_ptr}
, ref{_ref}
{}
unique_ptr(unique_ptr&) = delete;
unique_ptr(unique_ptr&& oth)
: ptr{oth.ptr}
, ref{oth.ref}
{
oth.ptr = nullptr;
}
void operator=(unique_ptr&) = delete;
void operator=(unique_ptr&& oth) {
ptr = oth.ptr;
ref = oth.ref;
oth.ptr = nullptr;
}
operator bool() {
return ptr != nullptr;
}
T* operator->() {
return ptr;
}
T* operator*() {
return ptr;
}
~unique_ptr() {
if(ptr) {
ptr->~T();
gp_config::assertion(ref.get().deallocate(ptr), "freeing unique_ptr failed");
}
}
};
template<typename T, typename allocator>
class unique_ptr{
T* ptr;
allocator alloc;
public:
unique_ptr()
: ptr{nullptr}
{}
unique_ptr(T* _ptr, allocator _alloc = allocator{})
: ptr{_ptr}
, alloc{_alloc}
{}
template<typename ...Args>
unique_ptr(Args ...args, allocator _alloc = allocator{})
: alloc{_alloc} {
auto p = alloc.allocate(sizeof(T));
if(p)
{
ptr = new(p) T(args...);
} else {
ptr = nullptr;
}
}
unique_ptr(unique_ptr&) = delete;
unique_ptr(unique_ptr&& oth)
: ptr{oth.ptr}
, alloc{oth.alloc}
{
oth.ptr = nullptr;
}
void operator=(unique_ptr&) = delete;
void operator=(unique_ptr&& oth) {
ptr = oth.ptr;
alloc = oth.alloc;
oth.ptr = nullptr;
}
operator bool() {
return ptr != nullptr;
}
T* operator->() {
return ptr;
}
T* operator*() {
return ptr;
}
~unique_ptr() {
if(ptr) {
ptr->~T();
gp_config::assertion(alloc.deallocate(ptr), "freeing unique_ptr failed");
}
}
};
class unique_array_ptr {
gp::buffer<char> data;
};

+ 149
- 0
include/gp/vfs/channel_fs.hpp View File

@ -0,0 +1,149 @@
#pragma once
#include "gp/array.hpp"
#include "gp/algorithm/move.hpp"
#include "gp/vfs/fs_types.hpp"
#include "gp/allocator/aggregator.hpp"
namespace gp {
template<typename error_function, typename pop_function>
class self_filling_channel{
error_function on_error;
pop_function filler;
public:
gp::buffer<char>::associated_iterator push(gp::buffer<char> input) {
on_error();
return input.begin();
}
gp::buffer<char>::associated_iterator pop(gp::buffer<char> dest) {
return filler(dest);
}
};
template<size_t size, size_t count = 1, bool whole_messages = true, bool zero_out = true>
class channel {
gp::array<size_t, count> message_sizes;
gp::array<
gp::array<char, size>,
count
> messages;
size_t r_offset = 0;
size_t w_offset = 0;
[[nodiscard]] size_t write_one(size_t loc, gp::buffer<char> message) {
auto cond = message.size();
size_t idx = 0;
for(; idx < cond; ++idx) {
messages[loc][idx] = message[idx];
}
message_sizes[loc] = message.size();
w_offset += 1;
if constexpr (count != 1) w_offset %= size;
if constexpr (zero_out) {
auto ret = idx;
for(; idx < messages[loc].size(); ++idx) {
messages[loc] = 0;
}
return ret;
}
return idx;
}
[[nodiscard]] size_t read_one(size_t loc, gp::buffer<char> message) {
size_t ret;
size_t idx = 0;
size_t trailer = 0;
if(message_sizes[loc] < message.size())
{
for(; idx < message_sizes[loc]; ++idx) {
message[idx] = messages[loc][idx];
}
r_offset += 1;
if constexpr (count != 1) w_offset %= size;
ret = idx;
} else {
for(; idx < message.size(); ++idx) {
message[idx] = messages[loc][idx];
}
ret = idx;
for(; idx < message_sizes[loc]; ++idx, ++trailer)
{
message[trailer] = message[idx];
}
message_sizes[loc] = trailer;
}
if constexpr (zero_out) {
if(trailer == 0) {
message_sizes[loc] = 0;
}
for(; trailer < messages[loc].size(); ++trailer)
{
messages[loc][trailer] = 0;
}
}
return ret;
}
public:
channel() {}
gp::buffer<char>::associated_iterator push(gp::buffer<char> input) {
if constexpr (whole_messages) {
if(input.size() > size) {
return input.begin();
}
}
if constexpr (count == 1) {
if(w_offset == r_offset) {
auto to_write = gp::min(input.size(), size);
write_one(
0,
gp::buffer<char>(input.begin().data, to_write)
);
return input.begin()+to_write;
} else {
return input.begin();
}
} else {
auto next_w = (w_offset+1)%count;
auto to_consume = input;
while(to_consume.size() && (next_w == r_offset)) {
auto to_write = gp::min(to_consume.size(), size);
to_write = write_one(
w_offset,
to_consume.trim_start(to_write)
);
to_consume = to_consume.trim_start(to_write);
next_w = (w_offset+1)%count;
}
return to_consume.begin();
}
}
gp::buffer<char>::associated_iterator pop(gp::buffer<char> dest) {
if(r_offset == w_offset) {
return dest.begin();
}
size_t idx;
if constexpr (count == 1) {
idx = 0;
} else {
idx = r_offset;
}
if constexpr (whole_messages) {
if(message_sizes[idx] > dest.size()) {
return dest.begin();
}
auto sz = gp::min(message_sizes[idx], dest.size());
read_one(idx, gp::buffer<char>(dest.begin(), sz));
return dest.begin()+sz;
}
auto to_fill = dest;
do{
auto to_read = gp::min(to_fill.size(), size);
to_read = read_one(
r_offset,
to_fill.trim_start(to_read)
);
to_fill = to_fill.trim_start(to_read);
}while(r_offset != w_offset && to_fill.size());
return to_fill.begin();
}
};
}

Loading…
Cancel
Save