dolphin/Source/Core/Common/BitUtils.h

103 lines
2.8 KiB
C++

// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <climits>
#include <cstddef>
#include <type_traits>
namespace Common
{
///
/// Retrieves the size of a type in bits.
///
/// @tparam T Type to get the size of.
///
/// @return the size of the type in bits.
///
template <typename T>
constexpr size_t BitSize() noexcept
{
return sizeof(T) * CHAR_BIT;
}
///
/// Extracts a bit from a value.
///
/// @param src The value to extract a bit from.
/// @param bit The bit to extract.
///
/// @tparam T The type of the value.
///
/// @return The extracted bit.
///
template <typename T>
constexpr T ExtractBit(const T src, const size_t bit) noexcept
{
return (src >> bit) & static_cast<T>(1);
}
///
/// Extracts a bit from a value.
///
/// @param src The value to extract a bit from.
///
/// @tparam bit The bit to extract.
/// @tparam T The type of the value.
///
/// @return The extracted bit.
///
template <size_t bit, typename T>
constexpr T ExtractBit(const T src) noexcept
{
static_assert(bit < BitSize<T>(), "Specified bit must be within T's bit width.");
return ExtractBit(src, bit);
}
///
/// Extracts a range of bits from a value.
///
/// @param src The value to extract the bits from.
/// @param begin The beginning of the bit range. This is inclusive.
/// @param end The ending of the bit range. This is inclusive.
///
/// @tparam T The type of the value.
/// @tparam Result The returned result type. This is the unsigned analog
/// of a signed type if a signed type is passed as T.
///
/// @return The extracted bits.
///
template <typename T, typename Result = std::make_unsigned_t<T>>
constexpr Result ExtractBits(const T src, const size_t begin, const size_t end) noexcept
{
return static_cast<Result>(((static_cast<Result>(src) << ((BitSize<T>() - 1) - end)) >>
(BitSize<T>() - end + begin - 1)));
}
///
/// Extracts a range of bits from a value.
///
/// @param src The value to extract the bits from.
///
/// @tparam begin The beginning of the bit range. This is inclusive.
/// @tparam end The ending of the bit range. This is inclusive.
/// @tparam T The type of the value.
/// @tparam Result The returned result type. This is the unsigned analog
/// of a signed type if a signed type is passed as T.
///
/// @return The extracted bits.
///
template <size_t begin, size_t end, typename T, typename Result = std::make_unsigned_t<T>>
constexpr Result ExtractBits(const T src) noexcept
{
static_assert(begin < end, "Beginning bit must be less than the ending bit.");
static_assert(begin < BitSize<T>(), "Beginning bit is larger than T's bit width.");
static_assert(end < BitSize<T>(), "Ending bit is larger than T's bit width.");
return ExtractBits<T, Result>(src, begin, end);
}
} // namespace Common