@@ -64,15 +64,6 @@ template <typename T, typename Spec>
6464concept field_locator_for =
6565 field_extractor_for<T, Spec> and field_inserter_for<T, Spec>;
6666
67- template <typename T>
68- concept field_location = requires (T const &t) {
69- { t.index () } -> std::same_as<std::uint32_t >;
70- { t.lsb () } -> std::same_as<std::uint32_t >;
71- { t.size () } -> std::same_as<std::uint32_t >;
72- { t.valid () } -> std::same_as<bool >;
73- { t.sort_key () } -> std::same_as<std::uint32_t >;
74- };
75-
7667namespace detail {
7768template <typename Name, typename T, std::uint32_t BitSize>
7869struct field_spec_t {
@@ -305,62 +296,33 @@ CONSTEVAL auto operator""_msb(unsigned long long int v) -> msb_t {
305296}
306297} // namespace literals
307298
308- template <typename ...> struct at ;
309-
310- template <> struct at <dword_index_t , msb_t , lsb_t > {
311- dword_index_t index_{};
312- msb_t msb_{};
313- lsb_t lsb_{};
299+ struct bit_unit {};
314300
315- [[nodiscard]] constexpr auto
316- index () const -> std::underlying_type_t <dword_index_t > {
317- return stdx::to_underlying (index_);
318- }
319- [[nodiscard]] constexpr auto lsb () const -> std::underlying_type_t<lsb_t> {
320- return stdx::to_underlying (lsb_);
321- }
322- [[nodiscard]] constexpr auto size () const -> std::underlying_type_t<lsb_t> {
323- return stdx::to_underlying (msb_) - lsb () + 1 ;
324- }
325- [[nodiscard]] constexpr auto valid () const -> bool {
326- return size () <= 64 and
327- stdx::to_underlying (msb_) >= stdx::to_underlying (lsb_);
328- }
329- [[nodiscard]] constexpr auto
330- sort_key () const -> std::underlying_type_t <lsb_t > {
331- return index () * 32u + stdx::to_underlying (lsb_);
301+ template <typename Unit, typename T>
302+ constexpr auto unit_bit_size (T t) -> std::uint32_t {
303+ if constexpr (std::same_as<Unit, bit_unit>) {
304+ return static_cast <std::uint32_t >(t);
305+ } else {
306+ return static_cast <std::uint32_t >(t) * sizeof (Unit) * CHAR_BIT;
332307 }
333- };
308+ }
334309
335- template <> struct at <byte_index_t , msb_t , lsb_t > {
336- byte_index_t index_{};
310+ struct at {
337311 msb_t msb_{};
338312 lsb_t lsb_{};
339313
340- [[nodiscard]] constexpr auto
341- index () const -> std::underlying_type_t <byte_index_t > {
342- return stdx::to_underlying (index_) / 4 ;
343- }
344- [[nodiscard]] constexpr auto lsb () const -> std::underlying_type_t<lsb_t> {
345- return (stdx::to_underlying (index_) * 8 ) % 32 +
346- stdx::to_underlying (lsb_);
347- }
348- [[nodiscard]] constexpr auto size () const -> std::underlying_type_t<lsb_t> {
349- return stdx::to_underlying (msb_) - stdx::to_underlying (lsb_) + 1 ;
350- }
351- [[nodiscard]] constexpr auto valid () const -> bool {
352- return size () <= 8 and
353- stdx::to_underlying (msb_) >= stdx::to_underlying (lsb_);
354- }
355- [[nodiscard]] constexpr auto
356- sort_key () const -> std::underlying_type_t <lsb_t > {
357- return index () * 32u + stdx::to_underlying (lsb_);
358- }
359- };
360-
361- template <> struct at <msb_t , lsb_t > {
362- msb_t msb_{};
363- lsb_t lsb_{};
314+ constexpr at () = default;
315+ constexpr at (msb_t m, lsb_t l) : msb_{m}, lsb_{l} {}
316+ constexpr at (dword_index_t di, msb_t m, lsb_t l)
317+ : msb_{unit_bit_size<std::uint32_t >(stdx::to_underlying (di)) +
318+ stdx::to_underlying (m)},
319+ lsb_{unit_bit_size<std::uint32_t >(stdx::to_underlying (di)) +
320+ stdx::to_underlying (l)} {}
321+ constexpr at (byte_index_t bi, msb_t m, lsb_t l)
322+ : msb_{unit_bit_size<std::uint8_t >(stdx::to_underlying (bi)) +
323+ stdx::to_underlying (m)},
324+ lsb_{unit_bit_size<std::uint8_t >(stdx::to_underlying (bi)) +
325+ stdx::to_underlying (l)} {}
364326
365327 [[nodiscard]] constexpr auto
366328 index () const -> std::underlying_type_t <lsb_t > {
@@ -380,13 +342,14 @@ template <> struct at<msb_t, lsb_t> {
380342 sort_key () const -> std::underlying_type_t <lsb_t > {
381343 return stdx::to_underlying (lsb_);
382344 }
345+ [[nodiscard]] constexpr auto shifted_by (auto n) const -> at {
346+ return {msb_t {stdx::to_underlying (msb_) + n},
347+ lsb_t {stdx::to_underlying (lsb_) + n}};
348+ }
383349};
384350
385- template <typename ... Ts> at (Ts...) -> at<Ts...>;
386-
387351namespace detail {
388- template <auto ... Ats>
389- requires (... and field_location<decltype (Ats)>)
352+ template <at... Ats>
390353using locator_for =
391354 field_locator_t <bits_locator_t <Ats.index(), Ats.size(), Ats.lsb()>...>;
392355
@@ -428,9 +391,8 @@ struct field_id_t {};
428391
429392template <typename Name, typename T = std::uint32_t ,
430393 typename Default = detail::with_default<T>,
431- match::matcher M = match::always_t , auto ... Ats>
432- requires std::is_trivially_copyable_v<T> and
433- (... and field_location<decltype (Ats)>)
394+ match::matcher M = match::always_t , at... Ats>
395+ requires std::is_trivially_copyable_v<T>
434396class field_t : public field_spec_t <Name, T, detail::field_size<Ats...>>,
435397 public detail::locator_for<Ats...>,
436398 public Default {
@@ -543,6 +505,12 @@ class field_t : public field_spec_t<Name, T, detail::field_size<Ats...>>,
543505 using with_required = field_t <Name, T, detail::with_const_default<T, V>,
544506 msg::equal_to_t <field_t , V>, Ats...>;
545507
508+ // ======================================================================
509+ // shift a field
510+ template <auto N, typename Unit = bit_unit>
511+ using shifted_by =
512+ field_t <Name, T, Default, M, Ats.shifted_by(unit_bit_size<Unit>(N))...>;
513+
546514 // ======================================================================
547515 // legacy aliases
548516 template <typename X> using WithMatch = with_matcher<X>;
@@ -560,8 +528,7 @@ template <stdx::ct_string Name, typename T = std::uint32_t,
560528 typename Default = detail::with_default<T>,
561529 match::matcher M = match::always_t >
562530struct field {
563- template <auto ... Ats>
564- requires (... and field_location<decltype (Ats)>)
531+ template <at... Ats>
565532 using located = detail::field_t <
566533 decltype (stdx::ct_string_to_type<Name, sc::string_constant>()), T,
567534 Default, M, Ats...>;
0 commit comments