Parcourir la source

Various fixes to containers and enhancements

cbor
Ludovic 'Archivist' Lagouardette il y a 3 ans
Parent
révision
998dda01a2
7 fichiers modifiés avec 214 ajouts et 39 suppressions
  1. +51
    -7
      include/gp/enveloppe/cbor.hpp
  2. +98
    -22
      include/gp/function.hpp
  3. +2
    -2
      include/gp/optional.hpp
  4. +34
    -3
      include/gp/variant.hpp
  5. +5
    -5
      include/gp/vector.hpp
  6. +1
    -0
      tests.cpp
  7. +23
    -0
      tests/cbor_test.cpp

+ 51
- 7
include/gp/enveloppe/cbor.hpp Voir le fichier

@ -1,9 +1,9 @@
#pragma once
#include <gp/variant.hpp>
#include <gp/pair.hpp>
#include <gp/optional.hpp>
#include <gp/variant.hpp>
#include <gp/vector.hpp>
#include <gp/pair.hpp>
namespace gp {
@ -71,16 +71,60 @@ namespace gp {
double
>;
struct undefined_t{};
struct undefined_t final {};
class cbor_value : public gp::fixed_variant<
template<typename T>
using cbor_composite = gp::fixed_variant<
cbor_number,
gp::buffer<std::byte>,
bool,
gp::vector<cbor_value>,
gp::vector<gp::pair<cbor_value, cbor_value>>,
gp::vector<T>,
gp::vector<gp::pair<T, T>>,
gp::nullopt_t,
undefined_t,
cbor_floating_point
>{};
>;
class cbor_value {
cbor_composite<cbor_value> contents;
gp::reference_wrapper<allocator> alloc;
public:
cbor_value(allocator& alloc_v)
: contents(cbor_composite<cbor_value>(undefined_t{}))
, alloc(alloc_v)
{}
cbor_value(cbor_number number, allocator& alloc_v)
: contents(number)
, alloc(alloc_v)
{}
cbor_value& operator=(cbor_value& value) {
contents = value.contents;
alloc = value.alloc;
return *this;
}
cbor_value& operator=(cbor_value&& value) {
gp::swap(contents, value.contents);
gp::swap(alloc, value.alloc);
return *this;
}
cbor_value& operator=(cbor_composite<cbor_value>& value) {
contents = value;
return *this;
}
auto new_array() {
return gp::vector<cbor_value>{alloc};
}
auto new_object() {
return gp::vector<gp::pair<cbor_value, cbor_value>>{alloc};
}
};
}

+ 98
- 22
include/gp/function.hpp Voir le fichier

@ -5,8 +5,18 @@
#include "gp/algorithm/move.hpp"
#include "gp/algorithm/tmp_manip.hpp"
#include "gp/allocator/allocator.hpp"
#include "gp/optional.hpp"
namespace gp{
namespace details {
template<typename pred, typename returner>
auto ensure(pred a, returner b) {
gp_config::assertion(a(), "could not ensure predicate");
return b();
}
}
template <typename fn>
class function;
@ -17,7 +27,7 @@ namespace gp{
using invoke_fn_t = ret (*)(fn_ptr, args&&...);
using condestruct_fn_t = void (*) (fn_ptr, fn_ptr);
gp::reference_wrapper<allocator> alloc;
gp::optional<gp::reference_wrapper<allocator>> alloc;
invoke_fn_t invokator;
condestruct_fn_t condestructor;
fn_ptr data_ptr;
@ -45,10 +55,10 @@ namespace gp{
public:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnull-dereference"
#pragma gcc diagnostic push
#pragma gcc diagnostic ignored "-Wnull-dereference"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnull-dereference"
function(allocator& alloc_v)
#pragma gcc pop
#pragma GCC diagnostic pop
#pragma clang diagnostic pop
: alloc(alloc_v)
, invokator(nullptr)
@ -62,54 +72,98 @@ namespace gp{
: alloc(alloc_v)
, invokator(reinterpret_cast<invoke_fn_t>(invoke<func>))
, condestructor(reinterpret_cast<condestruct_fn_t>(condestruct<func>))
, data_ptr((char*)(alloc.get().allocate(sizeof(func))))
, data_size(sizeof(func))
, data_ptr(
sizeof(func) <= sizeof(data_ptr)
? 0
: details::ensure(
[&](){return alloc.has_value();},
[&](){return (char*)(alloc.value().get().allocate(sizeof(func)));}
)
)
, data_size(
sizeof(func) <= sizeof(data_ptr)
? 0
: sizeof(func)
)
{
gp_config::assertion(data_ptr != nullptr, "allocator failed in function");
if(data_ptr != nullptr) this->condestructor(data_ptr, reinterpret_cast<char*>(&f));
gp_config::assertion(!(alloc.has_value() && data_ptr == nullptr), "allocator failed in function");
if(data_ptr != nullptr) this->condestructor(data_size < sizeof(data_ptr) ? (char*)&data_ptr : data_ptr, reinterpret_cast<char*>(&f));
}
template<typename func>
function(func f, nullopt_t alloc_v = nullopt)
: alloc(alloc_v)
, invokator(reinterpret_cast<invoke_fn_t>(invoke<func>))
, condestructor(reinterpret_cast<condestruct_fn_t>(condestruct<func>))
, data_ptr(
sizeof(func) <= sizeof(data_ptr)
? 0
: details::ensure(
[&](){return alloc.has_value();},
[&](){return (char*)(alloc.value().get().allocate(sizeof(func)));}
)
)
, data_size(
sizeof(func) <= sizeof(data_ptr)
? 0
: sizeof(func)
)
{
gp_config::assertion(!(alloc.has_value() && data_ptr == nullptr), "allocator failed in function");
if(data_ptr != nullptr) this->condestructor(data_size < sizeof(data_ptr) ? (char*)&data_ptr : data_ptr, reinterpret_cast<char*>(&f));
}
function(function const& rhs)
: alloc(rhs.alloc)
, invokator(rhs.invokator)
, condestructor(rhs.condestructor)
, data_ptr(rhs.data_size != 0 ? (char*)(alloc.get().allocate(rhs.data_size)) : nullptr)
, data_ptr(
rhs.data_size <= sizeof(data_ptr)
? 0
: details::ensure(
[&](){return alloc.has_value();},
[&](){return (char*)(alloc.value().get().allocate(rhs.data_size));}
)
)
, data_size(rhs.data_size)
{
gp_config::assertion(data_ptr != nullptr, "allocator failed in function");
gp_config::assertion(o">!(alloc.has_value() && data_ptr == nullptr), "allocator failed in function");
if(
data_ptr != nullptr
and rhs.data_ptr != nullptr
) this->condestructor(data_ptr, rhs.data_ptr);
) this->condestructor(data_size <= sizeof(data_ptr) ? (char*)&data_ptr : data_ptr, rhs.data_ptr);
}
function(function&& rhs)
: alloc(rhs.alloc)
, invokator(rhs.invokator)
, condestructor(rhs.condestructor)
, data_ptr(rhs.data_ptr)
, data_ptr(data_size <= sizeof(data_ptr) ? 0 : rhs.data_ptr)
, data_size(rhs.data_size)
{
if(data_size <= sizeof(data_ptr) && data_size != 0 && data_ptr != nullptr && alloc.has_value()) {
condestructor((char*)&data_ptr, (char*)&rhs.data_ptr);
condestructor(nullptr, (char*)&rhs.data_ptr);
}
rhs.data_ptr = nullptr;
}
constexpr function(ret(*fn)(args...), allocator alloc_v)
: alloc(alloc_v)
, invokator(reinterpret_cast<invoke_fn_t>(invoke<ret(args...)>))
, condestructor(nop_condestruct)
, data_ptr(reinterpret_cast<char*>(fn))
, data_size(0)
{}
~function(){
if(data_size == 0) {
return;
}
if(data_ptr != nullptr) {
if(data_size <= 0) {
return;
}
if(data_ptr != nullptr && alloc.has_value()) {
condestructor(nullptr, data_ptr);
alloc.get().deallocate(data_ptr);
alloc.value().get().deallocate(data_ptr);
data_ptr = nullptr;
}
if(data_size < sizeof(data_ptr))
{
condestructor(nullptr, (char*)&data_ptr);
}
}
function& operator=(function&& rhs) {
@ -121,6 +175,28 @@ namespace gp{
return *this;
}
function& operator=(function& rhs) {
alloc = rhs.alloc;
invokator = rhs.invokator;
condestructor = rhs.condestructor;
condestructor(nullptr, data_ptr);
alloc.value().get().deallocate(data_ptr);
data_ptr = rhs.data_size <= sizeof(data_ptr)
? 0
: details::ensure(
[&](){return alloc.has_value();},
[&](){return (char*)(alloc.value().get().allocate(rhs.data_size));}
);
data_size = rhs.data_size;
gp_config::assertion(!(alloc.has_value() && data_ptr == nullptr), "allocator failed in function");
if(
data_ptr != nullptr
and rhs.data_ptr != nullptr
) this->condestructor(data_size <= sizeof(data_ptr) ? (char*)&data_ptr : data_ptr, rhs.data_ptr);
return *this;
}
ret operator()(args&&... argv) {
return invokator(data_ptr, gp::forward<args>(argv)...);
}

+ 2
- 2
include/gp/optional.hpp Voir le fichier

@ -10,12 +10,12 @@
#include <new>
namespace gp{
struct nullopt_t{};
struct nullopt_t final{};
constexpr nullopt_t nullopt;
template<typename T>
class optional{
class optional final{
bool ready = false;
char buffer[sizeof(T)];
public:

+ 34
- 3
include/gp/variant.hpp Voir le fichier

@ -15,26 +15,41 @@
namespace gp{
template<typename ...T>
class fixed_variant{
class fixed_variant final {
std::size_t index = std::numeric_limits<std::size_t>::max();
char buffer[max_size<T...>()];
gp::function<void(void*, void*)> cpytor = [](void*, void*){};
gp::function<void(void*, void*)> mvtor = [](void*, void*){};
gp::function<void(void*)> dtor = [](void*){};
static_assert(all_of_fixed_size<T...>::value, "not fixed");
public:
template<typename Up">, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
template<typename Uo">>//, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
constexpr fixed_variant(U& value)
: index{r_index_of<U, T...>::value}
{
new(buffer) U(value);
dtor = gp::function<void(void*)>([](void* thing){((U*)thing)->~U();});
cpytor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(*(U*)src);});
mvtor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));});
}
template<typename Up">, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
template<typename Uo">>//, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
constexpr fixed_variant(U&& value)
: index{r_index_of<U, T...>::value}
{
new(buffer) U(std::move(value));
dtor = gp::function<void(void*)>([](void* thing){((U*)thing)->~U();});
cpytor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(*(U*)src);});
mvtor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));});
}
constexpr fixed_variant(fixed_variant& oth)
: index{oth.index}
, dtor{oth.dtor}
, cpytor{oth.cpytor}
, mvtor{oth.mvtor}
{
cpytor(oth.buffer, buffer);
}
template<typename U>
@ -46,6 +61,18 @@ namespace gp{
return index;
}
void operator=(fixed_variant& value)
{
if(index != std::numeric_limits<std::size_t>::max())
{
dtor((void*)buffer);
}
index = value.index;
cpytor = value.cpytor;
dtor = value.dtor;
mvtor(value.buffer, buffer);
}
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
void operator=(U& value)
{
@ -56,6 +83,8 @@ namespace gp{
index = r_index_of<U, T...>::value;
new(buffer) U(value);
dtor = gp::function([](void* thing){((U*)thing)->~U();});
cpytor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(*(U*)src);});
mvtor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));});
}
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
@ -68,6 +97,8 @@ namespace gp{
index = r_index_of<U, T...>::value;
new(buffer) U(std::move(value));
dtor = gp::function([](void* thing){((U*)thing)->~U();});
cpytor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(*(U*)src);});
mvtor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));});
}
~fixed_variant()

+ 5
- 5
include/gp/vector.hpp Voir le fichier

@ -7,7 +7,7 @@
namespace gp{
template<typename T>
class vector{
class vector final {
T* ary;
size_t sz;
size_t cap;
@ -110,7 +110,7 @@ namespace gp{
if(ary)
{
for(auto& elem : *this) {
elemo">->~T();
elemp">.~T();
}
gp_config::assertion(alloc.get().deallocate(ary), "could not deallocate");
}
@ -128,10 +128,10 @@ namespace gp{
if(alloc.get().try_reallocate(ary, new_data_size)) return true;
if(T* new_ary = alloc.get().allocate(new_data_size); new_ary) {
if(T* new_ary = p">(T*)alloc.get().allocate(new_data_size); new_ary) {
auto new_it = new_ary;
for(auto* elem : *this) {
++new_it = gp::move(elem);
for(auto& elem : *this) {
*(++new_it) = gp::move(elem);
}
gp_config::assertion(alloc.get().deallocate(ary), "failed to deallocate old range");

+ 1
- 0
tests.cpp Voir le fichier

@ -2,6 +2,7 @@
#include "allocator.hpp"
#include "bloomfilter.cpp"
#include "cbor_test.cpp"
#include "gp_test.cpp"
#include "math.cpp"
#include "meta_test.cpp"

+ 23
- 0
tests/cbor_test.cpp Voir le fichier

@ -0,0 +1,23 @@
#include <gp/allocator/arena.hpp>
#include <gp/array.hpp>
#include <gp/enveloppe/cbor.hpp>
#include "test_scaffold.h"
struct cbor_test : public test_scaffold {
cbor_test() {
name = __FILE__ ":1";
}
virtual int run() {
gp::array<char, 4096> store;
gp::arena alloc{&*store.begin(), store.size()};
gp::cbor_value data{alloc};
auto gen = data.new_object();
gen.emplace_back(uint8_t(12), int32_t(-98));
gen.emplace_back(uint8_t(13), uint32_t(98));
return 0;
}
};
append_test dummy_pg5zhr8bv(new cbor_test{});

Chargement…
Annuler
Enregistrer