From 61d4226624d15f5e03fbbcd41469d642f920acfe Mon Sep 17 00:00:00 2001 From: Ludovic 'Archivist' Lagouardette Date: Fri, 24 Nov 2023 15:03:25 +0100 Subject: [PATCH] updated a few containers, unveiled a bug --- include/gp/algorithms/move.hpp | 18 +++++++-- include/gp/containers/buffer.hpp | 64 ++++++++++++++++++++++++++++-- include/gp/containers/vector.hpp | 22 ++++++++-- include/gp/functional/function.hpp | 17 +++++++- include/gp/functional/variant.hpp | 53 ++++++++++++++++++++++++- tests/gp_test.cpp | 2 +- 6 files changed, 162 insertions(+), 14 deletions(-) diff --git a/include/gp/algorithms/move.hpp b/include/gp/algorithms/move.hpp index 789badd..8e56c2d 100644 --- a/include/gp/algorithms/move.hpp +++ b/include/gp/algorithms/move.hpp @@ -10,18 +10,30 @@ namespace gp{ { return (typename gp::remove_reference::type&&)value; } - - template + + template constexpr T&& forward(typename gp::remove_reference::type& t) noexcept { return static_cast(t); } - template + template constexpr T&& forward(typename gp::remove_reference::type&& t) noexcept { static_assert(!std::is_lvalue_reference_v,"bad forward of rvalue as lvalue"); return static_cast(t); } + + /*template + constexpr const T&& forward(const typename gp::remove_reference::type& t) noexcept + { + return static_cast(t); + } + template + constexpr const T&& forward(const typename gp::remove_reference::type&& t) noexcept + { + static_assert(!std::is_lvalue_reference_v,"bad forward of rvalue as lvalue"); + return static_cast(t); + }*/ template constexpr void swap( diff --git a/include/gp/containers/buffer.hpp b/include/gp/containers/buffer.hpp index 5935a69..1e093f6 100644 --- a/include/gp/containers/buffer.hpp +++ b/include/gp/containers/buffer.hpp @@ -10,6 +10,12 @@ #include namespace gp{ + + template + class buffer; + + template + bool hold_same_data(const gp::buffer& lhs, const gp::buffer& rhs); template class buffer final{ @@ -123,11 +129,19 @@ namespace gp{ } else { - return buffer(reinterpret_cast(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& lhs, const gp::buffer& rhs); + + bool starts_with(gp::buffer oth) { + return hold_same_data(this->slice_start(oth.size()), oth); + } + + optional front() { + if(size() == 0) return nullopt; + return *begin(); + } + + optional back() { + if(size() == 0) return nullopt; + return *slice_end(1).begin(); + } }; + + template + bool hold_same_data(const gp::buffer& lhs, const gp::buffer& 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; + } } \ No newline at end of file diff --git a/include/gp/containers/vector.hpp b/include/gp/containers/vector.hpp index b3b879d..f840400 100644 --- a/include/gp/containers/vector.hpp +++ b/include/gp/containers/vector.hpp @@ -118,7 +118,7 @@ namespace gp{ gp::swap(cap, oth.cap); } else { for(auto& elem : *this) { - elem->~T(); + elem.~T(); } sz = 0; if(capacity() begin() { return associated_iterator(&ary[0]); } - + constexpr gp::pointer_iterator end() { return associated_iterator(&ary[sz]); } + + constexpr gp::const_pointer_iterator begin() const + { + return associated_const_iterator(&ary[0]); + } + + constexpr gp::const_pointer_iterator end() const + { + return associated_const_iterator(&ary[sz]); + } constexpr gp::const_pointer_iterator cbegin() const { @@ -368,5 +378,9 @@ namespace gp{ { return gp::buffer{(T*)ary, (T*)ary+sz}; } + + T* data() { + return ary; + } }; } diff --git a/include/gp/functional/function.hpp b/include/gp/functional/function.hpp index 9018627..bebaa7c 100644 --- a/include/gp/functional/function.hpp +++ b/include/gp/functional/function.hpp @@ -20,6 +20,11 @@ namespace gp{ template class function; + /** + * TODO: Constness of arguments does weird things wherever forward is called, this needs some investigating + * @tparam ret + * @tparam args + */ template class function{ using fn_ptr = char*; @@ -28,6 +33,11 @@ namespace gp{ using condestruct_fn_t = void (*) (fn_ptr, fn_ptr); gp::optional> 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(argv)...); } + + ret operator()(const args&&... argv) const { + return invokator(data_size <= sizeof(data_ptr) ? (fn_ptr)&data_ptr : data_ptr, gp::forward(argv)...); + } bool ready() { + // TODO: add type safety to invocators with a toggleable check return invokator != nullptr; } }; diff --git a/include/gp/functional/variant.hpp b/include/gp/functional/variant.hpp index 8df87ff..2fac1ad 100644 --- a/include/gp/functional/variant.hpp +++ b/include/gp/functional/variant.hpp @@ -27,6 +27,10 @@ namespace gp{ gp::function cpytor = {[](void*, void*){}, nullopt}; gp::function mvtor = {[](void*, void*){}, nullopt}; gp::function 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::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(lhs) == *reinterpret_cast(rhs); + }; } static_assert(list_contains_class::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(lhs) == *reinterpret_cast(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::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::max(); mvtor(value.data, data); + cmptor = value.cmptor; } template::value,int>::type> @@ -175,6 +190,9 @@ namespace gp{ dtor = gp::function([](void* thing){((U*)thing)->~U();}, nullopt); cpytor = gp::function([](void* src, void* dest){new(dest) U(*(U*)src);}, nullopt); mvtor = gp::function([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));}, nullopt); + cmptor = +[](const void* lhs, const void* rhs) { + return *reinterpret_cast(lhs) == *reinterpret_cast(rhs); + }; } template::value,int>::type> @@ -189,6 +207,9 @@ namespace gp{ dtor = gp::function([](void* thing){((U*)thing)->~U();}, nullopt); cpytor = gp::function([](void* src, void* dest){new(dest) U(*(U*)src);}, nullopt); mvtor = gp::function([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));}, nullopt); + cmptor = +[](const void* lhs, const void* rhs) { + return *reinterpret_cast(lhs) == *reinterpret_cast(rhs); + }; } ~fixed_variant() @@ -199,7 +220,7 @@ namespace gp{ index = std::numeric_limits::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(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 + constexpr const U& value() const + { + if constexpr (gp_config::has_exceptions) + { + if(r_index_of, T...>::value != index) + { + throw bad_variant_access{}; + } + } + return *reinterpret_cast(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 - constexpr bool is_a() + constexpr bool is_a() const { if(r_index_of, 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_cast(this)), reinterpret_cast(const_cast(&rhs))); + } }; } \ No newline at end of file diff --git a/tests/gp_test.cpp b/tests/gp_test.cpp index 57a8473..c6b3c03 100644 --- a/tests/gp_test.cpp +++ b/tests/gp_test.cpp @@ -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>(); + auto store = std::make_unique>(); using buddy_loc = gp::buddy<>; using arena_loc = gp::arena; buddy_loc bud{&*store->begin(), store->size()};