diff options
-rw-r--r-- | serialize/packbits-read.cpp (renamed from serialize/packbits.cpp) | 18 | ||||
-rw-r--r-- | serialize/packbits-read.hpp | 8 | ||||
-rw-r--r-- | serialize/packbits-write.cpp | 11 | ||||
-rw-r--r-- | serialize/packbits-write.hpp | 63 |
4 files changed, 76 insertions, 24 deletions
diff --git a/serialize/packbits.cpp b/serialize/packbits-read.cpp index e9ce54bc..f21a0de9 100644 --- a/serialize/packbits.cpp +++ b/serialize/packbits-read.cpp @@ -1,5 +1,4 @@ #include "packbits-read.hpp" -#include "packbits-write.hpp" #include "compat/assert.hpp" namespace floormat { @@ -13,8 +12,7 @@ template<std::unsigned_integral T, size_t N> constexpr inline T lowbits = (T{1} static_assert(!input<uint32_t, 3>{65535}.check_zero()); static_assert(input<uint32_t, 30>{65535}.advance<16>() == 0); -static_assert(input<uint32_t, 30>::next<16>{ input<uint32_t, 30>{65535}.advance<16>() -}.check_zero()); +static_assert(input<uint32_t, 30>::next<16>{ input<uint32_t, 30>{65535}.advance<16>() }.check_zero()); static_assert(input<uint32_t, 30>::next<16>{}.Capacity == 14); constexpr bool test1() @@ -80,7 +78,7 @@ constexpr bool test4() { Tuple_u32 tuple{}; static_assert(lowbits<uint32_t, 17> == 0x1ffffU); - read(tuple, input<uint32_t, 32>{(uint32_t)-1}, std::make_index_sequence<3>{}, make_pack<uint32_t, 17, 14, 1>{}); + read_(tuple, input<uint32_t, 32>{(uint32_t)-1}, std::make_index_sequence<3>{}, make_pack<uint32_t, 17, 14, 1>{}); auto [a, b, c] = tuple; fm_assert(a == lowbits<uint32_t, 17>); fm_assert(b == lowbits<uint32_t, 14>); @@ -88,7 +86,7 @@ constexpr bool test4() } { Tuple_u8 tuple{}; - read(tuple, input<uint8_t, 8>{0b101011}, std::make_index_sequence<3>{}, make_pack<uint8_t, 1, 3, 2>{}); + read_(tuple, input<uint8_t, 8>{0b101011}, std::make_index_sequence<3>{}, make_pack<uint8_t, 1, 3, 2>{}); auto [a, b, c] = tuple; fm_assert(a == 0b1); fm_assert(b == 0b101); @@ -96,13 +94,13 @@ constexpr bool test4() } { std::tuple<> empty_tuple; - read(empty_tuple, input<uint8_t, 8>{0}, std::index_sequence<>{}, make_pack<uint8_t>{}); + read_(empty_tuple, input<uint8_t, 8>{0}, std::index_sequence<>{}, make_pack<uint8_t>{}); Tuple_u8 tuple{}; (void)tuple; - //read(empty_tuple, input<uint8_t, 8>{1}, std::index_sequence<>{}, make_tuple<uint8_t>{}); - //read(tuple, input<uint8_t, 5>{0b11111}, std::make_index_sequence<3>{}, make_tuple<uint8_t, 2, 2, 2>{}); + //read_(empty_tuple, input<uint8_t, 8>{1}, std::index_sequence<>{}, make_tuple<uint8_t>{}); + //read_(tuple, input<uint8_t, 5>{0b11111}, std::make_index_sequence<3>{}, make_tuple<uint8_t, 2, 2, 2>{}); //(void)input<uint8_t, 9>{}; - //read(empty_tuple, input<uint8_t, 8>{}, std::index_sequence<0>{}, make_tuple<uint8_t, 1>{}); - //read(empty_tuple, input<uint8_t, 8>{1}, std::index_sequence<>{}, make_tuple<uint8_t, 1>{}); + //read_(empty_tuple, input<uint8_t, 8>{}, std::index_sequence<0>{}, make_tuple<uint8_t, 1>{}); + //read_(empty_tuple, input<uint8_t, 8>{1}, std::index_sequence<>{}, make_tuple<uint8_t, 1>{}); } return true; diff --git a/serialize/packbits-read.hpp b/serialize/packbits-read.hpp index 67b2efcb..ff132913 100644 --- a/serialize/packbits-read.hpp +++ b/serialize/packbits-read.hpp @@ -89,7 +89,7 @@ struct input<T, 0> }; template<std::unsigned_integral T, typename Place, size_t Left, size_t I, size_t... Is, size_t Size, typename... Sizes> -constexpr void read(Place& p, input<T, Left> st, std::index_sequence<I, Is...>, empty_pack_tuple<input_bits<T, Size>, Sizes...>) +constexpr void read_(Place& p, input<T, Left> st, std::index_sequence<I, Is...>, empty_pack_tuple<input_bits<T, Size>, Sizes...>) { static_assert(sizeof...(Is) == sizeof...(Sizes)); static_assert(Size <= Left, "data type too small"); @@ -98,18 +98,18 @@ constexpr void read(Place& p, input<T, Left> st, std::index_sequence<I, Is...>, using next_type = typename S::template next<Size>; get<I>(p) = st.template get<Size>(); T next_value = st.template advance<Size>(); - read(p, next_type{ next_value }, std::index_sequence<Is...>{}, empty_pack_tuple<Sizes...>{}); + read_(p, next_type{ next_value }, std::index_sequence<Is...>{}, empty_pack_tuple<Sizes...>{}); } template<std::unsigned_integral T, typename Place, size_t Left> -constexpr void read(Place&, input<T, Left> st, std::index_sequence<>, empty_pack_tuple<>) +constexpr void read_(Place&, input<T, Left> st, std::index_sequence<>, empty_pack_tuple<>) { fm_assert(st.check_zero()); } template<std::unsigned_integral T, typename Place, size_t Left, size_t... Is, typename... Sizes> requires(sizeof...(Is) != sizeof...(Sizes)) -constexpr void read(Place&, input<T, Left>, std::index_sequence<Is...>, empty_pack_tuple<Sizes...>) = delete; +constexpr void read_(Place&, input<T, Left>, std::index_sequence<Is...>, empty_pack_tuple<Sizes...>) = delete; template<std::unsigned_integral T, size_t... Ns> using make_pack = empty_pack_tuple<input_bits<T, Ns>...>; diff --git a/serialize/packbits-write.cpp b/serialize/packbits-write.cpp new file mode 100644 index 00000000..0b4fb4f1 --- /dev/null +++ b/serialize/packbits-write.cpp @@ -0,0 +1,11 @@ +#include "packbits-write.hpp" + +namespace floormat::detail_Pack_output { + +using u32 = uint32_t; +using u8 = uint8_t; + +template u32 write_(output<u32, 32>, output_field<u32, 1>); +static_assert(output<u32, 32>::next<1>::Capacity == 31); + +} // namespace floormat::detail_Pack_output diff --git a/serialize/packbits-write.hpp b/serialize/packbits-write.hpp index 34fc140f..faa3ff00 100644 --- a/serialize/packbits-write.hpp +++ b/serialize/packbits-write.hpp @@ -1,28 +1,71 @@ #pragma once +#include "compat/assert.hpp" +#include <type_traits> +#include <utility> #include <concepts> namespace floormat::detail_Pack_output { -template<std::unsigned_integral T> +template<size_t N> +struct output_bits final +{ + static_assert(N > 0); + static_assert(N < sizeof(size_t)*8); + + static constexpr size_t length = N; +}; + +template<std::unsigned_integral T, size_t CAPACITY> struct output { - T value = 0; - uint8_t capacity = sizeof(T)*8; + static_assert(std::is_fundamental_v<T>); + static_assert(CAPACITY <= sizeof(T)*8); + static constexpr size_t Capacity = CAPACITY; + + T value{0}; - constexpr inline output next(T x, uint8_t bits) const + template<size_t N> + constexpr T set(T x, output_bits<N>) const { - fm_assert(bits > 0 && bits <= capacity); - auto val = value; - val <<= bits; - T x_ = T(x & (T{1} << bits)- T{1}); + static_assert(N <= CAPACITY, "data type too small"); + static_assert(N > 0); + T value_{value}; + if constexpr(CAPACITY != sizeof(T)*8) + value_ <<= CAPACITY; + auto x_ = T(x & (T{1}<<N)-T{1}); fm_assert(x_ == x); - val |= x_; - return { val | x_, capacity - bits }; + value_ |= x_; + return value_; } + + template<size_t N> + struct next_ + { + static_assert(N > 0); + static_assert(N <= CAPACITY); + using type = output<T, CAPACITY - N>; + }; + + template<size_t N> using next = typename next_<N>::type; }; +template<typename T, size_t N> +using output_field = std::pair<T, output_bits<N>>; +template<typename... Ts> struct empty_pack_tuple {}; // todo copypasta +template<typename T, size_t Left, size_t F, typename... Fields> +constexpr T write_(output<T, Left> st, output_field<T, F> field, Fields... fields) +{ + T value = st.set(field.first, field.second); + using next = typename output<T, Left>::template next<F>; + return write_(next{value}, fields...); +} +template<typename T, size_t Left> +constexpr T write_(output<T, Left> st) +{ + return st.value; +} } // namespace floormat::detail_Pack_output |