@@ -64,15 +64,6 @@ template <typename T, typename Spec>
64
64
concept field_locator_for =
65
65
field_extractor_for<T, Spec> and field_inserter_for<T, Spec>;
66
66
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
-
76
67
namespace detail {
77
68
template <typename Name, typename T, std::uint32_t BitSize>
78
69
struct field_spec_t {
@@ -305,62 +296,33 @@ CONSTEVAL auto operator""_msb(unsigned long long int v) -> msb_t {
305
296
}
306
297
} // namespace literals
307
298
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 {};
314
300
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;
332
307
}
333
- };
308
+ }
334
309
335
- template <> struct at <byte_index_t , msb_t , lsb_t > {
336
- byte_index_t index_{};
310
+ struct at {
337
311
msb_t msb_{};
338
312
lsb_t lsb_{};
339
313
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)} {}
364
326
365
327
[[nodiscard]] constexpr auto
366
328
index () const -> std::underlying_type_t <lsb_t > {
@@ -380,13 +342,14 @@ template <> struct at<msb_t, lsb_t> {
380
342
sort_key () const -> std::underlying_type_t <lsb_t > {
381
343
return stdx::to_underlying (lsb_);
382
344
}
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
+ }
383
349
};
384
350
385
- template <typename ... Ts> at (Ts...) -> at<Ts...>;
386
-
387
351
namespace detail {
388
- template <auto ... Ats>
389
- requires (... and field_location<decltype (Ats)>)
352
+ template <at... Ats>
390
353
using locator_for =
391
354
field_locator_t <bits_locator_t <Ats.index(), Ats.size(), Ats.lsb()>...>;
392
355
@@ -428,9 +391,8 @@ struct field_id_t {};
428
391
429
392
template <typename Name, typename T = std::uint32_t ,
430
393
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>
434
396
class field_t : public field_spec_t <Name, T, detail::field_size<Ats...>>,
435
397
public detail::locator_for<Ats...>,
436
398
public Default {
@@ -543,6 +505,12 @@ class field_t : public field_spec_t<Name, T, detail::field_size<Ats...>>,
543
505
using with_required = field_t <Name, T, detail::with_const_default<T, V>,
544
506
msg::equal_to_t <field_t , V>, Ats...>;
545
507
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
+
546
514
// ======================================================================
547
515
// legacy aliases
548
516
template <typename X> using WithMatch = with_matcher<X>;
@@ -560,8 +528,7 @@ template <stdx::ct_string Name, typename T = std::uint32_t,
560
528
typename Default = detail::with_default<T>,
561
529
match::matcher M = match::always_t >
562
530
struct field {
563
- template <auto ... Ats>
564
- requires (... and field_location<decltype (Ats)>)
531
+ template <at... Ats>
565
532
using located = detail::field_t <
566
533
decltype (stdx::ct_string_to_type<Name, sc::string_constant>()), T,
567
534
Default, M, Ats...>;
0 commit comments