From 84b8a220091e64bb1dd6c66fa49edac673df4ddb Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 12 Jan 2024 21:51:38 +0100 Subject: serialize/packbits: wip --- serialize/packbits.cpp | 55 ++++++++++++++++++++++++++++ serialize/packbits.hpp | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 serialize/packbits.cpp create mode 100644 serialize/packbits.hpp diff --git a/serialize/packbits.cpp b/serialize/packbits.cpp new file mode 100644 index 00000000..81c6c172 --- /dev/null +++ b/serialize/packbits.cpp @@ -0,0 +1,55 @@ +#include "packbits.hpp" + +namespace floormat { + +using namespace floormat::detail_Pack; + +namespace { + +constexpr bool test1() +{ + using S1 = Storage; + S1 st1{0b10111011}; + fm_assert(st1.value == 0b10111011); + + fm_assert(st1.get<3>() == 0b011); + using S2 = typename S1::next<3>; + S2 st2{st1.advance<3>()}; + static_assert(std::is_same_v>); + fm_assert(st2.value == 0b10111); + + return true; +} +static_assert(test1()); + +namespace test2 { +template using ibits = Bits_; +using foo1 = ibits<2>; +using foo2 = ibits<10>; +using foo3 = ibits<4>; +using bar1 = check_size_overflow; +static_assert(bar1::result); +static_assert(bar1::size == 12); + +using bar2 = check_size_overflow; +static_assert(bar2::result); +static_assert(bar2::size == 10); + +using bar3 = check_size_overflow; +static_assert(bar3::result); +static_assert(bar3::size == 16); + +using foo4 = ibits<1>; +using bar4 = check_size_overflow; +static_assert(!bar4::result); +static_assert(bar4::size == 17); + +using foo5 = ibits<20>; +using bar5 = check_size_overflow; +static_assert(!bar5::result); +static_assert(bar5::size == 37); +} // namespace test2 + +} // namespace + +} // namespace floormat diff --git a/serialize/packbits.hpp b/serialize/packbits.hpp new file mode 100644 index 00000000..6e388846 --- /dev/null +++ b/serialize/packbits.hpp @@ -0,0 +1,98 @@ +#pragma once +#include "compat/assert.hpp" +#include +#include + +namespace floormat::Pack { +template struct Bits_; +} // namespace floormat::Pack + +namespace floormat::detail_Pack { + +using namespace floormat::Pack; +template struct check_size_overflow; + +template +struct check_size_overflow, Xs...> +{ + static_assert(std::is_same_v); + static constexpr auto acc = Sum + size_t{N}; + using next_check = check_size_overflow; + static constexpr auto size = next_check::size; + static constexpr bool result = next_check::result; +}; + +template +struct check_size_overflow +{ + static constexpr size_t size = Sum; + static constexpr bool result = Sum <= sizeof(T)*8; +}; + +template +struct Storage +{ + static_assert(Capacity <= sizeof(T)*8); + T value; + + template + constexpr T get() + { + static_assert(N <= sizeof(T)*8); + static_assert(N <= Capacity); + return T(value & (T(1) << N) - T(1)); + } + + template + constexpr T advance() + { + static_assert(N <= sizeof(T)*8); + static_assert(N <= Capacity); + return T(value >> N); + } + + template [[maybe_unused]] constexpr bool check_zero() = delete; + + template + using next = Storage; +}; + +template +struct Storage +{ + T value; + + template [[maybe_unused]] constexpr T get() = delete; + template [[maybe_unused]] constexpr T advance() = delete; + + template constexpr inline bool check_zero() + { + fm_assert(value == T(0)); + return true; + } + + template struct next + { + static_assert(!std::is_same_v, "reading past the end"); + static_assert( std::is_same_v, "can't happen!"); + }; +}; + +} // namespace floormat::detail_Pack + +namespace floormat::Pack { + +template +struct Bits_ final +{ + static_assert(std::is_fundamental_v); + static_assert(N > 0); + static_assert(N < sizeof(T)*8); + + using type = T; + static constexpr auto bits = N; +}; + + + +} // namespace floormat::Pack -- cgit v1.2.3