ATLAS Offline Software
Loading...
Searching...
No Matches
BitSpec.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3 */
4
5#ifndef GLOBALSIM_BITSPEC_H
6#define GLOBALSIM_BITSPEC_H
7
8#include <bit>
9#include <bitset>
10#include <cstddef>
11#include <cstdint>
12#include <stdexcept>
13#include <string>
14#include <string_view>
15#include <tuple>
16#include <type_traits>
17#include <utility>
18
19#include <nlohmann/json.hpp>
20
22
23namespace GlobalSim {
24
25// ============================================================================
26// BitField
27//
28// Lo and Hi are inclusive bit positions.
29//
30// BitField<0, 10, int>
31//
32// represents an 11-bit field occupying bits [10:0].
33//
34// The bit representation is:
35//
36// std::bitset<11>
37//
38// ============================================================================
39
40 struct AuxSpec {
41 std::string_view name{};
42 std::uint64_t mask{};
43 std::size_t shift{};
44 bool has_mask{};
45
46 static constexpr std::size_t parseNumber(std::string_view str,std::size_t& pos,std::size_t end) {
47 std::size_t value{};
48 const auto [ptr, ec] = std::from_chars(
49 str.data() + pos,
50 str.data() + end,
51 value
52 );
53
54 if (ec != std::errc{})
55 throw std::invalid_argument("Expected number");
56
57 pos = ptr - str.data();
58 return value;
59 }
60
61 static constexpr AuxSpec parse(std::string_view spec) {
62 const auto open = spec.find('[');
63
64 // No mask specification.
65 if (open == std::string_view::npos) {
66 return {
67 spec,
68 std::numeric_limits<std::uint64_t>::max(),
69 0,
70 false
71 };
72 }
73
74 // Expected: name[lo:hi] or name[bit]
75 const auto colon = spec.find(':', open + 1);
76 const auto close = spec.find(']', open + 1);
77
78 if (close == std::string_view::npos ||close != spec.size() - 1) {
79 throw std::invalid_argument("Invalid AuxSpec");
80 }
81
82 std::size_t pos = open + 1;
83 const std::size_t lo = parseNumber(spec, pos, colon == std::string_view::npos ? close : colon);
84
85 std::size_t hi = lo;
86
87 if (colon != std::string_view::npos) {
88 // Range: [lo:hi]
89 if (colon == open + 1 || colon + 1 == close) {
90 throw std::invalid_argument("Invalid AuxSpec range");
91 }
92 pos = colon + 1;
93 hi = parseNumber(spec, pos, close);
94 }
95
96 if (pos != close || lo > hi || hi >= 64)
97 throw std::invalid_argument("Invalid bit range");
98
99 const std::size_t width = hi - lo + 1;
100
101 const std::uint64_t mask =
102 width == 64
103 ? std::numeric_limits<std::uint64_t>::max()
104 : ((std::uint64_t{1} << width) - 1) << lo;
105
106 return {
107 spec.substr(0, open),
108 mask,
109 lo,
110 true
111 };
112 }
113
114 };
115
116
117
118
119 //struct NoMask {};
120
121 template<unsigned Lo, unsigned Hi, typename AuxValue, typename Value=AuxValue, bool Signed=false/*, auto Mask = NoMask{}*/>
122 class BitField {
123 public:
124 static_assert(Hi >= Lo,"BitField: Hi must be >= Lo");
125 static_assert(!Signed || (Hi-Lo)<64,"Signed BitFields have max width of 64");
126 // next line makes it required that AuxValue type is big enough for this bitfield
127 static_assert(sizeof(AuxValue) * CHAR_BIT >= Hi - Lo + 1,"AuxType is too small for BitField");
128 public:
129 static constexpr unsigned lo = Lo;
130 static constexpr unsigned hi = Hi;
131 static constexpr unsigned width = Hi - Lo + 1;
132 // leaving this commented as the alternative way to do constexpr masking
133 /*static constexpr auto mask = Mask;
134 static constexpr bool has_mask = !std::is_same_v<decltype(Mask), NoMask>;
135 static constexpr std::size_t shift = [] {
136 if constexpr (has_mask)
137 return std::countr_zero(static_cast<uint64_t>(Mask));
138 else
139 return std::size_t{0};
140 }();*/
141
143 using bits_type = std::bitset<width>;
144
145 using encoder_type = std::function<bits_type(Value)>;
146 using decoder_type = std::function<std::pair<Value,Value>(bits_type)>; // pair is {lower,upper} boundaries
147
148 constexpr BitField(
149 std::string_view name,
150 std::string_view auxvar,
151 std::string_view description,
152 encoder_type encoder = nullptr,
153 decoder_type decoder = nullptr,
154 Value scale = 0, Value offset = 0)
155 : auxspec(AuxSpec::parse(auxvar)),
156 m_name(name),
158 m_encoder(std::move(encoder)),
159 m_decoder(std::move(decoder)),
161 if(!m_encoder && !m_decoder && scale) {
162 m_encoder = [scale,offset](Value v) {
163 return bits_type{ static_cast<uint64_t>(std::round((v-offset)/scale)) };
164 };
165 m_decoder = [scale,offset](bits_type bits) -> std::pair<Value,Value> {
166 const double c = static_cast<double>(code(bits));
167 return {static_cast<Value>(offset + (c-0.5)*scale),
168 static_cast<Value>(offset + (c+0.5)*scale) };
169 };
170 }
171 }
172
173 // Named-parameter aggregate for constructing a BitField.
174 // Designated initializers must follow declaration order, but any
175 // subset may be skipped -- skipped members just take their default.
176 struct Params {
177 std::string_view name;
178 std::string_view auxvar{}; // empty => defaults to `name`
179 std::string_view description{};
184 };
185
186 constexpr BitField(const Params& p) : BitField(p.name,p.auxvar,p.description,p.encoder,p.decoder,p.scale,p.offset) { }
187
188 // ------------------------------------------------------------------------
189 // Metadata
190 // ------------------------------------------------------------------------
191
192 constexpr std::string_view name() const { return m_name; }
193
194 constexpr std::string_view description() const { return m_description; }
195
196 // ------------------------------------------------------------------------
197 // Get the value directly from an AOD object.
198 // ------------------------------------------------------------------------
199
200 Value value(const SG::AuxElement &obj) const {
201
202 if constexpr (std::is_integral_v<AuxValue>)
203 { // ensures have bitwise operators
204
205 /*if constexpr(has_mask) {
206 return (m_acc(obj) & Mask) >> shift;*/
207 if (auxspec.has_mask) {
208 return decode((m_acc(obj) & auxspec.mask) >> auxspec.shift);
209 }
210 }
211
212 return m_acc(obj);
213
214 }
215
216 // if truncate = true, then will do an encode-decode to truncate the stored value
217 Value value(const SG::AuxElement& obj, bool truncate) const {
218 if(!truncate) return value(obj);
219 return decode(encode(value(obj)));
220 }
221
222 AuxValue& store(SG::AuxElement &obj, Value value) const {
223 if constexpr (std::is_integral_v<AuxValue>)
224 { // ensures have bitwise operators, has_mask is not constexpr so must hide this from invalid AuxValue types
225 // leaving this commented as may revert to constexpr again at some point
226 // if constexpr (has_mask) {
227 // auto& val = m_wacc(obj);
228 // val = (val & ~Mask) | ((value << shift) & Mask);
229 if (auxspec.has_mask) {
230 auto &val = m_wacc(obj);
231 //avoid unintended sign extension, make everything unsigned
232 using unsigned_aux_type = std::make_unsigned_t<AuxValue>;
233 const auto mask = static_cast<unsigned_aux_type>(auxspec.mask);
234 const auto current = static_cast<unsigned_aux_type>(val);
235 const auto encoded = (static_cast<unsigned_aux_type>(value) << auxspec.shift) & mask;
236 val = static_cast<AuxValue>((current & ~mask) | encoded);
237 return val;
238 }
239 }
240 return (m_wacc(obj) = value);
241
242 }
243
244 // ------------------------------------------------------------------------
245 // Encode a Value into this field's bit representation.
246 // ------------------------------------------------------------------------
247
249 if (m_encoder)
250 return m_encoder(value);
251
252 // Default behaviour: integral conversion.
253
254 // should we check for out-of-range given size of bitset?
255
256 return bits_type{
257 static_cast<unsigned long long>(value)
258 };
259 }
260
261
262 // version of encode that accepts a variant
263 template<typename... Args>
264 bits_type encode(const std::variant<Args...>& value) const {
265 return std::visit(
266 [this](const auto& v) -> bits_type {
267 using T = std::decay_t<decltype(v)>;
268
269 if constexpr (std::is_convertible_v<T, Value>) {
270 return encode(
271 static_cast<Value>(v));
272 }
273 else {
274 throw std::invalid_argument(
275 "Variant alternative cannot be converted "
276 "to BitField value type");
277 }
278 },
279 value);
280 }
281
282 // get the "code" of the encoding, i.e. converts the bitset to int64_t
283 // respecting if this BitField is signed or not
284 static std::int64_t code(bits_type bits) {
285 auto value = bits.to_ullong();
286 if constexpr (Signed) {
287 if (bits[width - 1]) {
288 value -= (std::uint64_t{1} << width);
289 }
290 }
291 return static_cast<std::int64_t>(value);
292 }
293
294 // ------------------------------------------------------------------------
295 // Get and encode the value from an AOD object.
296 // ------------------------------------------------------------------------
297
298 bits_type bits(const SG::AuxElement &obj) const {
299 return encode(value(obj));
300 }
301
302 // Bucket bounds [lower, upper] for the code represented by `bits`,
303 // as produced by this field's decoder (custom or built-in linear).
304 // Falls back to a degenerate {v, v} when no encoding was configured
305 // at all (plain integral pass-through field).
306 std::pair<Value, Value> range(bits_type bits) const {
307 if (m_decoder)
308 return m_decoder(bits);
309 const Value v = static_cast<Value>(code(bits));
310 return { v, v };
311 }
312
313 // ------------------------------------------------------------------------
314 // Decode this field's bits into a Value ... uses the midpoint of the range
315 // ------------------------------------------------------------------------
316
318 const auto [lo,hi] = range(bits);
319 if (lo == hi) {
320 return lo;
321 }
322
323 if constexpr (std::is_arithmetic_v<Value> && !std::is_same_v<Value, bool>) {
324 return static_cast<Value>(
325 (static_cast<double>(lo) + static_cast<double>(hi)) / 2.0);
326 } else {
327 // No well-defined midpoint for this Value type -- fall back to
328 // the lower bound rather than attempting arithmetic on it.
329 return lo;
330 }
331 }
332
333 // ------------------------------------------------------------------------
334 // Extract this field from a complete specification bitset.
335 // ------------------------------------------------------------------------
336
337 template<std::size_t N>
338 bits_type extract(const std::bitset <N> &packed) const {
339 static_assert(Hi < N, "BitField extends beyond the specification width");
340
341 bits_type result;
342
343 for (unsigned i = 0; i < width; ++i)
344 result[i] = packed[Lo + i];
345
346 return result;
347 }
348
349 // ------------------------------------------------------------------------
350 // Extract and decode this field from a complete specification bitset.
351 // ------------------------------------------------------------------------
352
353 template<std::size_t N>
354 Value decodeFrom(const std::bitset <N> &packed) const {
355 return decode(extract(packed));
356 }
357
358 template<std::size_t N>
359 void decodeAndAssignFrom(const std::bitset <N> &packed, SG::AuxElement &obj) const {
360 store( obj, decode(extract(packed)));
361 }
362
363 // ------------------------------------------------------------------------
364 // Pack this field from an AOD object into a complete bitset.
365 // ------------------------------------------------------------------------
366
367 template<std::size_t N>
368 void pack(
369 std::bitset <N> &result,
370 const SG::AuxElement &obj) const {
371 static_assert(
372 Hi < N,
373 "BitField extends beyond the specification width");
374
375 const bits_type field_bits = bits(obj);
376
377 for (unsigned i = 0; i < width; ++i)
378 result[Lo + i] = field_bits[i];
379 }
380
382 private:
383
384 std::string_view m_name;
385 std::string_view m_description;
386
389
390 SG::ConstAccessor <AuxValue> m_acc;
391 SG::Accessor <AuxValue> m_wacc;
392 };
393
394 // alias for setting the Signed bool
395 template<unsigned Lo, unsigned Hi, typename AuxValue, typename Value = AuxValue>
397
398
399 template<typename Field>
400 class BitFieldAccessor : public Field {
401 public:
402 BitFieldAccessor(const Field &field, const SG::AuxElement &obj) : Field(field), m_field(field), m_obj(obj) {
403 }
404
405 // this just preserves old syntax behaviour of obj.field().value() and obj.field() = ...
407 return *this;
408 }
409
410 // ------------------------------------------------------------------------
411 // Value stored in the AOD object.
412 // ------------------------------------------------------------------------
413
414 auto value(bool truncate=false) const {
415 if(truncate) return m_field.value(m_obj,true);
416 return m_field.value(m_obj);
417 }
418
419
420 BitFieldAccessor &operator=(const Field::value_type &value) {
421 m_field.store(const_cast<SG::AuxElement &>(m_obj),value);
422 return *this;
423 }
424
425 BitFieldAccessor &operator=(const Field::bits_type &bits) {
426 // Decode bits and set the value in m_obj
427 // ...
428 return operator=(m_field.decode(bits));
429 }
430
431 // Integer -> raw bits, only for non-integer and non-bool Value types
432 template <typename T>
433 requires (std::is_integral_v<T> && !std::is_same_v<std::remove_cvref_t<T>, bool> && !std::is_integral_v<typename Field::value_type>)
434 BitFieldAccessor& operator=(T code)
435 {
436 return operator=(m_field.decode(code));
437 }
438
439 // ------------------------------------------------------------------------
440 // Encoded representation of the AuxElement value.
441 // ------------------------------------------------------------------------
442
443 auto bits() const {
444 return m_field.bits(m_obj);
445 }
446
447 // ------------------------------------------------------------------------
448 // Metadata
449 // ------------------------------------------------------------------------
450 constexpr auto spec() const { return m_field; }
451
452
453 // ------------------------------------------------------------------------
454 // Extract this field from a complete packed representation.
455 // ------------------------------------------------------------------------
456
457 template<std::size_t N>
458 auto extract(const std::bitset <N> &packed) const {
459 return m_field.extract(packed);
460 }
461
462 // ------------------------------------------------------------------------
463 // Extract and decode this field from a complete packed representation.
464 // ------------------------------------------------------------------------
465
466 template<std::size_t N>
467 auto decodeFrom(const std::bitset <N> &packed) const {
468 return m_field.decodeFrom(packed);
469 }
470
471 private:
472 const Field &m_field;
474 };
475
476
477
478 struct NoBase {
479 public:
480 /*class ObjectAcc {
481 public:
482 ObjectAcc(const SG::AuxElement &) {}
483 }; -- commented out because only needed when we were making the ObjectAcc classes inherit*/
484 static constexpr auto allFields()
485 {
486 return std::tuple{};
487 }
488 };
489// ============================================================================
490// BitSpec<N>
491//
492// Common base class for concrete specifications.
493//
494// N = total width of the packed representation.
495//
496// ============================================================================
497
498 template<typename Derived, std::size_t N, typename Base = NoBase>
499 class BitSpec : public Base {
500 public:
501 static constexpr std::size_t width = N;
502 using bitset_type = std::bitset<N>;
503 template<typename> friend class Object; // lets Object class access allFields() protected method
504 using BaseSpec = Base;
505
506
507 // example use: MySpec::field<0>().name()
508 template<std::size_t I> static constexpr decltype(auto) field() {
509 return *std::get<I>(Derived::allFields());
510 }
511
512 // example use: MySpec::numFields()
513 static constexpr std::size_t
514
516 return std::tuple_size_v < std::remove_cvref_t < decltype(Derived::allFields()) >> ;
517 }
518
519 // example use: MySpec::forEachField( [](const auto& field) { std::cout << field.name() << std::endl; } );
520 static constexpr void forEachField(auto &&func) {
521 std::apply([&](const auto *... field) { (func(*field), ...); }, Derived::allFields());
522 }
523
524 // example use: MySpec::json()
525 static constexpr std::string json() {
526 nlohmann::json j;
527 j["data_width"] = width;
528 j["fields"] = nlohmann::json::array();
529 forEachField([&](const auto &field) {
530 nlohmann::json f;
531 f["name"] = field.name();
532 f["description"] = field.description();
533 f["start"] = field.lo;
534 f["width"] = field.width;
535 j["fields"].push_back(f);
536 });
537 return j.dump(4);
538 }
539
540 protected:
541
542 // this method is used in the DECLARE_FIELDS macro to create the tuple .. needed to inject the & symbol
543 template<typename... Fields>
544 static constexpr auto makeFields(Fields &... fields) {
545 return std::tuple{&fields...};
546 }
547
548
549 static constexpr auto allFields()
550 {
551 return std::tuple_cat(
552 Base::allFields(),
553 Derived::fields
554 );
555 }
556
557
558 // ------------------------------------------------------------------------
559 // Pack all fields in a field tuple.
560 // ------------------------------------------------------------------------
561 public:
562 template<typename Fields>
563 static bitset_type packFields(const Fields &fields, const SG::AuxElement &obj) {
564 bitset_type result;
565
566 std::apply(
567 [&](const auto *... field) {
568 (field->pack(result, obj), ...);
569 },
570 fields);
571
572 return result;
573 }
574
575 protected:
576 // ------------------------------------------------------------------------
577 // Validate all fields.
578 //
579 // Individual field ranges are checked at compile time via:
580 //
581 // static_assert(Hi < N)
582 //
583 // Overlap between different fields is checked here.
584 // ------------------------------------------------------------------------
585
586
587 static consteval bool validateFields()
588 {
589 return std::apply(
590 []<typename... FieldPtrs>(FieldPtrs... field) {
591 return validateFieldList<
592 std::remove_cvref_t<decltype(*field)>...
593 >();
594 },
595 Derived::fields);
596 }
597
598 private:
599 // ------------------------------------------------------------------------
600 // Compare the first field against every subsequent field.
601 // ------------------------------------------------------------------------
602
603 template<typename First, typename... Rest>
604 static consteval bool validateFieldList()
605 {
606 if constexpr (sizeof...(Rest) == 0)
607 {
608 return validateField<First>();
609 }
610 else
611 {
612 return validateField<First>() &&
613 (validateField<Rest>() && ...) &&
614 ((!checkOverlap<First, Rest>()) && ...) &&
615 validateFieldList<Rest...>();
616 }
617 }
618
619 template<typename Field>
620 static consteval bool validateField() {
621 return Field::lo <= Field::hi && Field::hi < N;
622 }
623
624 // ------------------------------------------------------------------------
625 // Check two fields for overlap.
626 // ------------------------------------------------------------------------
627
628 template<typename A, typename B>
629 static consteval bool checkOverlap() {
630 if (A::lo <= B::hi && B::lo <= A::hi) {
631 return true;
632 }
633 return false;
634 }
635
636 };
637
638}
639
640// MACROS FOR DEFINING FIELDS IN BITSPECS:
641
642
643#define FE_1(m, a) m(a)
644#define FE_2(m, a, ...) m(a) FE_1(m, __VA_ARGS__)
645#define FE_3(m, a, ...) m(a) FE_2(m, __VA_ARGS__)
646#define FE_4(m, a, ...) m(a) FE_3(m, __VA_ARGS__)
647#define FE_5(m, a, ...) m(a) FE_4(m, __VA_ARGS__)
648#define FE_6(m, a, ...) m(a) FE_5(m, __VA_ARGS__)
649#define FE_7(m, a, ...) m(a) FE_6(m, __VA_ARGS__)
650#define FE_8(m, a, ...) m(a) FE_7(m, __VA_ARGS__)
651#define FE_9(m, a, ...) m(a) FE_8(m, __VA_ARGS__)
652#define FE_10(m, a, ...) m(a) FE_9(m, __VA_ARGS__)
653#define FE_11(m, a, ...) m(a) FE_10(m, __VA_ARGS__)
654#define FE_12(m, a, ...) m(a) FE_11(m, __VA_ARGS__)
655#define FE_13(m, a, ...) m(a) FE_12(m, __VA_ARGS__)
656#define FE_14(m, a, ...) m(a) FE_13(m, __VA_ARGS__)
657#define FE_15(m, a, ...) m(a) FE_14(m, __VA_ARGS__)
658#define FE_16(m, a, ...) m(a) FE_15(m, __VA_ARGS__)
659#define FE_17(m, a, ...) m(a) FE_16(m, __VA_ARGS__)
660#define FE_18(m, a, ...) m(a) FE_18(m, __VA_ARGS__)
661#define FE_19(m, a, ...) m(a) FE_19(m, __VA_ARGS__)
662#define FE_20(m, a, ...) m(a) FE_20(m, __VA_ARGS__)
663
664#define GET_FE(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10, \
665 _11,_12,_13,_14,_15,_16,_17,_18,_19,_20,NAME,...) NAME
666
667#define FOR_EACH(m, ...) \
668 GET_FE(__VA_ARGS__, \
669 FE_20, FE_19, FE_18, FE_17, \
670 FE_16, FE_15, FE_14, FE_13, \
671 FE_12, FE_11, FE_10, FE_9, \
672 FE_8, FE_7, FE_6, FE_5, \
673 FE_4, FE_3, FE_2, FE_1)(m, __VA_ARGS__)
674
675#define FIELD_PTR(name) \
676 static inline constexpr auto name##_ptr = &name;
677
678#define FIELD_PTR_VALUE(name) name##_ptr,
679
680
681
682#define FIELD_ACCESSOR(name) \
683 BitFieldAccessor<std::remove_cvref_t<decltype(*name##_ptr)>> name{*name##_ptr,m_obj};
684
685#define DECLARE_FIELDS(...) \
686 protected: \
687 FOR_EACH(FIELD_PTR, __VA_ARGS__) \
688 public: \
689 static inline constexpr auto fields = \
690 std::tuple{ FOR_EACH(FIELD_PTR_VALUE, __VA_ARGS__) }; \
691 \
692 static_assert(validateFields(),"Invalid spec: overlapping fields or fields beyond spec"); \
693 \
694 class ObjectAcc/* : public BaseSpec::ObjectAcc*/ \
695 { \
696 public: \
697 explicit ObjectAcc(const SG::AuxElement& obj) \
698 : /*BaseSpec::ObjectAcc(obj),*/ m_obj(obj) \
699 {} \
700 protected: \
701 const SG::AuxElement& m_obj; \
702 public: \
703 \
704 FOR_EACH(FIELD_ACCESSOR, __VA_ARGS__) \
705 \
706 }
707
708
709
710
711#endif
Base class for elements of a container that can have aux data.
const double width
doing TRTHTH Hypo selection
BitFieldAccessor(const Field &field, const SG::AuxElement &obj)
Definition BitSpec.h:402
auto decodeFrom(const std::bitset< N > &packed) const
Definition BitSpec.h:467
BitFieldAccessor & operator=(const Field::value_type &value)
Definition BitSpec.h:420
BitFieldAccessor & operator()()
Definition BitSpec.h:406
const SG::AuxElement & m_obj
Definition BitSpec.h:473
BitFieldAccessor & operator=(const Field::bits_type &bits)
Definition BitSpec.h:425
constexpr auto spec() const
Definition BitSpec.h:450
auto value(bool truncate=false) const
Definition BitSpec.h:414
auto extract(const std::bitset< N > &packed) const
Definition BitSpec.h:458
Value value(const SG::AuxElement &obj, bool truncate) const
Definition BitSpec.h:217
bits_type extract(const std::bitset< N > &packed) const
Definition BitSpec.h:338
AuxValue & store(SG::AuxElement &obj, Value value) const
Definition BitSpec.h:222
constexpr std::string_view name() const
Definition BitSpec.h:192
void decodeAndAssignFrom(const std::bitset< N > &packed, SG::AuxElement &obj) const
Definition BitSpec.h:359
constexpr BitField(const Params &p)
Definition BitSpec.h:186
static std::int64_t code(bits_type bits)
Definition BitSpec.h:284
bits_type encode(const std::variant< Args... > &value) const
Definition BitSpec.h:264
Value value(const SG::AuxElement &obj) const
Definition BitSpec.h:200
bits_type bits(const SG::AuxElement &obj) const
Definition BitSpec.h:298
bits_type encode(Value value) const
Definition BitSpec.h:248
constexpr std::string_view description() const
Definition BitSpec.h:194
std::bitset< width > bits_type
Definition BitSpec.h:143
constexpr BitField(std::string_view name, std::string_view auxvar, std::string_view description, encoder_type encoder=nullptr, decoder_type decoder=nullptr, Value scale=0, Value offset=0)
Definition BitSpec.h:148
std::function< std::pair< Value, Value >(bits_type)> decoder_type
Definition BitSpec.h:146
void pack(std::bitset< N > &result, const SG::AuxElement &obj) const
Definition BitSpec.h:368
Value decodeFrom(const std::bitset< N > &packed) const
Definition BitSpec.h:354
Value decode(bits_type bits) const
Definition BitSpec.h:317
std::function< bits_type(Value)> encoder_type
Definition BitSpec.h:145
std::pair< Value, Value > range(bits_type bits) const
Definition BitSpec.h:306
static constexpr std::size_t width
Definition BitSpec.h:501
static constexpr void forEachField(auto &&func)
Definition BitSpec.h:520
static constexpr std::string json()
Definition BitSpec.h:525
std::bitset< N > bitset_type
Definition BitSpec.h:502
static constexpr decltype(auto) field()
Definition BitSpec.h:508
static consteval bool validateField()
Definition BitSpec.h:620
friend class Object
Definition BitSpec.h:503
static consteval bool checkOverlap()
Definition BitSpec.h:629
static consteval bool validateFieldList()
Definition BitSpec.h:604
static constexpr auto makeFields(Fields &... fields)
Definition BitSpec.h:544
static constexpr auto allFields()
Definition BitSpec.h:549
static consteval bool validateFields()
Definition BitSpec.h:587
static bitset_type packFields(const Fields &fields, const SG::AuxElement &obj)
Definition BitSpec.h:563
static constexpr std::size_t numFields()
Definition BitSpec.h:515
tag-value pair class.
Definition Value.h:39
STL class.
std::map< std::string, std::string, std::less<> > parse(const std::string &list)
AlgTool to read in LArStripNeighborhoods, and run the BDT Algorithm.
Definition BitSpec.h:23
BitField< Lo, Hi, AuxValue, Value, true > SignedBitField
Definition BitSpec.h:396
AuxElement(SG::AuxVectorData *container, size_t index)
Base class for elements of a container that can have aux data.
STL namespace.
std::uint64_t mask
Definition BitSpec.h:42
std::size_t shift
Definition BitSpec.h:43
static constexpr std::size_t parseNumber(std::string_view str, std::size_t &pos, std::size_t end)
Definition BitSpec.h:46
static constexpr AuxSpec parse(std::string_view spec)
Definition BitSpec.h:61
std::string_view name
Definition BitSpec.h:41
std::string_view name
Definition BitSpec.h:177
std::string_view auxvar
Definition BitSpec.h:178
std::string_view description
Definition BitSpec.h:179
static constexpr auto allFields()
Definition BitSpec.h:484