Browse Source

updated a few containers, unveiled a bug

master
Ludovic 'Archivist' Lagouardette 5 months ago
parent
commit
61d4226624
6 changed files with 162 additions and 14 deletions
  1. +15
    -3
      include/gp/algorithms/move.hpp
  2. +61
    -3
      include/gp/containers/buffer.hpp
  3. +18
    -4
      include/gp/containers/vector.hpp
  4. +16
    -1
      include/gp/functional/function.hpp
  5. +51
    -2
      include/gp/functional/variant.hpp
  6. +1
    -1
      tests/gp_test.cpp

+ 15
- 3
include/gp/algorithms/move.hpp View File

@ -10,18 +10,30 @@ namespace gp{
{
return (typename gp::remove_reference<T>::type&&)value;
}
template<typename T>
template<typename T>
constexpr T&& forward(typename gp::remove_reference<T>::type& t) noexcept
{
return static_cast<T&&>(t);
}
template<typename T>
template<typename T>
constexpr T&& forward(typename gp::remove_reference<T>::type&& t) noexcept
{
static_assert(!std::is_lvalue_reference_v<T>,"bad forward of rvalue as lvalue");
return static_cast<T&&>(t);
}
/*template<typename T>
constexpr const T&& forward(const typename gp::remove_reference<T>::type& t) noexcept
{
return static_cast<const T&&>(t);
}
template<typename T>
constexpr const T&& forward(const typename gp::remove_reference<T>::type&& t) noexcept
{
static_assert(!std::is_lvalue_reference_v<T>,"bad forward of rvalue as lvalue");
return static_cast<const T&&>(t);
}*/
template<typename T>
constexpr void swap(

+ 61
- 3
include/gp/containers/buffer.hpp View File

@ -10,6 +10,12 @@
#include <cstdint>
namespace gp{
template<typename T>
class buffer;
template<typename T>
bool hold_same_data(const gp::buffer<T>& lhs, const gp::buffer<T>& rhs);
template<typename T>
class buffer final{
@ -123,11 +129,19 @@ namespace gp{
}
else
{
return buffer<U>(reinterpret_cast<U*>(nullptr), 0);
gp_config::assertion(
false,
"Buffer bounds infringed during cast"
);
}
}
}
/**
* Create a new subslice of the buffer containing `new_sz` elements exactly, or no elements
* @param new_sz the size of the new slice
* @return a slice of size new_sz or an empty slice
*/
buffer slice_start(size_t new_sz)
{
if(new_sz<=size())
@ -139,7 +153,12 @@ namespace gp{
return buffer{(T*)nullptr,(size_t)0};
}
}
/**
* Create a new subslice from the end of the buffer containing `new_sz` elements exactly, or no elements
* @param new_sz the size of the new slice
* @return a slice of size new_sz or an empty slice
*/
buffer slice_end(size_t new_sz)
{
if(new_sz<=size())
@ -152,6 +171,12 @@ namespace gp{
}
}
/**
* Create a new subslice from the end of the buffer containing `rm_sz` elements less elements than the original
* buffer, or no elements
* @param rm_sz the number of elements to remove from the start of the slice
* @return a new slice
*/
buffer trim_start(size_t rm_sz)
{
if(rm_sz<=size())
@ -163,7 +188,13 @@ namespace gp{
return buffer{(T*)nullptr,(size_t)0};
}
}
/**
* Create a new subslice from the start of the buffer containing `rm_sz` elements less elements than the
* original buffer, or no elements
* @param rm_sz the number of elements to remove from the start of the slice
* @return a new slice
*/
buffer trim_end(size_t rm_sz)
{
if(rm_sz<=size())
@ -175,5 +206,32 @@ namespace gp{
return buffer{(T*)nullptr,(size_t)0};
}
}
friend bool hold_same_data(const gp::buffer<T>& lhs, const gp::buffer<T>& rhs);
bool starts_with(gp::buffer<T> oth) {
return hold_same_data<T>(this->slice_start(oth.size()), oth);
}
optional<T> front() {
if(size() == 0) return nullopt;
return *begin();
}
optional<T> back() {
if(size() == 0) return nullopt;
return *slice_end(1).begin();
}
};
template<typename T>
bool hold_same_data(const gp::buffer<T>& lhs, const gp::buffer<T>& rhs) {
if(lhs.size() != rhs.size()) return false;
size_t idx = 0;
while(idx != lhs.size()) {
if(lhs[idx] != rhs[idx]) return false;
++idx;
}
return true;
}
}

+ 18
- 4
include/gp/containers/vector.hpp View File

@ -118,7 +118,7 @@ namespace gp{
gp::swap(cap, oth.cap);
} else {
for(auto& elem : *this) {
elemo">->~T();
elemp">.~T();
}
sz = 0;
if(capacity()<oth.size()) {
@ -133,7 +133,7 @@ namespace gp{
gp_config::assertion(alloc.get().deallocate(oth.ary), "could not deallocate");
sz = idx;
oth.sz = 0;
oth.capacity = 0;
oth.cap = 0;
oth.ary = nullptr;
}
return *this;
@ -300,16 +300,26 @@ namespace gp{
(*rbegin()).~T();
sz -= 1;
}
constexpr gp::pointer_iterator<T, 1> begin()
{
return associated_iterator(&ary[0]);
}
constexpr gp::pointer_iterator<T, 1> end()
{
return associated_iterator(&ary[sz]);
}
constexpr gp::const_pointer_iterator<T, 1> begin() const
{
return associated_const_iterator(&ary[0]);
}
constexpr gp::const_pointer_iterator<T, 1> end() const
{
return associated_const_iterator(&ary[sz]);
}
constexpr gp::const_pointer_iterator<T, 1> cbegin() const
{
@ -368,5 +378,9 @@ namespace gp{
{
return gp::buffer<T>{(T*)ary, (T*)ary+sz};
}
T* data() {
return ary;
}
};
}

+ 16
- 1
include/gp/functional/function.hpp View File

@ -20,6 +20,11 @@ namespace gp{
template <typename fn>
class function;
/**
* TODO: Constness of arguments does weird things wherever forward is called, this needs some investigating
* @tparam ret
* @tparam args
*/
template <typename ret, typename ...args>
class function<ret(args...)>{
using fn_ptr = char*;
@ -28,6 +33,11 @@ namespace gp{
using condestruct_fn_t = void (*) (fn_ptr, fn_ptr);
gp::optional<gp::reference_wrapper<allocator>> alloc;
/**
* Special thanks to the Krepuskulte for this
*
* `invocator` is taken by the stdlib
*/
invoke_fn_t invokator;
condestruct_fn_t condestructor;
fn_ptr data_ptr;
@ -199,12 +209,17 @@ namespace gp{
);
return *this;
}
ret operator()(args&&... argv) {
return invokator(data_size <= sizeof(data_ptr) ? (fn_ptr)&data_ptr : data_ptr, gp::forward<args>(argv)...);
}
ret operator()(const args&&... argv) const {
return invokator(data_size <= sizeof(data_ptr) ? (fn_ptr)&data_ptr : data_ptr, gp::forward<args>(argv)...);
}
bool ready() {
// TODO: add type safety to invocators with a toggleable check
return invokator != nullptr;
}
};

+ 51
- 2
include/gp/functional/variant.hpp View File

@ -27,6 +27,10 @@ namespace gp{
gp::function<void(void*, void*)> cpytor = {[](void*, void*){}, nullopt};
gp::function<void(void*, void*)> mvtor = {[](void*, void*){}, nullopt};
gp::function<void(void*)> dtor = {[](void*){}, nullopt};
/**
* This is kinda bad, but stems from my inability to make gp::function work properly with constness
*/
bool(*cmptor)(const void*, const void*) = +[](const void*, const void*) -> bool {return false;};
static_assert(all_of_fixed_size<T...>::value, "not fixed");
public:
@ -55,6 +59,9 @@ namespace gp{
new(dest) actual(gp::move(*(actual*)src));
}, nullopt);
cpytor((char*)&value, data);
cmptor = +[](const void* lhs, const void* rhs) {
return *reinterpret_cast<const U*>(lhs) == *reinterpret_cast<const U*>(rhs);
};
}
static_assert(list_contains_class<int, int>::value, "list_contains_class doesn't work properly");
@ -84,6 +91,9 @@ namespace gp{
new(dest) actual(gp::move(*(actual*)src));
}, nullopt);
mvtor((char*)&value, data);
cmptor = +[](const void* lhs, const void* rhs) {
return *reinterpret_cast<const U*>(lhs) == *reinterpret_cast<const U*>(rhs);
};
}
fixed_variant(const fixed_variant& oth)
@ -91,6 +101,7 @@ namespace gp{
, dtor{oth.dtor}
, cpytor{oth.cpytor}
, mvtor{oth.mvtor}
, cmptor{oth.cmptor}
{
cpytor((char*)oth.data, (char*)data);
}
@ -100,6 +111,7 @@ namespace gp{
, dtor{oth.dtor}
, cpytor{oth.cpytor}
, mvtor{oth.mvtor}
, cmptor{oth.cmptor}
{
cpytor(oth.data, data);
}
@ -109,6 +121,7 @@ namespace gp{
, dtor{oth.dtor}
, cpytor{oth.cpytor}
, mvtor{oth.mvtor}
, cmptor{oth.cmptor}
{
oth.index = std::numeric_limits<std::size_t>::max();
mvtor(oth.data, data);
@ -147,6 +160,7 @@ namespace gp{
dtor = value.dtor;
mvtor = value.mvtor;
cpytor(value.data, data);
cmptor = value.cmptor;
}
void operator=(fixed_variant&& value)
@ -161,6 +175,7 @@ namespace gp{
index = value.index;
value.index = std::numeric_limits<std::size_t>::max();
mvtor(value.data, data);
cmptor = value.cmptor;
}
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
@ -175,6 +190,9 @@ namespace gp{
dtor = gp::function([](void* thing){((U*)thing)->~U();}, nullopt);
cpytor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(*(U*)src);}, nullopt);
mvtor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));}, nullopt);
cmptor = +[](const void* lhs, const void* rhs) {
return *reinterpret_cast<const U*>(lhs) == *reinterpret_cast<const U*>(rhs);
};
}
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
@ -189,6 +207,9 @@ namespace gp{
dtor = gp::function([](void* thing){((U*)thing)->~U();}, nullopt);
cpytor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(*(U*)src);}, nullopt);
mvtor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));}, nullopt);
cmptor = +[](const void* lhs, const void* rhs) {
return *reinterpret_cast<const U*>(lhs) == *reinterpret_cast<const U*>(rhs);
};
}
~fixed_variant()
@ -199,7 +220,7 @@ namespace gp{
index = std::numeric_limits<std::size_t>::max();
}
}
/**
* @brief Brutally decay the variant into the given type.
Will throw (@see bad_variant_access) if exceptions are enabled, else behaviour is undefined.
@ -219,6 +240,26 @@ namespace gp{
}
return *reinterpret_cast<U*>(data);
}
/**
* @brief Brutally decay the variant into the given type.
Will throw (@see bad_variant_access) if exceptions are enabled, else behaviour is undefined.
*
* @tparam U the type to decay towards
* @return constexpr U& a decayed reference to the variant
*/
template<typename U>
constexpr const U& value() const
{
if constexpr (gp_config::has_exceptions)
{
if(r_index_of<gp::remove_cvref_t<U>, T...>::value != index)
{
throw bad_variant_access<U>{};
}
}
return *reinterpret_cast<const U*>(data);
}
/**
* @brief Tests if the variant is of a particular type.
@ -228,7 +269,7 @@ namespace gp{
* @return false if the types don't match
*/
template<typename U>
constexpr bool is_a()
constexpr bool is_a() const
{
if(r_index_of<gp::remove_cvref_t<U>, T...>::value == index)
{
@ -239,5 +280,13 @@ namespace gp{
return false;
}
}
bool operator==(const fixed_variant& rhs) const {
if(index != rhs.index) {
return false;
}
// TODO: find a way to remove those const casts, the underlying things also use const so it is safe but kind ew
return cmptor(reinterpret_cast<const void*>(const_cast<const fixed_variant*const>(this)), reinterpret_cast<const void*>(const_cast<const fixed_variant*const>(&rhs)));
}
};
}

+ 1
- 1
tests/gp_test.cpp View File

@ -703,7 +703,7 @@ struct alloc_bench_test : public test_scaffold {
virtual int run() {
int res = 0;
if(do_bench) {
auto store = std::make_unique<std::array<char, 1 << 16>>();
auto store = std::make_unique<gp::array<char, 1 << 16>>();
using buddy_loc = gp::buddy<>;
using arena_loc = gp::arena;
buddy_loc bud{&*store->begin(), store->size()};

Loading…
Cancel
Save