From b8daa75b9b0e50a11c95869a74742403f903c77c Mon Sep 17 00:00:00 2001 From: Michael Caisse Date: Sat, 24 Aug 2024 18:11:50 -0700 Subject: [PATCH] enable byte indexing for msg::located at --- include/msg/field.hpp | 43 +++++++++++++++++++++++++++++++++----- test/msg/field_extract.cpp | 24 ++++++++++++++++++++- test/msg/field_insert.cpp | 28 +++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 6 deletions(-) diff --git a/include/msg/field.hpp b/include/msg/field.hpp index da7dad6d..25652172 100644 --- a/include/msg/field.hpp +++ b/include/msg/field.hpp @@ -83,7 +83,7 @@ struct field_spec_t { constexpr static auto size = BitSize; }; -template +template struct bits_locator_t { constexpr static auto size = BitSize; @@ -112,7 +112,7 @@ struct bits_locator_t { constexpr auto Msb = Lsb + BitSize - 1u; constexpr auto BaseIndex = - DWordIndex * sizeof(std::uint32_t) / sizeof(elem_t); + Index * sizeof(std::uint32_t) / sizeof(elem_t); constexpr auto elem_size = stdx::bit_size(); constexpr auto max_idx = BaseIndex + Msb / elem_size; @@ -158,7 +158,7 @@ struct bits_locator_t { constexpr auto Msb = Lsb + BitSize - 1u; constexpr auto BaseIndex = - DWordIndex * sizeof(std::uint32_t) / sizeof(elem_t); + Index * sizeof(std::uint32_t) / sizeof(elem_t); constexpr auto elem_size = stdx::bit_size(); [[maybe_unused]] constexpr auto min_idx = BaseIndex + Lsb / elem_size; @@ -209,13 +209,13 @@ struct bits_locator_t { template constexpr static auto fits_inside() -> bool { constexpr auto Msb = Lsb + BitSize - 1; - return DWordIndex * 32 + Msb <= NumBits; + return Index * 32 + Msb <= NumBits; } template constexpr static auto extent_in() -> std::size_t { constexpr auto msb = Lsb + BitSize - 1; constexpr auto msb_extent = (msb + CHAR_BIT - 1) / CHAR_BIT; - constexpr auto base_extent = DWordIndex * sizeof(std::uint32_t); + constexpr auto base_extent = Index * sizeof(std::uint32_t); constexpr auto extent = base_extent + msb_extent; return (extent + sizeof(T) - 1) / sizeof(T); } @@ -277,12 +277,19 @@ template struct field_locator_t { }; } // namespace detail +enum struct byte_index_t : std::uint32_t {}; enum struct dword_index_t : std::uint32_t {}; enum struct msb_t : std::uint32_t {}; enum struct lsb_t : std::uint32_t {}; inline namespace literals { // NOLINTNEXTLINE(google-runtime-int) +CONSTEVAL auto operator""_bi(unsigned long long int v) -> byte_index_t { + return static_cast(v); +} +CONSTEVAL auto operator""_dwi(unsigned long long int v) -> dword_index_t { + return static_cast(v); +} CONSTEVAL auto operator""_dw(unsigned long long int v) -> dword_index_t { return static_cast(v); } @@ -323,6 +330,32 @@ template <> struct at { } }; +template <> struct at { + byte_index_t index_{}; + msb_t msb_{}; + lsb_t lsb_{}; + + [[nodiscard]] constexpr auto + index() const -> std::underlying_type_t { + return stdx::to_underlying(index_) / 4; + } + [[nodiscard]] constexpr auto lsb() const -> std::underlying_type_t { + return (stdx::to_underlying(index_) * 8) % 32 + + stdx::to_underlying(lsb_); + } + [[nodiscard]] constexpr auto size() const -> std::underlying_type_t { + return stdx::to_underlying(msb_) - stdx::to_underlying(lsb_) + 1; + } + [[nodiscard]] constexpr auto valid() const -> bool { + return size() <= 8 and + stdx::to_underlying(msb_) >= stdx::to_underlying(lsb_); + } + [[nodiscard]] constexpr auto + sort_key() const -> std::underlying_type_t { + return index() * 32u + stdx::to_underlying(lsb_); + } +}; + template <> struct at { msb_t msb_{}; lsb_t lsb_{}; diff --git a/test/msg/field_extract.cpp b/test/msg/field_extract.cpp index 8baadcfc..eedcce7f 100644 --- a/test/msg/field_extract.cpp +++ b/test/msg/field_extract.cpp @@ -61,12 +61,34 @@ TEST_CASE("across multiple storage elements", "[field extract]") { CHECK(0b11'1010'1010'1010'11u == F::extract(data)); } +TEST_CASE("with byte index", "[field extract]") { + using F = field<"", std::uint32_t>::located< + at{0_bi, 7_msb, 2_lsb}, at{1_bi, 7_msb, 0_lsb}, at{2_bi, 1_msb, 0_lsb}>; + std::array data{ + 0b1010'1110u, + 0b1010'1010u, + 0b0000'0111u, + }; + CHECK(0b1010'11'1010'1010'11u == F::extract(data)); +} + +TEST_CASE("with byte index, at order", "[field extract]") { + using F = field<"", std::uint32_t>::located< + at{2_bi, 1_msb, 0_lsb}, at{1_bi, 7_msb, 0_lsb}, at{0_bi, 7_msb, 2_lsb}>; + std::array data{ + 0b1010'1110u, + 0b1010'1010u, + 0b0000'0111u, + }; + CHECK(0b11'1010'1010'1010'11u == F::extract(data)); +} + TEST_CASE("without dword index", "[field extract]") { using F = field<"", std::uint32_t>::located; std::array data{ 0b1010'1110u, 0b1010'1010u, - 0b111u, + 0b0000'0111u, }; CHECK(0b11'1010'1010'1010'11u == F::extract(data)); } diff --git a/test/msg/field_insert.cpp b/test/msg/field_insert.cpp index 5610fcc4..26291662 100644 --- a/test/msg/field_insert.cpp +++ b/test/msg/field_insert.cpp @@ -70,6 +70,34 @@ TEST_CASE("across multiple storage elements", "[field insert]") { CHECK(0b111u == data[2]); } +TEST_CASE("with byte index", "[field insert]") { + using F = field<"", std::uint32_t>::located< + at{0_bi, 7_msb, 2_lsb}, at{1_bi, 7_msb, 0_lsb}, at{2_bi, 1_msb, 0_lsb}>; + std::array data{ + 0b0000'0010u, + 0b0000'0000u, + 0b0000'0100u, + }; + F::insert(data, 0b11'1010'1010'1010'11u); + CHECK(0b1110'1010u == data[0]); + CHECK(0b1010'1010u == data[1]); + CHECK(0b0000'0111u == data[2]); +} + +TEST_CASE("with byte index, at order", "[field insert]") { + using F = field<"", std::uint32_t>::located< + at{2_bi, 1_msb, 0_lsb}, at{1_bi, 7_msb, 0_lsb}, at{0_bi, 7_msb, 2_lsb}>; + std::array data{ + 0b0000'0010u, + 0b0000'0000u, + 0b0000'0100u, + }; + F::insert(data, 0b11'1010'1010'1010'11u); + CHECK(0b1010'1110u == data[0]); + CHECK(0b1010'1010u == data[1]); + CHECK(0b0000'0111u == data[2]); +} + TEST_CASE("without dword index", "[field insert]") { using F = field<"", std::uint32_t>::located; std::array data{