Skip to content

Commit 0d45131

Browse files
committed
enable byte indexing for msg::located at
1 parent 924cab6 commit 0d45131

File tree

3 files changed

+101
-7
lines changed

3 files changed

+101
-7
lines changed

include/msg/field.hpp

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ concept field_locator_for =
6666

6767
template <typename T>
6868
concept field_location = requires(T const &t) {
69+
{ t.indexed_bit_size() } -> std::same_as<std::uint32_t>;
6970
{ t.index() } -> std::same_as<std::uint32_t>;
7071
{ t.lsb() } -> std::same_as<std::uint32_t>;
7172
{ t.size() } -> std::same_as<std::uint32_t>;
@@ -83,9 +84,10 @@ struct field_spec_t {
8384
constexpr static auto size = BitSize;
8485
};
8586

86-
template <std::uint32_t DWordIndex, std::uint32_t BitSize, std::uint32_t Lsb>
87+
template <std::uint32_t Index, std::uint32_t IndexedBitSize, std::uint32_t BitSize, std::uint32_t Lsb>
8788
struct bits_locator_t {
8889
constexpr static auto size = BitSize;
90+
constexpr static auto indexed_byte_size = std::size_t{IndexedBitSize/8};
8991

9092
template <std::unsigned_integral T>
9193
[[nodiscard]] constexpr static auto fold(T value) -> T {
@@ -112,7 +114,7 @@ struct bits_locator_t {
112114
constexpr auto Msb = Lsb + BitSize - 1u;
113115

114116
constexpr auto BaseIndex =
115-
DWordIndex * sizeof(std::uint32_t) / sizeof(elem_t);
117+
Index * indexed_byte_size / sizeof(elem_t);
116118

117119
constexpr auto elem_size = stdx::bit_size<elem_t>();
118120
constexpr auto max_idx = BaseIndex + Msb / elem_size;
@@ -158,7 +160,7 @@ struct bits_locator_t {
158160
constexpr auto Msb = Lsb + BitSize - 1u;
159161

160162
constexpr auto BaseIndex =
161-
DWordIndex * sizeof(std::uint32_t) / sizeof(elem_t);
163+
Index * indexed_byte_size / sizeof(elem_t);
162164

163165
constexpr auto elem_size = stdx::bit_size<elem_t>();
164166
[[maybe_unused]] constexpr auto min_idx = BaseIndex + Lsb / elem_size;
@@ -209,13 +211,13 @@ struct bits_locator_t {
209211
template <std::uint32_t NumBits>
210212
constexpr static auto fits_inside() -> bool {
211213
constexpr auto Msb = Lsb + BitSize - 1;
212-
return DWordIndex * 32 + Msb <= NumBits;
214+
return Index * IndexedBitSize + Msb <= NumBits;
213215
}
214216

215217
template <typename T> constexpr static auto extent_in() -> std::size_t {
216218
constexpr auto msb = Lsb + BitSize - 1;
217219
constexpr auto msb_extent = (msb + CHAR_BIT - 1) / CHAR_BIT;
218-
constexpr auto base_extent = DWordIndex * sizeof(std::uint32_t);
220+
constexpr auto base_extent = Index * indexed_byte_size;
219221
constexpr auto extent = base_extent + msb_extent;
220222
return (extent + sizeof(T) - 1) / sizeof(T);
221223
}
@@ -277,12 +279,16 @@ template <bits_locator... BLs> struct field_locator_t {
277279
};
278280
} // namespace detail
279281

282+
enum struct byte_index_t : std::uint32_t {};
280283
enum struct dword_index_t : std::uint32_t {};
281284
enum struct msb_t : std::uint32_t {};
282285
enum struct lsb_t : std::uint32_t {};
283286

284287
inline namespace literals {
285288
// NOLINTNEXTLINE(google-runtime-int)
289+
CONSTEVAL auto operator""_bi(unsigned long long int v) -> byte_index_t {
290+
return static_cast<byte_index_t>(v);
291+
}
286292
CONSTEVAL auto operator""_dw(unsigned long long int v) -> dword_index_t {
287293
return static_cast<dword_index_t>(v);
288294
}
@@ -307,6 +313,9 @@ template <> struct at<dword_index_t, msb_t, lsb_t> {
307313
index() const -> std::underlying_type_t<dword_index_t> {
308314
return stdx::to_underlying(index_);
309315
}
316+
[[nodiscard]] constexpr auto indexed_bit_size() const -> std::uint32_t {
317+
return 32;
318+
}
310319
[[nodiscard]] constexpr auto lsb() const -> std::underlying_type_t<lsb_t> {
311320
return stdx::to_underlying(lsb_);
312321
}
@@ -323,6 +332,34 @@ template <> struct at<dword_index_t, msb_t, lsb_t> {
323332
}
324333
};
325334

335+
template <> struct at<byte_index_t, msb_t, lsb_t> {
336+
byte_index_t index_{};
337+
msb_t msb_{};
338+
lsb_t lsb_{};
339+
340+
[[nodiscard]] constexpr auto
341+
index() const -> std::underlying_type_t<byte_index_t> {
342+
return stdx::to_underlying(index_);
343+
}
344+
[[nodiscard]] constexpr auto indexed_bit_size() const -> std::uint32_t {
345+
return 8;
346+
}
347+
[[nodiscard]] constexpr auto lsb() const -> std::underlying_type_t<lsb_t> {
348+
return stdx::to_underlying(lsb_);
349+
}
350+
[[nodiscard]] constexpr auto size() const -> std::underlying_type_t<lsb_t> {
351+
return stdx::to_underlying(msb_) - lsb() + 1;
352+
}
353+
[[nodiscard]] constexpr auto valid() const -> bool {
354+
return size() <= 64 and
355+
stdx::to_underlying(msb_) >= stdx::to_underlying(lsb_);
356+
}
357+
[[nodiscard]] constexpr auto
358+
sort_key() const -> std::underlying_type_t<lsb_t> {
359+
return index() * 8u + stdx::to_underlying(lsb_);
360+
}
361+
};
362+
326363
template <> struct at<msb_t, lsb_t> {
327364
msb_t msb_{};
328365
lsb_t lsb_{};
@@ -331,6 +368,9 @@ template <> struct at<msb_t, lsb_t> {
331368
index() const -> std::underlying_type_t<lsb_t> {
332369
return stdx::to_underlying(lsb_) / 32u;
333370
}
371+
[[nodiscard]] constexpr auto indexed_bit_size() const -> std::uint32_t {
372+
return 32;
373+
}
334374
[[nodiscard]] constexpr auto lsb() const -> std::underlying_type_t<lsb_t> {
335375
return stdx::to_underlying(lsb_) % 32u;
336376
}
@@ -353,7 +393,7 @@ namespace detail {
353393
template <auto... Ats>
354394
requires(... and field_location<decltype(Ats)>)
355395
using locator_for =
356-
field_locator_t<bits_locator_t<Ats.index(), Ats.size(), Ats.lsb()>...>;
396+
field_locator_t<bits_locator_t<Ats.index(), Ats.indexed_bit_size(), Ats.size(), Ats.lsb()>...>;
357397

358398
template <at... Ats> constexpr inline auto field_size = (0u + ... + Ats.size());
359399

test/msg/field_extract.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,36 @@ TEST_CASE("across multiple storage elements", "[field extract]") {
6161
CHECK(0b11'1010'1010'1010'11u == F::extract(data));
6262
}
6363

64+
TEST_CASE("with byte index", "[field extract]") {
65+
using F = field<"", std::uint32_t>::located<at{0_bi, 7_msb, 2_lsb},
66+
at{1_bi, 7_msb, 0_lsb},
67+
at{2_bi, 1_msb, 0_lsb}>;
68+
std::array<std::uint8_t, 3> data{
69+
0b1010'1110u,
70+
0b1010'1010u,
71+
0b0000'0111u,
72+
};
73+
CHECK(0b1010'11'1010'1010'11u == F::extract(data));
74+
}
75+
76+
TEST_CASE("with byte index, at order", "[field extract]") {
77+
using F = field<"", std::uint32_t>::located<at{2_bi, 1_msb, 0_lsb},
78+
at{1_bi, 7_msb, 0_lsb},
79+
at{0_bi, 7_msb, 2_lsb}>;
80+
std::array<std::uint8_t, 3> data{
81+
0b1010'1110u,
82+
0b1010'1010u,
83+
0b0000'0111u,
84+
};
85+
CHECK(0b11'1010'1010'1010'11u == F::extract(data));
86+
}
87+
6488
TEST_CASE("without dword index", "[field extract]") {
6589
using F = field<"", std::uint32_t>::located<at{17_msb, 2_lsb}>;
6690
std::array<std::uint8_t, 3> data{
6791
0b1010'1110u,
6892
0b1010'1010u,
69-
0b111u,
93+
0b0000'0111u,
7094
};
7195
CHECK(0b11'1010'1010'1010'11u == F::extract(data));
7296
}

test/msg/field_insert.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,36 @@ TEST_CASE("across multiple storage elements", "[field insert]") {
7070
CHECK(0b111u == data[2]);
7171
}
7272

73+
TEST_CASE("with byte index", "[field insert]") {
74+
using F = field<"", std::uint32_t>::located<at{0_bi, 7_msb, 2_lsb},
75+
at{1_bi, 7_msb, 0_lsb},
76+
at{2_bi, 1_msb, 0_lsb}>;
77+
std::array<std::uint8_t, 3> data{
78+
0b0000'0010u,
79+
0b0000'0000u,
80+
0b0000'0100u,
81+
};
82+
F::insert(data, 0b11'1010'1010'1010'11u);
83+
CHECK(0b1110'1010u == data[0]);
84+
CHECK(0b1010'1010u == data[1]);
85+
CHECK(0b0000'0111u == data[2]);
86+
}
87+
88+
TEST_CASE("with byte index, at order", "[field insert]") {
89+
using F = field<"", std::uint32_t>::located<at{2_bi, 1_msb, 0_lsb},
90+
at{1_bi, 7_msb, 0_lsb},
91+
at{0_bi, 7_msb, 2_lsb}>;
92+
std::array<std::uint8_t, 3> data{
93+
0b0000'0010u,
94+
0b0000'0000u,
95+
0b0000'0100u,
96+
};
97+
F::insert(data, 0b11'1010'1010'1010'11u);
98+
CHECK(0b1010'1110u == data[0]);
99+
CHECK(0b1010'1010u == data[1]);
100+
CHECK(0b0000'0111u == data[2]);
101+
}
102+
73103
TEST_CASE("without dword index", "[field insert]") {
74104
using F = field<"", std::uint32_t>::located<at{17_msb, 2_lsb}>;
75105
std::array<std::uint8_t, 3> data{

0 commit comments

Comments
 (0)