diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-01-14 20:47:15 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-01-14 20:47:15 +0100 |
commit | b5f96dda3de339b2db61c531f6f486f9d3d45866 (patch) | |
tree | 21da3c8f9d9a3ced8aeef25ccbf184148184da5f | |
parent | 97fc4fcd50272dab1d2c6e94019502d42deb4a2c (diff) |
a
-rw-r--r-- | serialize/packbits.cpp | 63 | ||||
-rw-r--r-- | serialize/packbits.hpp | 70 |
2 files changed, 47 insertions, 86 deletions
diff --git a/serialize/packbits.cpp b/serialize/packbits.cpp index 634191fc..ffca868f 100644 --- a/serialize/packbits.cpp +++ b/serialize/packbits.cpp @@ -7,10 +7,11 @@ using namespace floormat::detail_Pack; namespace { +#if 0 template<std::unsigned_integral T, size_t Sum, typename... Xs> struct check_size_overflow; template<std::unsigned_integral T, std::unsigned_integral U, size_t Sum, size_t N, typename... Xs> -struct check_size_overflow<T, Sum, Bits_<U, N>, Xs...> +struct check_size_overflow<T, Sum, Bits<U, N>, Xs...> { static_assert(std::is_same_v<T, U>); static constexpr auto acc = Sum + size_t{N}; @@ -25,10 +26,10 @@ struct check_size_overflow<T, Sum> static constexpr size_t size = Sum; static constexpr bool result = Sum <= sizeof(T)*8; }; +#endif template<std::unsigned_integral T, size_t N> constexpr inline T lowbits = (T{1} << N)-T{1}; - -template<size_t Val> using us_bits = Bits_<uint16_t, Val>; +template<size_t Val> using us_bits = Bits<uint16_t, Val>; static_assert(!Storage<uint32_t, 3>{65535}.check_zero()); static_assert(Storage<uint32_t, 30>{65535}.advance<16>() == 0); @@ -72,6 +73,7 @@ constexpr bool test1() } static_assert(test1()); +#if 0 constexpr bool test2() { using foo1 = us_bits<2>; @@ -107,6 +109,7 @@ constexpr bool test2() return true; } static_assert(test2()); +#endif constexpr bool test3() { @@ -131,30 +134,36 @@ static_assert(std::is_same_v< make_tuple_type<uint8_t, 3>, std::tuple<uint8_t, constexpr bool test4() { - using Tuple = std::tuple<uint32_t, uint32_t, uint32_t>; - Tuple tuple{}; - assign_tuple2(tuple, Storage<uint32_t, 32>{(uint32_t)-1}, std::make_index_sequence<3>{}, - Bits_<uint32_t, 17>{}, Bits_<uint32_t, 14>{}, Bits_<uint32_t, 1>{}); - auto [a, b, c] = tuple; - - static_assert(lowbits<uint32_t, 17> != 0); - fm_assert(a == lowbits<uint32_t, 17>); - fm_assert(b == lowbits<uint32_t, 14>); - fm_assert(c & 1); - - //Assign::do_tuple(tuple, Storage<uint32_t, 32>{(uint32_t)-1}); - - return true; -} -static_assert(test4()); - -constexpr bool test5() -{ - auto st = Storage<uint32_t, 32>{0xB16B00B5}; - uint32_t a, b, c; - using Tuple = std::tuple<uint32_t&, uint32_t&, uint32_t&>; - auto t = Tuple{a, b, c}; - //assign_tuple<uint32_t, std::make_index_sequence<3>, Tuple, + using Tuple_u32 = make_tuple_type<uint32_t, 3>; + static_assert(std::is_same_v<Tuple_u32, std::tuple<uint32_t, uint32_t, uint32_t>>); + using Tuple_u8 = make_tuple_type<uint8_t, 3>; + { + Tuple_u32 tuple{}; + static_assert(lowbits<uint32_t, 17> == 0x1ffffU); + assign_tuple(tuple, Storage<uint32_t, 32>{(uint32_t)-1}, std::make_index_sequence<3>{}, Bits<uint32_t, 17>{}, Bits<uint32_t, 14>{}, Bits<uint32_t, 1>{}); + auto [a, b, c] = tuple; + fm_assert(a == lowbits<uint32_t, 17>); + fm_assert(b == lowbits<uint32_t, 14>); + fm_assert(c & 1); + } + { + Tuple_u8 tuple{}; + assign_tuple(tuple, Storage<uint8_t, 8>{0b101011}, std::make_index_sequence<3>{}, Bits<uint8_t, 1>{}, Bits<uint8_t, 3>{}, Bits<uint8_t, 2>{}); + auto [a, b, c] = tuple; + fm_assert(a == 0b1); + fm_assert(b == 0b101); + fm_assert(c == 0b10); + } + { + std::tuple<> empty_tuple; + assign_tuple(empty_tuple, Storage<uint8_t, 8>{0}, std::index_sequence<>{}); + Tuple_u8 tuple{}; (void)tuple; + // assign_tuple(empty_tuple, Storage<uint8_t, 8>{1}, std::index_sequence<>{}); + // assign_tuple(tuple, Storage<uint8_t, 5>{0b11111}, std::make_index_sequence<3>{}, Bits<uint8_t, 2>{}, Bits<uint8_t, 2>{}, Bits<uint8_t, 2>{}); + // (void)Storage<uint8_t, 9>{}; + //assign_tuple(empty_tuple, Storage<uint8_t, 8>{}, std::index_sequence<0>{}, Bits<uint8_t, 1>{}); + // assign_tuple(empty_tuple, Storage<uint8_t, 8>{1}, std::index_sequence<>{}, Bits<uint8_t, 1>{}); + } return true; } diff --git a/serialize/packbits.hpp b/serialize/packbits.hpp index c94f96d7..8a828f94 100644 --- a/serialize/packbits.hpp +++ b/serialize/packbits.hpp @@ -5,14 +5,13 @@ #include "compat/assert.hpp" namespace floormat::Pack { -template<std::unsigned_integral T, size_t N> struct Bits_; +template<std::unsigned_integral T, size_t N> struct Bits; } // namespace floormat::Pack namespace floormat::detail_Pack { using namespace floormat::Pack; - template<std::unsigned_integral T, size_t CAPACITY> struct Storage { @@ -79,80 +78,33 @@ struct make_tuple_type_ template<std::unsigned_integral T, size_t N> using make_tuple_type = typename make_tuple_type_<T, N>::Seq; template<typename T, typename Place, size_t Left, size_t I, size_t... Is, size_t Size, typename... Sizes> -constexpr void assign_tuple2(Place& p, Storage<T, Left> st, std::index_sequence<I, Is...>, Bits_<T, Size>, Sizes... sizes) +constexpr void assign_tuple(Place& p, Storage<T, Left> st, std::index_sequence<I, Is...>, Bits<T, Size>, Sizes... sizes) { + static_assert(Size <= Left, "too many bits requested"); + static_assert(I < std::tuple_size_v<Place>, "too few tuple members"); using S = Storage<T, Left>; using next_type = typename S::template next<Size>; get<I>(p) = st.template get<Size>(); T next_value = st.template advance<Size>(); - assign_tuple2(p, next_type{next_value}, std::index_sequence<Is...>{}, sizes...); + assign_tuple(p, next_type{next_value}, std::index_sequence<Is...>{}, sizes...); } template<typename T, typename Place, size_t Left> -constexpr void assign_tuple2(Place&, Storage<T, Left>, std::index_sequence<>) +constexpr void assign_tuple(Place&, Storage<T, Left> st, std::index_sequence<>) { + fm_assert(st.check_zero()); } -#if 0 -template<typename T, typename Indexes, typename... Sizes> struct assign_tuple; - -template<typename T, size_t Index, size_t... Indexes, size_t Size, typename... Sizes> -struct assign_tuple<T, std::index_sequence<Index, Indexes...>, Bits_<T, Size>, Sizes...> -{ - static_assert(Size <= sizeof(T)*8, "bit count can't be larger than sizeof(T)*8"); - static_assert(Size > 0, "bit count can't be zero"); - - template<typename Place, size_t Left> - static constexpr inline void do_tuple(Place& p, Storage<T, Left> st) - { - static_assert(requires (Place& p) { std::get<0>(p) = T{0}; }); - static_assert(std::tuple_size_v<Place> >= sizeof...(Indexes) + 1); - static_assert(Size <= Left, "not enough bits for element"); - - get<Index>(p) = st.template get<Size>(st.value); - using Next = typename Storage<T, Left>::template next<Size>; - assign_tuple<T, std::index_sequence<Indexes...>, Sizes...>:: - template do_tuple<Place, Next>(p, Next{st.template advance<Size>()}); - } - - static constexpr bool is_empty = false; -}; - -template<typename T, size_t Index, size_t... Indexes> -struct assign_tuple<T, std::index_sequence<Index, Indexes...>> -{ - static_assert(sizeof(T) == (size_t)-1, "too few lhs elements"); - static_assert(sizeof(T) != (size_t)-1); -}; - -template<typename T, size_t Size, typename... Sizes> -struct assign_tuple<T, std::index_sequence<>, Bits_<T, Size>, Sizes...> -{ - static_assert(sizeof(T) == (size_t)-1, "too few rhs elements"); - static_assert(sizeof(T) != (size_t)-1); -}; - -template<typename T> -struct assign_tuple<T, std::index_sequence<>> -{ - template<typename Place, size_t Left> - static constexpr inline void do_tuple(Place&, Storage<T, Left> st) - { - fm_assert(st.check_zero()); - } - - static constexpr bool is_empty = true; - using type = T; -}; - -#endif +template<typename T, typename Place, size_t Left, size_t... Is, typename... Sizes> +requires(sizeof...(Is) != sizeof...(Sizes)) +constexpr void assign_tuple(Place&, Storage<T, Left>, std::index_sequence<Is...>, Sizes...) = delete; } // namespace floormat::detail_Pack namespace floormat::Pack { template<std::unsigned_integral T, size_t N> -struct Bits_ final +struct Bits final { static_assert(std::is_fundamental_v<T>); static_assert(N > 0); |