Bitset service
This commit is contained in:
102
src/Services/BitsetService.hpp
Normal file
102
src/Services/BitsetService.hpp
Normal 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;
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user