#pragma once #include #include #include #include namespace Services { class BitsetService { public: struct BitFieldRange { std::uint8_t startPosition; std::uint8_t length; constexpr BitFieldRange(std::uint8_t startPosition, std::uint8_t length) : startPosition(startPosition) , length(length) {} }; template static constexpr std::uint8_t totalBitRangeLength(const std::array& ranges) { auto output = std::uint8_t{0}; for (const auto& range : ranges) { output += range.length; } return output; } template requires std::is_integral_v static constexpr SubjectType extractBitField(SubjectType subject, const BitFieldRange& range) { const auto mask = BitsetService::setBitField(SubjectType{0}, range); return (subject & mask) >> (range.startPosition - range.length + 1); } template requires std::is_integral_v static constexpr SubjectType extractBitField( SubjectType subject, const std::array& ranges ) { auto output = SubjectType{0}; for (const auto& range : ranges) { output = static_cast( (output << range.length) | BitsetService::extractBitField(subject, range) ); } return output; } template requires std::is_integral_v static constexpr SubjectType setBitField(SubjectType subject, const BitFieldRange& range) { const auto mask = static_cast( ~(-1LL << range.length) << (range.startPosition - range.length + 1) ); return subject | mask; } template requires std::is_integral_v static constexpr SubjectType setBitField( SubjectType subject, const std::array& ranges ) { for (const auto& range : ranges) { subject = BitsetService::setBitField(subject, range); } return subject; } template requires std::is_integral_v static constexpr SubjectType clearBitField(SubjectType subject, const BitFieldRange& range) { const auto mask = static_cast( ~(~(-1LL << range.length) << (range.startPosition - range.length + 1)) ); return subject & mask; } template requires std::is_integral_v static constexpr SubjectType clearBitField( SubjectType subject, const std::array& ranges ) { for (const auto& range : ranges) { subject = BitsetService::clearBitField(subject, range); } return subject; } }; }