diff options
-rw-r--r-- | serialize/packbits-impl.cpp | 16 | ||||
-rw-r--r-- | serialize/packbits-impl.hpp | 13 | ||||
-rw-r--r-- | serialize/packbits-read.cpp | 127 | ||||
-rw-r--r-- | serialize/packbits-read.hpp | 132 | ||||
-rw-r--r-- | serialize/packbits-write.cpp | 53 | ||||
-rw-r--r-- | serialize/packbits-write.hpp | 90 |
6 files changed, 0 insertions, 431 deletions
diff --git a/serialize/packbits-impl.cpp b/serialize/packbits-impl.cpp deleted file mode 100644 index b03b31b6..00000000 --- a/serialize/packbits-impl.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "packbits-impl.hpp" -#include "compat/exception.hpp" - -namespace floormat::Pack_impl { - -void throw_on_read_nonzero() noexcept(false) -{ - throw std::runtime_error{"extra bits in pack_read()"}; -} - -void throw_on_write_input_bit_overflow() noexcept(false) -{ - throw std::runtime_error{"extra bits in pack_write()"}; -} - -} // namespace floormat::Pack_impl diff --git a/serialize/packbits-impl.hpp b/serialize/packbits-impl.hpp deleted file mode 100644 index 3e57ea75..00000000 --- a/serialize/packbits-impl.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -namespace floormat::Pack_impl { - -[[noreturn]] void throw_on_read_nonzero() noexcept(false); -[[noreturn]] void throw_on_write_input_bit_overflow() noexcept(false); - -template<size_t... Ns> struct expand_sum; -template<size_t N, size_t... Ns> struct expand_sum<N, Ns...> { static constexpr size_t value = N + expand_sum<Ns...>::value; }; -template<> struct expand_sum<> { static constexpr size_t value = 0; }; -template<size_t... Ns> constexpr inline size_t sum = expand_sum<Ns...>::value; - -} // namespace floormat::Pack_impl diff --git a/serialize/packbits-read.cpp b/serialize/packbits-read.cpp deleted file mode 100644 index d8b9451c..00000000 --- a/serialize/packbits-read.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#include "packbits-read.hpp" -#include "compat/assert.hpp" -#include "compat/exception.hpp" - -namespace floormat { - -using namespace floormat::Pack_impl; - -namespace { - -static_assert(sum<1, 2, 3, 4, 5> == 6*(6-1)/2); -static_assert(sum<5, 10, 15> == 30); - -using u32 = uint32_t; -using u16 = uint16_t; -using u8 = uint8_t; - -template<std::unsigned_integral T, size_t N> constexpr inline T lowbits = N == sizeof(T)*8 ? (T)-1 : (T{1} << N)-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>{}.Left == 14); - -constexpr bool test1() -{ - constexpr size_t bits[] = { 5, 2, 1 }; - constexpr size_t vals[] = { 8, 3, 1, 0 }; - - constexpr auto S0 = input<uint8_t, vals[0]>{0b10111011}; - constexpr auto S1 = input<uint8_t, vals[1]>{0b00000101}; - constexpr auto S2 = input<uint8_t, vals[2]>{0b00000001}; - constexpr auto S3 = input<uint8_t, vals[3]>{0b00000000}; - - using P0 = std::decay_t<decltype(S0)>; - using P1 = P0::next<bits[0]>; - using P2 = P1::next<bits[1]>; - using P3 = P2::next<bits[2]>; - - static_assert(std::is_same_v<P0, input<uint8_t, vals[0]>>); - static_assert(std::is_same_v<P1, input<uint8_t, vals[1]>>); - static_assert(std::is_same_v<P2, input<uint8_t, vals[2]>>); - static_assert(std::is_same_v<P3, input<uint8_t, vals[3]>>); - - static_assert(S0.advance< 0>() == S0.value); - static_assert(S0.advance<bits[0]>() == S1.value); - static_assert(S1.advance<bits[1]>() == S2.value); - static_assert(S2.advance<bits[2]>() == S3.value); - - static_assert(S0.get<bits[0]>() == (S0.value & (1<<bits[0])-1)); - static_assert(S1.get<bits[1]>() == (S1.value & (1<<bits[1])-1)); - static_assert(S2.get<bits[2]>() == (S2.value & (1<<bits[2])-1)); - static_assert(S3.check_zero()); - - return true; -} -static_assert(test1()); - -constexpr bool test3() -{ - constexpr auto S0 = input<uint16_t, 16>{0b1110100110001011}; - constexpr auto S1 = input<uint16_t, 4>{0b1110}; - constexpr auto S2 = input<uint16_t, 1>{0b1}; - - static_assert(S0.get<12>() == 0b100110001011); - static_assert(S0.advance<12>() == S1.value); - - static_assert(S1.get<3>() == 0b110); - static_assert(S1.advance<3>() == S2.value); - - static_assert(S2.get<1>() == 0b1); - static_assert(S2.advance<1>() == 0); - - return true; -} -static_assert(test3()); - -template<size_t N> using f32 = input_field<uint32_t, N>; -template<size_t N> using f8 = input_field<uint8_t, N>; - -constexpr bool test4() -{ - - { - static_assert(lowbits<uint32_t, 17> == 0x1ffffU); - //auto tuple = std::tuple<f32<17>&, f32<14>&, f32<1>&>{a, b, c}; - f32<17> a; f32<14> b; f32< 1> c; - auto tuple = std::tie(a, b, c); - read_(tuple, input<uint32_t, 32>{(uint32_t)-1}, std::make_index_sequence<3>{}); - fm_assert(a == lowbits<uint32_t, 17>); - fm_assert(b == lowbits<uint32_t, 14>); - fm_assert(c & 1); - } - { - f8<1> a; - f8<3> b; - f8<2> c; - read_(std::tie(a, b, c), input<uint8_t, 8>{0b101011}, std::make_index_sequence<3>{}); - fm_assert(a == 0b1); - fm_assert(b == 0b101); - fm_assert(c == 0b10); - } - { - read_(std::tuple<>{}, input<uint8_t, 8>{0}, std::index_sequence<>{}); - //f32<2> a, b, c; - //read_(std::tuple<>{}, input<uint8_t, 8>{1}, std::index_sequence<>{}); - //read_(std::tie(a, b, c), input<uint8_t, 5>{0b11111}, std::make_index_sequence<3>{}); - //(void)input<uint8_t, 9>{}; - //read_(std::tie(a), input<uint8_t, 8>{3}, std::index_sequence<0>{}); fm_assert(a == 3); - //f8<1> d; read_(std::tie(d), input<uint8_t, 8>{1}, std::index_sequence<>{}); - } - { - f8<1> a; f8<3> b; f8<2> c; - pack_read(std::tie(a, b, c), uint8_t{0b101011}); - fm_assert(a == 0b1); - fm_assert(b == 0b101); - fm_assert(c == 0b10); - } - - return true; -} -static_assert(test4()); - -} // namespace - -} // namespace floormat diff --git a/serialize/packbits-read.hpp b/serialize/packbits-read.hpp deleted file mode 100644 index 4ad3aa74..00000000 --- a/serialize/packbits-read.hpp +++ /dev/null @@ -1,132 +0,0 @@ -#pragma once -#include "packbits-impl.hpp" -#include "compat/assert.hpp" -#include <type_traits> -#include <concepts> -#include <tuple> - -namespace floormat::Pack_impl { - -template<std::unsigned_integral T, size_t LENGTH> -struct input_field final -{ - static_assert(LENGTH > 0); - static_assert(LENGTH <= sizeof(T)*8); - static constexpr size_t Length = LENGTH; - T value; - constexpr T operator*() const { return value; } - constexpr operator T() const { return value; } -}; - -template<std::unsigned_integral T, size_t LEFT> -struct input -{ - static_assert(LEFT > 0); - static_assert(LEFT <= sizeof(T)*8); - static constexpr size_t Left = LEFT; - - T value; - - template<size_t N> - struct next_ - { - static_assert(N <= LEFT); - using type = input<T, LEFT - N>; - }; - template<size_t N> using next = typename next_<N>::type; - - template<size_t N> - constexpr CORRADE_ALWAYS_INLINE T get() const - { - static_assert(N > 0); - static_assert(N <= sizeof(T)*8); - static_assert(N <= LEFT); - return T(value & (T{1} << N) - T{1}); - } - - template<size_t N> - constexpr T advance() const - { - static_assert(N <= sizeof(T)*8); - static_assert(N <= LEFT); - return T(value >> N); - } - - constexpr bool operator==(const input&) const noexcept = default; - [[nodiscard]] constexpr inline bool check_zero() const { return value == T{0}; } -}; - -template<std::unsigned_integral T> -struct input<T, 0> -{ - static constexpr size_t Left = 0; - using Type = T; - T value; - - template<size_t N> [[maybe_unused]] constexpr T get() const = delete; - template<size_t N> [[maybe_unused]] constexpr T advance() const = delete; - constexpr bool operator==(const input&) const noexcept = default; - [[nodiscard]] constexpr inline bool check_zero() const { return true; } - - template<size_t N> struct next - { - static_assert(!N, "reading past the end"); - static_assert( N, "reading past the end"); - }; -}; - -template<typename T> struct is_input_field : std::bool_constant<false> {}; -template<std::unsigned_integral T, size_t N> struct is_input_field<input_field<T, N>> : std::bool_constant<true> { static_assert(N > 0); }; - -template<typename Field> -requires requires (Field& x) -{ - { size_t{Field::Length} > 0 }; - sizeof(std::decay_t<decltype(x.value)>); - requires std::unsigned_integral<std::decay_t<decltype(x.value)>>; -} -struct is_input_field<Field> : std::bool_constant<true> {}; - -template<std::unsigned_integral T, typename Tuple, size_t Left, size_t I, size_t... Is> -constexpr CORRADE_ALWAYS_INLINE void read_(Tuple&& tuple, input<T, Left> st, std::index_sequence<I, Is...>) -{ - using U = std::decay_t<Tuple>; - static_assert(Left <= sizeof(T)*8, "bits to read count too large"); - static_assert(Left > 0, "too many bits to write"); - static_assert(std::tuple_size_v<U> >= sizeof...(Is)+1, "index count larger than tuple element count"); - static_assert(I < std::tuple_size_v<U>, "too few tuple elements"); - using Field = std::decay_t<std::tuple_element_t<I, U>>; - static_assert(is_input_field<Field>{}, "tuple element must be input_field<T, N>"); - constexpr size_t Size = Field::Length; - static_assert(Size <= Left, "data type too small"); - using next_type = typename input<T, Left>::template next<Size>; - std::get<I>(tuple).value = st.template get<Size>(); - T next_value = st.template advance<Size>(); - read_(floormat::forward<Tuple>(tuple), next_type{ next_value }, std::index_sequence<Is...>{}); -} - -template<std::unsigned_integral T, typename Tuple, size_t Left> -constexpr CORRADE_ALWAYS_INLINE void read_(Tuple&&, input<T, Left> st, std::index_sequence<>) -{ - if (!st.check_zero()) [[unlikely]] - throw_on_read_nonzero(); -} - -} // namespace floormat::Pack_impl - -namespace floormat { - -template<std::unsigned_integral T, typename Tuple> constexpr void pack_read(Tuple&& tuple, T value) -requires requires (const Tuple& tuple) { - std::tuple_size_v<Tuple> > 0uz; - Pack_impl::is_input_field<std::decay_t<decltype(std::get<0>(tuple))>>::value; -} -{ - constexpr size_t nbits = sizeof(T)*8, - tuple_size = std::tuple_size_v<std::decay_t<Tuple>>; - Pack_impl::read_(floormat::forward<Tuple>(tuple), - Pack_impl::input<T, nbits>{value}, - std::make_index_sequence<tuple_size>{}); -} - -} // namespace floormat diff --git a/serialize/packbits-write.cpp b/serialize/packbits-write.cpp deleted file mode 100644 index 7dab800a..00000000 --- a/serialize/packbits-write.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "packbits-write.hpp" - -namespace floormat { - -namespace { - -using namespace floormat::Pack_impl; - -using u32 = uint32_t; -using u16 = uint16_t; -using u8 = uint8_t; -template<size_t N> using f32 = output_field<u32, N>; -template<size_t N> using f16 = output_field<u16, N>; -template<size_t N> using f8 = output_field<u8, N>; - -static_assert(write_(std::tuple<output_field<u32, 13>>{4242}, output<u32, 32, 32>{0}, std::index_sequence<0>{}) == 4242u); - -static_assert(write_( - std::tuple{f8<3>{7}, f8<2>{3}, f8<1>{1}}, - output<u8, 8, 6>{0}, - std::make_index_sequence<3>{} -) == (1 << 6) - 1); - -static_assert(write_( - std::tuple{f32<2>{0b10}, f32<3>{0b011}, f32<3>{0b001}}, - output<u32, 32, 32>{0}, - make_reverse_index_sequence<3>{}) == 0b000101110); - -static_assert(pack_write(std::tuple{f32<2>{0b10}, f32<3>{0b011}, f32<3>{0b01}}) == 0b00101110); -//static_assert(pack_write(std::tuple{f32<2>{0b10}, f32<3>{0b1011}, f32<3>{0b001}}) == 0b000101110); -static_assert(pack_write(std::tuple{f8<2>{0b10}, f8<3>{0b011}, f8<3>{0b01}}) == 0b00101110); -//static_assert(pack_write(std::tuple{f8<2>{0b10}, f8<3>{0b011}, f8<4>{0b01}}) == 0b00101110); -//static_assert(pack_write(std::tuple{}) == 0); -static_assert(pack_write(std::tuple{f8<1>{0b1}, f8<3>{0b101}, f8<2>{0b10}}) == 0b101011); - -#if 0 // check disassembly -u32 foo1(u32 a, u32 b, u32 c); -u32 foo1(u32 a, u32 b, u32 c) -{ - return pack_write(std::tuple{f32<2>{a}, f32<3>{b}, f32<3>{c}}); -} -#endif - -} // namespace - -#if 0 -[[maybe_unused]] uint8_t test1(uint8_t a, uint8_t b, uint8_t c) -{ - return pack_write(std::tuple{f8<2>{a}, f8<3>{b}, f8<3>{c}}); -} -#endif - -} // namespace floormat diff --git a/serialize/packbits-write.hpp b/serialize/packbits-write.hpp deleted file mode 100644 index 4689419a..00000000 --- a/serialize/packbits-write.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#pragma once -#include "packbits-impl.hpp" -#include "compat/reverse-index-sequence.hpp" -#include <type_traits> -#include <bit> -#include <concepts> -#include <tuple> - -namespace floormat::Pack_impl { - -template<std::unsigned_integral T, size_t CAPACITY, size_t LEFT> -struct output -{ - static_assert(LEFT >= 0); - static_assert(LEFT <= CAPACITY); - static_assert(CAPACITY <= sizeof(T)*8); - static constexpr size_t Capacity = CAPACITY, Left = LEFT; - T value{0}; -}; - -template<std::unsigned_integral T, size_t LENGTH> -struct output_field -{ - static_assert(LENGTH > 0); - static_assert(LENGTH <= sizeof(T)*8); - static constexpr size_t Length = LENGTH; - T value; -}; - -template<typename T> struct is_output_field : std::bool_constant<false> {}; -template<std::unsigned_integral T, size_t N> struct is_output_field<output_field<T, N>> : std::bool_constant<true> { static_assert(N > 0); }; - -template<typename Field> -requires requires (const Field& x) { - { size_t{Field::Length} > 0 }; - sizeof(std::decay_t<decltype(x.value)>); - requires std::unsigned_integral<std::decay_t<decltype(x.value)>>; -} -struct is_output_field<Field> : std::bool_constant<true> {}; - -template<std::unsigned_integral T, size_t Capacity, size_t Left, size_t I, size_t... Is, typename Tuple> -constexpr CORRADE_ALWAYS_INLINE T write_(const Tuple& tuple, output<T, Capacity, Left> st, std::index_sequence<I, Is...>) -{ - static_assert(Capacity > 0); - static_assert(Capacity <= sizeof(T)*8); - static_assert(Left > 0, "too many bits to write"); - static_assert(Left <= Capacity, "too many bits to write"); - static_assert(I < std::tuple_size_v<Tuple>, "too few tuple elements"); - static_assert(is_output_field<std::decay_t<std::tuple_element_t<0, Tuple>>>{}, - "tuple element must be output_field<T,N>"); - constexpr size_t N = std::tuple_element_t<I, Tuple>::Length; - static_assert(N <= Left, "too many bits to write"); - - T x = std::get<I>(tuple).value; - - if (!((size_t)std::bit_width(x) <= N)) [[unlikely]] - throw_on_write_input_bit_overflow(); - T value = T(T(st.value << N) | x); - return write_(tuple, output<T, Capacity, Left - N>{value}, std::index_sequence<Is...>{}); -} - -template<std::unsigned_integral T, size_t Capacity, size_t Left, typename Tuple> -constexpr CORRADE_ALWAYS_INLINE T write_(const Tuple&, output<T, Capacity, Left> st, std::index_sequence<>) -{ - return st.value; -} - -} // namespace floormat::Pack_impl - -namespace floormat { - -template<typename Tuple> -requires requires (const Tuple& tuple) { - std::tuple_size_v<Tuple> > 0uz; - Pack_impl::is_output_field<std::decay_t<decltype(std::get<0>(tuple))>>::value; -} -[[nodiscard]] constexpr auto pack_write(const Tuple& tuple) -{ - using Field = std::decay_t<std::tuple_element_t<0, Tuple>>; - static_assert(Pack_impl::is_output_field<Field>{}); - using T = std::decay_t<decltype(std::declval<Field>().value)>; - constexpr size_t nbits = sizeof(T)*8, tuple_size = std::tuple_size_v<Tuple>; - return Pack_impl::write_(tuple, - Pack_impl::output<T, nbits, nbits>{T{0}}, - make_reverse_index_sequence<tuple_size>{}); -} - -constexpr uint8_t pack_write(const std::tuple<>&) = delete; - -} // namespace floormat |