summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--serialize/packbits-read.cpp (renamed from serialize/packbits.cpp)18
-rw-r--r--serialize/packbits-read.hpp8
-rw-r--r--serialize/packbits-write.cpp11
-rw-r--r--serialize/packbits-write.hpp63
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