mirror of
https://github.com/espressif/openthread.git
synced 2026-07-27 22:37:45 +00:00
[common] introduce bit_utils.hpp for bit manipulation (#11884)
This commit introduces a new header file, `common/bit_utils.hpp`, to consolidate bit manipulation utility functions. These functions were previously located in `common/num_utils.hpp`. Moving them to a dedicated file improves code organization and clarity by separating them from general numerical utilities. All files that used these functions have been updated to include the new header.
This commit is contained in:
@@ -393,6 +393,7 @@ openthread_core_files = [
|
||||
"common/binary_search.cpp",
|
||||
"common/binary_search.hpp",
|
||||
"common/bit_set.hpp",
|
||||
"common/bit_utils.hpp",
|
||||
"common/callback.hpp",
|
||||
"common/clearable.hpp",
|
||||
"common/const_cast.hpp",
|
||||
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (c) 2025, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definition for bit manipulation utility functions.
|
||||
*/
|
||||
|
||||
#ifndef BIT_UTILS_HPP_
|
||||
#define BIT_UTILS_HPP_
|
||||
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/numeric_limits.hpp"
|
||||
#include "common/type_traits.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
/**
|
||||
* Counts the number of `1` bits in the binary representation of a given unsigned int bit-mask value.
|
||||
*
|
||||
* @tparam UintType The unsigned int type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
*
|
||||
* @param[in] aMask A bit mask.
|
||||
*
|
||||
* @returns The number of `1` bits in @p aMask.
|
||||
*/
|
||||
template <typename UintType> uint8_t CountBitsInMask(UintType aMask)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
uint8_t count = 0;
|
||||
|
||||
while (aMask != 0)
|
||||
{
|
||||
aMask &= aMask - 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified bit in a given integer to 1.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
*
|
||||
* @param[in,out] aBits A reference to the integer to modify.
|
||||
* @param[in] aBitOffset The offset of the bit to set (0 corresponds to the least-significant bit).
|
||||
*/
|
||||
template <typename UintType> void SetBit(UintType &aBits, uint8_t aBitOffset)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
aBits |= static_cast<UintType>(static_cast<UintType>(1) << aBitOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the specified bit in a given integer to 0.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
*
|
||||
* @param[in,out] aBits A reference to the integer to modify.
|
||||
* @param[in] aBitOffset The offset of the bit to clear (0 corresponds to the least-significant bit).
|
||||
*/
|
||||
template <typename UintType> void ClearBit(UintType &aBits, uint8_t aBitOffset)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
aBits &= (~(static_cast<UintType>(1) << aBitOffset));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the specified bit in a given integer.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
*
|
||||
* @param[in] aBits The integer to read from.
|
||||
* @param[in] aBitOffset The offset of the bit to read (0 corresponds to the least-significant bit).
|
||||
*
|
||||
* @returns The value of the specified bit.
|
||||
*/
|
||||
template <typename UintType> bool GetBit(UintType aBits, uint8_t aBitOffset)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
return (aBits & (static_cast<UintType>(1) << aBitOffset)) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the specified bit in a given integer to a given value (0 or 1).
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
*
|
||||
* @param[in,out] aBits A reference to the integer to modify.
|
||||
* @param[in] aBitOffset The offset of the bit to write (0 corresponds to the least-significant bit).
|
||||
* @param[in] aValue The value to write.
|
||||
*/
|
||||
template <typename UintType> void WriteBit(UintType &aBits, uint8_t aBitOffset, bool aValue)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
if (aValue)
|
||||
{
|
||||
SetBit<UintType>(aBits, aBitOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearBit<UintType>(aBits, aBitOffset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the offset of the lowest non-zero bit in a given mask.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
*
|
||||
* @param[in] aMask The bitmask to inspect (MUST NOT be zero).
|
||||
*
|
||||
* @returns The offset of the lowest set bit (0 corresponds to the least-significant bit).
|
||||
*/
|
||||
template <typename UintType> inline constexpr uint8_t BitOffsetOfMask(UintType aMask)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
return (aMask & 0x1) ? 0 : (1 + BitOffsetOfMask<UintType>(aMask >> 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a value to a specified bit-field within an integer.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
* @tparam kMask The bit mask indicating the field to modify (MUST not be 0). The mask must be pre-shifted.
|
||||
* @tparam kOffset The bit offset to write. If not provided, this is computed from @p kMask.
|
||||
*
|
||||
* @param[in,out] aBits A reference to the integer to modify.
|
||||
* @param[in] aValue The value to write into the field (the value should not be pre-shifted).
|
||||
*/
|
||||
template <typename UintType, UintType kMask, UintType kOffset = BitOffsetOfMask(kMask)>
|
||||
void WriteBits(UintType &aBits, UintType aValue)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
aBits = ((aBits & ~kMask) | ((aValue << kOffset) & kMask));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a value to a specified bit-field within an integer and returns the modified integer.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
* @tparam kMask The bitmask indicating the field to modify (must not be zero). The mask must be pre-shifted.
|
||||
* @tparam kOffset The bit offset of the field. If not provided, this is computed from @p kMask.
|
||||
*
|
||||
* @param[in] aBits The original integer value.
|
||||
* @param[in] aValue The value to write into the field (it should not be pre-shifted).
|
||||
*
|
||||
* @returns The integer with the specified bit-field updated.
|
||||
*/
|
||||
template <typename UintType, UintType kMask, UintType kOffset = BitOffsetOfMask(kMask)>
|
||||
UintType UpdateBits(UintType aBits, UintType aValue)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
return ((aBits & ~kMask) | ((aValue << kOffset) & kMask));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the value of a specified bit-field from an integer.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
* @tparam kMask The bitmask indicating the field to read (must not be zero). The mask must be pre-shifted.
|
||||
* @tparam kOffset The bit offset of the field. If not provided, this is computed from @p kMask.
|
||||
*
|
||||
* @param[in] aBits The integer value to read from.
|
||||
*
|
||||
* @returns The value from the bit-field (shifted to start at bit 0).
|
||||
*/
|
||||
template <typename UintType, UintType kMask, UintType kOffset = BitOffsetOfMask(kMask)>
|
||||
UintType ReadBits(UintType aBits)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
return (aBits & kMask) >> kOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a value to a specified bit-field within a little-endian integer and returns the modified integer in
|
||||
* little-endian format.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
* @tparam kMask The bitmask indicating the field to modify (must not be zero). The mask must be pre-shifted.
|
||||
* @tparam kOffset The bit offset of the field. If not provided, this is computed from @p kMask.
|
||||
*
|
||||
* @param[in] aBits The original integer value in little-endian format.
|
||||
* @param[in] aValue The value to write into the field (it should not be pre-shifted).
|
||||
*
|
||||
* @returns The updated integer in little-endian format.
|
||||
*/
|
||||
template <typename UintType, UintType kMask, UintType kOffset = BitOffsetOfMask(kMask)>
|
||||
UintType UpdateBitsLittleEndian(UintType aBits, UintType aValue)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
return LittleEndian::HostSwap<UintType>((LittleEndian::HostSwap<UintType>(aBits) & ~kMask) |
|
||||
((aValue << kOffset) & kMask));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a value to a specified bit-field within a big-endian integer and returns the modified integer in big-endian
|
||||
* format.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
* @tparam kMask The bitmask indicating the field to modify (must not be zero). The mask must be pre-shifted.
|
||||
* @tparam kOffset The bit offset of the field. If not provided, this is computed from @p kMask.
|
||||
*
|
||||
* @param[in] aBits The original integer value in big-endian format.
|
||||
* @param[in] aValue The value to write into the field (it should not be pre-shifted).
|
||||
*
|
||||
* @returns The updated integer in big-endian format.
|
||||
*/
|
||||
template <typename UintType, UintType kMask, UintType kOffset = BitOffsetOfMask(kMask)>
|
||||
UintType UpdateBitsBigEndian(UintType aBits, UintType aValue)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
return BigEndian::HostSwap<UintType>((BigEndian::HostSwap<UintType>(aBits) & ~kMask) |
|
||||
((aValue << kOffset) & kMask));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the value of a specified bit-field from a little-endian integer.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
* @tparam kMask The bitmask indicating the field to read (must not be zero). The mask must be pre-shifted.
|
||||
* @tparam kOffset The bit offset of the field. If not provided, this is computed from @p kMask.
|
||||
*
|
||||
* @param[in] aBits The integer value in little-endian format to read from.
|
||||
*
|
||||
* @returns The value from the bit-field (shifted to start at bit 0).
|
||||
*/
|
||||
template <typename UintType, UintType kMask, UintType kOffset = BitOffsetOfMask(kMask)>
|
||||
UintType ReadBitsLittleEndian(UintType aBits)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
return (LittleEndian::HostSwap<UintType>(aBits) & kMask) >> kOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the value of a specified bit-field from a big-endian integer.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
* @tparam kMask The bitmask indicating the field to read (must not be zero). The mask must be pre-shifted.
|
||||
* @tparam kOffset The bit offset of the field. If not provided, this is computed from @p kMask.
|
||||
*
|
||||
* @param[in] aBits The integer value in big-endian format to read from.
|
||||
*
|
||||
* @returns The value from the bit-field (shifted to start at bit 0).
|
||||
*/
|
||||
template <typename UintType, UintType kMask, UintType kOffset = BitOffsetOfMask(kMask)>
|
||||
UintType ReadBitsBigEndian(UintType aBits)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
return (BigEndian::HostSwap<UintType>(aBits) & kMask) >> kOffset;
|
||||
}
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // BIT_UTILS_HPP_
|
||||
@@ -34,7 +34,6 @@
|
||||
#ifndef NUM_UTILS_HPP_
|
||||
#define NUM_UTILS_HPP_
|
||||
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/numeric_limits.hpp"
|
||||
#include "common/type_traits.hpp"
|
||||
|
||||
@@ -255,259 +254,6 @@ template <typename IntType> inline IntType DivideAndRoundUp(IntType aDividend, I
|
||||
*/
|
||||
inline unsigned long ToUlong(uint32_t aUint32) { return static_cast<unsigned long>(aUint32); }
|
||||
|
||||
/**
|
||||
* Counts the number of `1` bits in the binary representation of a given unsigned int bit-mask value.
|
||||
*
|
||||
* @tparam UintType The unsigned int type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
*
|
||||
* @param[in] aMask A bit mask.
|
||||
*
|
||||
* @returns The number of `1` bits in @p aMask.
|
||||
*/
|
||||
template <typename UintType> uint8_t CountBitsInMask(UintType aMask)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
uint8_t count = 0;
|
||||
|
||||
while (aMask != 0)
|
||||
{
|
||||
aMask &= aMask - 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified bit of the given integer to 1.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
*
|
||||
* @param[in,out] aBits The integer to set the bit.
|
||||
* @param[in] aBitOffset The bit offset to set. The bit offset starts with zero corresponding to the
|
||||
* least-significant bit.
|
||||
*/
|
||||
template <typename UintType> void SetBit(UintType &aBits, uint8_t aBitOffset)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
aBits |= static_cast<UintType>(static_cast<UintType>(1) << aBitOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the specified bit of the given integer.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
*
|
||||
* @param[in,out] aBits The integer to clear the bit.
|
||||
* @param[in] aBitOffset The bit offset to clear. The bit offset starts with zero corresponding to the
|
||||
* least-significant bit.
|
||||
*/
|
||||
template <typename UintType> void ClearBit(UintType &aBits, uint8_t aBitOffset)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
aBits &= (~(static_cast<UintType>(1) << aBitOffset));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the specified bit of the given integer.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
*
|
||||
* @param[in] aBits The integer to get the bit.
|
||||
* @param[in] aBitOffset The bit offset to get. The bit offset starts with zero corresponding to the
|
||||
* least-significant bit.
|
||||
*
|
||||
* @returns The value of the specified bit.
|
||||
*/
|
||||
template <typename UintType> bool GetBit(UintType aBits, uint8_t aBitOffset)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
return (aBits & (static_cast<UintType>(1) << aBitOffset)) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the specified bit of the given integer to the given value (0 or 1).
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
*
|
||||
* @param[in,out] aBits The integer to write the bit.
|
||||
* @param[in] aBitOffset The bit offset to get. The bit offset starts with zero corresponding to the
|
||||
* least-significant bit.
|
||||
* @param[in] aValue The value to write.
|
||||
*/
|
||||
template <typename UintType> void WriteBit(UintType &aBits, uint8_t aBitOffset, bool aValue)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
if (aValue)
|
||||
{
|
||||
SetBit<UintType>(aBits, aBitOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearBit<UintType>(aBits, aBitOffset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the offset of the lowest non-zero bit in the given mask.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
*
|
||||
* @param[in] aMask The mask (MUST not be 0) to calculate the offset of the lowest non-zero bit.
|
||||
*
|
||||
* @returns The offset of the lowest non-zero bit in the mask.
|
||||
*/
|
||||
template <typename UintType> inline constexpr uint8_t BitOffsetOfMask(UintType aMask)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
return (aMask & 0x1) ? 0 : (1 + BitOffsetOfMask<UintType>(aMask >> 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the specified bits of the given integer to the given value.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
* @tparam kMask The bit mask (MUST not be 0) to write. The @p kMask must be provided in a shifted form.
|
||||
* @tparam kOffset The bit offset to write. The default @p kOffset is computed from the given @p kMask.
|
||||
*
|
||||
* @param[in,out] aBits The integer to write the bits.
|
||||
* @param[in] aValue The value to write.
|
||||
*/
|
||||
template <typename UintType, UintType kMask, UintType kOffset = BitOffsetOfMask(kMask)>
|
||||
void WriteBits(UintType &aBits, UintType aValue)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
aBits = ((aBits & ~kMask) | ((aValue << kOffset) & kMask));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the specified bits of the given integer to the given value and returns the updated integer.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
* @tparam kMask The bit mask (MUST not be 0) to write. The @p kMask must be provided in a shifted form.
|
||||
* @tparam kOffset The bit offset to write. The default @p kOffset is computed from the given @p kMask.
|
||||
*
|
||||
* @param[in] aBits The integer to write the bits.
|
||||
* @param[in] aValue The value to write.
|
||||
*
|
||||
* @returns The updated integer.
|
||||
*/
|
||||
template <typename UintType, UintType kMask, UintType kOffset = BitOffsetOfMask(kMask)>
|
||||
UintType UpdateBits(UintType aBits, UintType aValue)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
return ((aBits & ~kMask) | ((aValue << kOffset) & kMask));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the value of the specified bits of the given integer.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
* @tparam kMask The bit mask (MUST not be 0) to write. The @p kMask must be provided in a shifted form.
|
||||
* @tparam kOffset The bit offset to write. The default @p kOffset is computed from the given @p kMask.
|
||||
*
|
||||
* @param[in] aBits The integer to read the bits.
|
||||
*
|
||||
* @returns The value of the specified bits.
|
||||
*/
|
||||
template <typename UintType, UintType kMask, UintType kOffset = BitOffsetOfMask(kMask)>
|
||||
UintType ReadBits(UintType aBits)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
return (aBits & kMask) >> kOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the specified bits of the given integer stored in little-endian format to the given value and returns the
|
||||
* updated integer stored in little-endian format.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
* @tparam kMask The bit mask (MUST not be 0) to write. The @p kMask must be provided in a shifted form.
|
||||
* @tparam kOffset The bit offset to write. The default @p kOffset is computed from the given @p kMask.
|
||||
*
|
||||
* @param[in] aBits The integer to write the bits.
|
||||
* @param[in] aValue The value to write.
|
||||
*
|
||||
* @returns The updated integer.
|
||||
*/
|
||||
template <typename UintType, UintType kMask, UintType kOffset = BitOffsetOfMask(kMask)>
|
||||
UintType UpdateBitsLittleEndian(UintType aBits, UintType aValue)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
return LittleEndian::HostSwap<UintType>((LittleEndian::HostSwap<UintType>(aBits) & ~kMask) |
|
||||
((aValue << kOffset) & kMask));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the specified bits of the given integer stored in big-endian format to the given value and returns the updated
|
||||
* integer stored in big-endian format.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
* @tparam kMask The bit mask (MUST not be 0) to write. The @p kMask must be provided in a shifted form.
|
||||
* @tparam kOffset The bit offset to write. The default @p kOffset is computed from the given @p kMask.
|
||||
*
|
||||
* @param[in] aBits A pointer to the integer to write the bits.
|
||||
* @param[in] aValue The value to write.
|
||||
*
|
||||
* @returns The updated integer.
|
||||
*/
|
||||
template <typename UintType, UintType kMask, UintType kOffset = BitOffsetOfMask(kMask)>
|
||||
UintType UpdateBitsBigEndian(UintType aBits, UintType aValue)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
return BigEndian::HostSwap<UintType>((BigEndian::HostSwap<UintType>(aBits) & ~kMask) |
|
||||
((aValue << kOffset) & kMask));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the value of the specified bits of the given integer stored in little-endian format.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
* @tparam kMask The bit mask (MUST not be 0) to write. The @p kMask must be provided in a shifted form.
|
||||
* @tparam kOffset The bit offset to write. The default @p kOffset is computed from the given @p kMask.
|
||||
*
|
||||
* @param[in] aBits The integer stored in little-endian format to read the bits.
|
||||
*
|
||||
* @returns The value of the specified bits.
|
||||
*/
|
||||
template <typename UintType, UintType kMask, UintType kOffset = BitOffsetOfMask(kMask)>
|
||||
UintType ReadBitsLittleEndian(UintType aBits)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
return (LittleEndian::HostSwap<UintType>(aBits) & kMask) >> kOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the value of the specified bits of the given integer stored in big-endian format.
|
||||
*
|
||||
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
* @tparam kMask The bit mask (MUST not be 0) to write. The @p kMask must be provided in a shifted form.
|
||||
* @tparam kOffset The bit offset to write. The default @p kOffset is computed from the given @p kMask.
|
||||
*
|
||||
* @param[in] aBits The integer stored in big-endian format to read the bits.
|
||||
*
|
||||
* @returns The value of the specified bits.
|
||||
*/
|
||||
template <typename UintType, UintType kMask, UintType kOffset = BitOffsetOfMask(kMask)>
|
||||
UintType ReadBitsBigEndian(UintType aBits)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
return (BigEndian::HostSwap<UintType>(aBits) & kMask) >> kOffset;
|
||||
}
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // NUM_UTILS_HPP_
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include <openthread/platform/radio.h>
|
||||
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/equatable.hpp"
|
||||
#include "common/numeric_limits.hpp"
|
||||
#include "common/string.hpp"
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include "common/as_core_type.hpp"
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/numeric_limits.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <openthread/dataset.h>
|
||||
#include <openthread/platform/radio.h>
|
||||
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/const_cast.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/message.hpp"
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include "timestamp.hpp"
|
||||
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/num_utils.hpp"
|
||||
#include "common/numeric_limits.hpp"
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#include "common/appender.hpp"
|
||||
#include "common/as_core_type.hpp"
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/clearable.hpp"
|
||||
#include "common/data.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/clearable.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/message.hpp"
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
|
||||
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/data.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/locator.hpp"
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "mle_types.hpp"
|
||||
|
||||
#include "common/array.hpp"
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/message.hpp"
|
||||
#include "common/random.hpp"
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include <openthread/netdata.h>
|
||||
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/const_cast.hpp"
|
||||
#include "common/debug.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include "test_util.h"
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/num_utils.hpp"
|
||||
#include "common/numeric_limits.hpp"
|
||||
|
||||
Reference in New Issue
Block a user