Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 38 additions & 5 deletions include/msg/field.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ struct field_spec_t {
constexpr static auto size = BitSize;
};

template <std::uint32_t DWordIndex, std::uint32_t BitSize, std::uint32_t Lsb>
template <std::uint32_t Index, std::uint32_t BitSize, std::uint32_t Lsb>
struct bits_locator_t {
constexpr static auto size = BitSize;

Expand Down Expand Up @@ -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<elem_t>();
constexpr auto max_idx = BaseIndex + Msb / elem_size;
Expand Down Expand Up @@ -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<elem_t>();
[[maybe_unused]] constexpr auto min_idx = BaseIndex + Lsb / elem_size;
Expand Down Expand Up @@ -209,13 +209,13 @@ struct bits_locator_t {
template <std::uint32_t NumBits>
constexpr static auto fits_inside() -> bool {
constexpr auto Msb = Lsb + BitSize - 1;
return DWordIndex * 32 + Msb <= NumBits;
return Index * 32 + Msb <= NumBits;
}

template <typename T> 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);
}
Expand Down Expand Up @@ -277,12 +277,19 @@ template <bits_locator... BLs> 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<byte_index_t>(v);
}
CONSTEVAL auto operator""_dwi(unsigned long long int v) -> dword_index_t {
return static_cast<dword_index_t>(v);
}
CONSTEVAL auto operator""_dw(unsigned long long int v) -> dword_index_t {
return static_cast<dword_index_t>(v);
}
Expand Down Expand Up @@ -323,6 +330,32 @@ template <> struct at<dword_index_t, msb_t, lsb_t> {
}
};

template <> struct at<byte_index_t, msb_t, lsb_t> {
byte_index_t index_{};
msb_t msb_{};
lsb_t lsb_{};

[[nodiscard]] constexpr auto
index() const -> std::underlying_type_t<byte_index_t> {
return stdx::to_underlying(index_) / 4;
}
[[nodiscard]] constexpr auto lsb() const -> std::underlying_type_t<lsb_t> {
return (stdx::to_underlying(index_) * 8) % 32 +
stdx::to_underlying(lsb_);
}
[[nodiscard]] constexpr auto size() const -> std::underlying_type_t<lsb_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<lsb_t> {
return index() * 32u + stdx::to_underlying(lsb_);
}
};

template <> struct at<msb_t, lsb_t> {
msb_t msb_{};
lsb_t lsb_{};
Expand Down
24 changes: 23 additions & 1 deletion test/msg/field_extract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::uint8_t, 3> 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<std::uint8_t, 3> 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<at{17_msb, 2_lsb}>;
std::array<std::uint8_t, 3> data{
0b1010'1110u,
0b1010'1010u,
0b111u,
0b0000'0111u,
};
CHECK(0b11'1010'1010'1010'11u == F::extract(data));
}
Expand Down
28 changes: 28 additions & 0 deletions test/msg/field_insert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::uint8_t, 3> 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<std::uint8_t, 3> 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<at{17_msb, 2_lsb}>;
std::array<std::uint8_t, 3> data{
Expand Down