summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-01-14 19:48:43 +0100
committerStanislaw Halik <sthalik@misaki.pl>2024-01-14 19:48:43 +0100
commit6c747d58f85d29987011d9519109928c3438fcef (patch)
tree4713f84d7bc06d4ce8e9b71951546345ebdf5040
parent9b957f519620a07597fa28f796c09bdbef2e8fab (diff)
a
-rw-r--r--serialize/packbits.cpp27
-rw-r--r--serialize/packbits.hpp77
2 files changed, 92 insertions, 12 deletions
diff --git a/serialize/packbits.cpp b/serialize/packbits.cpp
index 6ed898c7..86c6f605 100644
--- a/serialize/packbits.cpp
+++ b/serialize/packbits.cpp
@@ -7,6 +7,8 @@ using namespace floormat::detail_Pack;
namespace {
+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>;
static_assert(!Storage<uint32_t, 3>{65535}.check_zero());
@@ -110,7 +112,30 @@ static_assert(std::is_same_v< make_tuple_type<uint8_t, 3>, std::tuple<uint8_t,
constexpr bool test4()
{
- auto t = std::tuple<unsigned, unsigned, unsigned>();
+ 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,
return true;
}
diff --git a/serialize/packbits.hpp b/serialize/packbits.hpp
index 12c1dd31..527b7676 100644
--- a/serialize/packbits.hpp
+++ b/serialize/packbits.hpp
@@ -5,7 +5,7 @@
#include "compat/assert.hpp"
namespace floormat::Pack {
-template<std::unsigned_integral T, uint8_t N> struct Bits_;
+template<std::unsigned_integral T, size_t N> struct Bits_;
} // namespace floormat::Pack
namespace floormat::detail_Pack {
@@ -13,7 +13,7 @@ namespace floormat::detail_Pack {
using namespace floormat::Pack;
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, uint8_t N, typename... Xs>
+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...>
{
static_assert(std::is_same_v<T, U>);
@@ -95,25 +95,80 @@ 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>
-static void assign_to_tuple(Place&, Storage<T, Left> st, std::index_sequence<>)
+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)
{
- fm_assert(st.check_zero());
+ 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...);
}
-template<typename T, typename Place, size_t Left, size_t Size, size_t... Sizes>
-static void assign_to_tuple(Place& p, Storage<T, Left> st, std::index_sequence<Size, Sizes...>)
+template<typename T, typename Place, size_t Left>
+constexpr void assign_tuple2(Place&, Storage<T, Left>, std::index_sequence<>)
{
- using std::get;
- get<Size>(p) = st.template get<Size>(st);
- assign_to_tuple(p, st.template advance<Size>(), std::index_sequence<Sizes...>{});
}
+#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
+
} // namespace floormat::detail_Pack
namespace floormat::Pack {
-template<std::unsigned_integral T, uint8_t N>
+template<std::unsigned_integral T, size_t N>
struct Bits_ final
{
static_assert(std::is_fundamental_v<T>);