[wpiutil] Endian.h: minor cleanup and improvements (#2454)

- Make use of if constexpr when possible for byte_swap
- Remove unnecessary make_unsigned_t alias (added to STL in C++14)
This commit is contained in:
Armeen Mahdian
2020-03-28 12:35:47 -05:00
committed by GitHub
parent b7a79c70cc
commit 0d30108dcb

View File

@@ -68,7 +68,9 @@ inline value_type byte_swap(value_type value, endianness endian) {
/// Swap the bytes of value to match the given endianness.
template<typename value_type, endianness endian>
inline value_type byte_swap(value_type value) {
return byte_swap(value, endian);
if constexpr ((endian != native) && (endian != system_endianness()))
sys::swapByteOrder(value);
return value;
}
/// Read a value of a particular endianness from memory.
@@ -87,7 +89,13 @@ template<typename value_type,
endianness endian,
std::size_t alignment>
inline value_type read(const void *memory) {
return read<value_type, alignment>(memory, endian);
value_type ret;
memcpy(&ret,
LLVM_ASSUME_ALIGNED(
memory, (detail::PickAlignment<value_type, alignment>::value)),
sizeof(value_type));
return byte_swap<value_type, endian>(ret);
}
/// Read a value of a particular endianness from a buffer, and increment the
@@ -102,7 +110,9 @@ inline value_type readNext(const CharT *&memory, endianness endian) {
template<typename value_type, endianness endian, std::size_t alignment,
typename CharT>
inline value_type readNext(const CharT *&memory) {
return readNext<value_type, alignment, CharT>(memory, endian);
value_type ret = read<value_type, endian, alignment>(memory);
memory += sizeof(value_type);
return ret;
}
/// Write a value to memory with a particular endianness.
@@ -118,12 +128,12 @@ template<typename value_type,
endianness endian,
std::size_t alignment>
inline void write(void *memory, value_type value) {
write<value_type, alignment>(memory, value, endian);
value = byte_swap<value_type, endian>(value);
memcpy(LLVM_ASSUME_ALIGNED(
memory, (detail::PickAlignment<value_type, alignment>::value)),
&value, sizeof(value_type));
}
template <typename value_type>
using make_unsigned_t = typename std::make_unsigned<value_type>::type;
/// Read a value of a particular endianness from memory, for a location
/// that starts at the given bit offset within the first byte.
template <typename value_type, endianness endian, std::size_t alignment>
@@ -142,15 +152,15 @@ inline value_type readAtBitAlignment(const void *memory, uint64_t startBit) {
val[1] = byte_swap<value_type, endian>(val[1]);
// Shift bits from the lower value into place.
make_unsigned_t<value_type> lowerVal = val[0] >> startBit;
std::make_unsigned_t<value_type> lowerVal = val[0] >> startBit;
// Mask off upper bits after right shift in case of signed type.
make_unsigned_t<value_type> numBitsFirstVal =
std::make_unsigned_t<value_type> numBitsFirstVal =
(sizeof(value_type) * 8) - startBit;
lowerVal &= ((make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1;
lowerVal &= ((std::make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1;
// Get the bits from the upper value.
make_unsigned_t<value_type> upperVal =
val[1] & (((make_unsigned_t<value_type>)1 << startBit) - 1);
std::make_unsigned_t<value_type> upperVal =
val[1] & (((std::make_unsigned_t<value_type>)1 << startBit) - 1);
// Shift them in to place.
upperVal <<= numBitsFirstVal;
@@ -178,15 +188,15 @@ inline void writeAtBitAlignment(void *memory, value_type value,
// Mask off any existing bits in the upper part of the lower value that
// we want to replace.
val[0] &= ((make_unsigned_t<value_type>)1 << startBit) - 1;
make_unsigned_t<value_type> numBitsFirstVal =
val[0] &= ((std::make_unsigned_t<value_type>)1 << startBit) - 1;
std::make_unsigned_t<value_type> numBitsFirstVal =
(sizeof(value_type) * 8) - startBit;
make_unsigned_t<value_type> lowerVal = value;
std::make_unsigned_t<value_type> lowerVal = value;
if (startBit > 0) {
// Mask off the upper bits in the new value that are not going to go into
// the lower value. This avoids a left shift of a negative value, which
// is undefined behavior.
lowerVal &= (((make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1);
lowerVal &= (((std::make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1);
// Now shift the new bits into place
lowerVal <<= startBit;
}
@@ -194,11 +204,11 @@ inline void writeAtBitAlignment(void *memory, value_type value,
// Mask off any existing bits in the lower part of the upper value that
// we want to replace.
val[1] &= ~(((make_unsigned_t<value_type>)1 << startBit) - 1);
val[1] &= ~(((std::make_unsigned_t<value_type>)1 << startBit) - 1);
// Next shift the bits that go into the upper value into position.
make_unsigned_t<value_type> upperVal = value >> numBitsFirstVal;
std::make_unsigned_t<value_type> upperVal = value >> numBitsFirstVal;
// Mask off upper bits after right shift in case of signed type.
upperVal &= ((make_unsigned_t<value_type>)1 << startBit) - 1;
upperVal &= ((std::make_unsigned_t<value_type>)1 << startBit) - 1;
val[1] |= upperVal;
// Finally, rewrite values.