Bitset service

This commit is contained in:
Nav
2023-09-07 23:24:30 +01:00
parent 47f9ce0415
commit d7891b386b

View File

@@ -0,0 +1,102 @@
#pragma once
#include <string>
#include <bitset>
#include <limits>
#include <vector>
#include <numeric>
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 <std::size_t bitFieldRangeCount>
static constexpr std::uint8_t totalBitRangeLength(const std::array<BitFieldRange, bitFieldRangeCount>& ranges) {
auto output = std::uint8_t{0};
for (const auto& range : ranges) {
output += range.length;
}
return output;
}
template <typename SubjectType>
requires std::is_integral_v<SubjectType>
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 <typename SubjectType, std::size_t bitFieldRangeCount>
requires std::is_integral_v<SubjectType>
static constexpr SubjectType extractBitField(
SubjectType subject,
const std::array<BitFieldRange, bitFieldRangeCount>& ranges
) {
auto output = SubjectType{0};
for (const auto& range : ranges) {
output = (output << range.length) | BitsetService::extractBitField(subject, range);
}
return output;
}
template <typename SubjectType>
requires std::is_integral_v<SubjectType>
static constexpr SubjectType setBitField(SubjectType subject, const BitFieldRange& range) {
const auto mask = static_cast<SubjectType>(
~(-1LL << range.length) << (range.startPosition - range.length + 1)
);
return subject | mask;
}
template <typename SubjectType, std::size_t bitFieldRangeCount>
requires std::is_integral_v<SubjectType>
static constexpr SubjectType setBitField(
SubjectType subject,
const std::array<BitFieldRange, bitFieldRangeCount>& ranges
) {
for (const auto& range : ranges) {
subject = BitsetService::setBitField(subject, range);
}
return subject;
}
template <typename SubjectType>
requires std::is_integral_v<SubjectType>
static constexpr SubjectType clearBitField(SubjectType subject, const BitFieldRange& range) {
const auto mask = static_cast<SubjectType>(
~(~(-1LL << range.length) << (range.startPosition - range.length + 1))
);
return subject & mask;
}
template <typename SubjectType, std::size_t bitFieldRangeCount>
requires std::is_integral_v<SubjectType>
static constexpr SubjectType clearBitField(
SubjectType subject,
const std::array<BitFieldRange, bitFieldRangeCount>& ranges
) {
for (const auto& range : ranges) {
subject = BitsetService::clearBitField(subject, range);
}
return subject;
}
};
}