diff --git a/wpiutil/src/main/native/include/wpi/Endian.h b/wpiutil/src/main/native/include/wpi/Endian.h index 365209c481..ee4a51d250 100644 --- a/wpiutil/src/main/native/include/wpi/Endian.h +++ b/wpiutil/src/main/native/include/wpi/Endian.h @@ -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 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 inline value_type read(const void *memory) { - return read(memory, endian); + value_type ret; + + memcpy(&ret, + LLVM_ASSUME_ALIGNED( + memory, (detail::PickAlignment::value)), + sizeof(value_type)); + return byte_swap(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 inline value_type readNext(const CharT *&memory) { - return readNext(memory, endian); + value_type ret = read(memory); + memory += sizeof(value_type); + return ret; } /// Write a value to memory with a particular endianness. @@ -118,12 +128,12 @@ template inline void write(void *memory, value_type value) { - write(memory, value, endian); + value = byte_swap(value); + memcpy(LLVM_ASSUME_ALIGNED( + memory, (detail::PickAlignment::value)), + &value, sizeof(value_type)); } -template -using make_unsigned_t = typename std::make_unsigned::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 @@ -142,15 +152,15 @@ inline value_type readAtBitAlignment(const void *memory, uint64_t startBit) { val[1] = byte_swap(val[1]); // Shift bits from the lower value into place. - make_unsigned_t lowerVal = val[0] >> startBit; + std::make_unsigned_t lowerVal = val[0] >> startBit; // Mask off upper bits after right shift in case of signed type. - make_unsigned_t numBitsFirstVal = + std::make_unsigned_t numBitsFirstVal = (sizeof(value_type) * 8) - startBit; - lowerVal &= ((make_unsigned_t)1 << numBitsFirstVal) - 1; + lowerVal &= ((std::make_unsigned_t)1 << numBitsFirstVal) - 1; // Get the bits from the upper value. - make_unsigned_t upperVal = - val[1] & (((make_unsigned_t)1 << startBit) - 1); + std::make_unsigned_t upperVal = + val[1] & (((std::make_unsigned_t)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)1 << startBit) - 1; - make_unsigned_t numBitsFirstVal = + val[0] &= ((std::make_unsigned_t)1 << startBit) - 1; + std::make_unsigned_t numBitsFirstVal = (sizeof(value_type) * 8) - startBit; - make_unsigned_t lowerVal = value; + std::make_unsigned_t 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)1 << numBitsFirstVal) - 1); + lowerVal &= (((std::make_unsigned_t)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)1 << startBit) - 1); + val[1] &= ~(((std::make_unsigned_t)1 << startBit) - 1); // Next shift the bits that go into the upper value into position. - make_unsigned_t upperVal = value >> numBitsFirstVal; + std::make_unsigned_t upperVal = value >> numBitsFirstVal; // Mask off upper bits after right shift in case of signed type. - upperVal &= ((make_unsigned_t)1 << startBit) - 1; + upperVal &= ((std::make_unsigned_t)1 << startBit) - 1; val[1] |= upperVal; // Finally, rewrite values.