Files
BloomPatched/src/Services/BitsetService.hpp
2023-09-10 01:19:23 +01:00

104 lines
3.4 KiB
C++

#pragma once
#include <cstdint>
#include <cstddef>
#include <array>
#include <type_traits>
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 = static_cast<SubjectType>(
(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;
}
};
}