summaryrefslogtreecommitdiffhomepage
path: root/serialize
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-01-13 01:09:20 +0100
committerStanislaw Halik <sthalik@misaki.pl>2024-01-13 02:29:09 +0100
commiteb2766a55358d1724ace532231892facd8fe2d75 (patch)
tree8c1649b5ff7121aa70ad00d2736c4ac6c5c5cba8 /serialize
parentaeb346ea244f15faf75b948de6fdf33c1431a6b1 (diff)
w
Diffstat (limited to 'serialize')
-rw-r--r--serialize/packbits.cpp41
-rw-r--r--serialize/packbits.hpp29
2 files changed, 47 insertions, 23 deletions
diff --git a/serialize/packbits.cpp b/serialize/packbits.cpp
index 12f80791..976e7f6e 100644
--- a/serialize/packbits.cpp
+++ b/serialize/packbits.cpp
@@ -1,4 +1,5 @@
#include "packbits.hpp"
+#include "compat/assert.hpp"
namespace floormat {
@@ -8,15 +9,37 @@ namespace {
constexpr bool test1()
{
- using S1 = Storage<uint8_t, 8>;
- S1 st1{0b10111011};
- fm_assert(st1.value == 0b10111011);
-
- fm_assert(st1.get<3>() == 0b011);
- using S2 = typename S1::next<3>;
- S2 st2{st1.advance<3>()};
- static_assert(std::is_same_v<S2, Storage<uint8_t, 5>>);
- fm_assert(st2.value == 0b10111);
+ constexpr size_t left[] = { 8, 3, 2, 1, 0 };
+ constexpr size_t rest[] = { 0, 5, 6, 7, 8 };
+ constexpr size_t bits[] = { 5, 2, 1, 1 };
+ constexpr size_t vals[] = { 8, 3, 1, 0 };
+ constexpr auto S0 = Storage<uint8_t, left[0]>{0b10111011uz};
+ constexpr auto S1 = Storage<uint8_t, left[1]>{0b00000101uz};
+ constexpr auto S2 = Storage<uint8_t, left[2]>{0b00000010uz};
+ constexpr auto S3 = Storage<uint8_t, left[3]>{0b00000001uz};
+ constexpr auto S4 = Storage<uint8_t, left[4]>{0b00000000uz};
+ static_assert(S0.Capacity == 8 - rest[0]);
+ static_assert(S1.Capacity == 8 - rest[1]);
+ static_assert(S2.Capacity == 8 - rest[2]);
+ static_assert(S3.Capacity == 8 - rest[3]);
+ static_assert(S4.Capacity == 8 - rest[4]);
+ static_assert(S0.advance<left[0] - left[1]>() == S1.value);
+ static_assert(S1.advance<left[1] - left[2]>() == S2.value);
+ static_assert(S2.advance<left[2] - left[3]>() == S3.value);
+ static_assert(S3.advance<left[3] - left[4]>() == S4.value);
+ 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(P0::Capacity == vals[0]);
+ static_assert(P1::Capacity == vals[1]);
+ static_assert(P2::Capacity == vals[2]);
+ static_assert(P3::Capacity == vals[3]);
+ static_assert(std::is_same_v<P1, Storage<uint8_t, vals[1]>>);
+ static_assert(std::is_same_v<P2, Storage<uint8_t, vals[2]>>);
+ static_assert(std::is_same_v<P3, Storage<uint8_t, vals[3]>>);
+ static_assert(std::is_same_v<P4, Storage<uint8_t, vals[4]>>);
+
return true;
}
diff --git a/serialize/packbits.hpp b/serialize/packbits.hpp
index 6e388846..41e15177 100644
--- a/serialize/packbits.hpp
+++ b/serialize/packbits.hpp
@@ -1,5 +1,4 @@
#pragma once
-#include "compat/assert.hpp"
#include <type_traits>
#include <concepts>
@@ -29,14 +28,15 @@ struct check_size_overflow<T, Sum>
static constexpr bool result = Sum <= sizeof(T)*8;
};
-template<std::unsigned_integral T, size_t Capacity>
+template<std::unsigned_integral T, size_t CAPACITY>
struct Storage
{
- static_assert(Capacity <= sizeof(T)*8);
+ static_assert(CAPACITY <= sizeof(T)*8);
+ static constexpr size_t Capacity = CAPACITY;
T value;
template<size_t N>
- constexpr T get()
+ constexpr T get() const
{
static_assert(N <= sizeof(T)*8);
static_assert(N <= Capacity);
@@ -44,37 +44,38 @@ struct Storage
}
template<size_t N>
- constexpr T advance()
+ constexpr T advance() const
{
static_assert(N <= sizeof(T)*8);
static_assert(N <= Capacity);
return T(value >> N);
}
- template<size_t N> [[maybe_unused]] constexpr bool check_zero() = delete;
+ constexpr bool operator==(const Storage&) const noexcept = default;
+ constexpr bool check_zero() const = delete;
- template<size_t N>
- using next = Storage<T, Capacity - N>;
+ template<size_t N> using next = Storage<T, Capacity - N>;
};
template<std::unsigned_integral T>
struct Storage<T, 0>
{
+ static constexpr size_t Capacity = 0;
T value;
- template<size_t N> [[maybe_unused]] constexpr T get() = delete;
- template<size_t N> [[maybe_unused]] constexpr T advance() = delete;
+ 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 Storage&) const noexcept = default;
- template<size_t N> constexpr inline bool check_zero()
+ [[nodiscard]] constexpr inline bool check_zero() const
{
- fm_assert(value == T(0));
- return true;
+ return value == T(0);
}
template<size_t N> struct next
{
static_assert(!std::is_same_v<T, void>, "reading past the end");
- static_assert( std::is_same_v<T, void>, "can't happen!");
+ static_assert( std::is_same_v<T, void>, "reading past the end");
};
};