@@ -187,27 +187,26 @@ namespace detail {
187187 using uint_t = std::make_unsigned_t <std::remove_cvref_t <UT>>;
188188 // Fallback implementation that handles even __int24 etc.
189189 constexpr size_t const nbits = CHAR_BIT;
190+ constexpr size_t const delta = 2ULL * nbits;
190191
191- size_t diff = nbits * (sizeof (T) - 1 );
192- uint_t mask1 = std::numeric_limits<uint8_t >::max ();
193- auto mask2 = static_cast <uint_t >(mask1 << diff);
194- uint_t new_value = val;
192+ size_t bit_offset = nbits * (sizeof (T) + 1 );
193+ size_t shift_amount = bit_offset - delta;
194+ uint_t low_byte_mask = std::numeric_limits<uint8_t >::max ();
195+ auto high_byte_mask = static_cast <uint_t >(low_byte_mask << shift_amount);
196+ uint_t new_value = val;
195197 for (size_t ii = 0 ; ii < sizeof (T) / 2 ; ++ii) {
196- uint_t const byte1 = new_value & mask1;
197- uint_t const byte2 = new_value & mask2;
198- auto const byte3 = static_cast <uint_t >(byte1 << diff);
199- auto const byte4 = static_cast <uint_t >(byte2 >> diff);
200- new_value ^= byte1;
201- new_value ^= byte2;
202- new_value ^= byte3;
203- new_value ^= byte4;
204- mask1 = std::rotl (mask1, nbits);
205- mask2 = std::rotr (mask2, nbits);
206- diff -= 2ULL * nbits;
198+ bit_offset -= delta;
199+ uint_t const low_byte = new_value & low_byte_mask;
200+ uint_t const high_byte = new_value & high_byte_mask;
201+ new_value ^= low_byte;
202+ new_value ^= high_byte;
203+ new_value ^= static_cast <uint_t >(low_byte << bit_offset);
204+ new_value ^= static_cast <uint_t >(high_byte >> bit_offset);
205+ low_byte_mask = std::rotl (low_byte_mask, nbits);
206+ high_byte_mask = std::rotr (high_byte_mask, nbits);
207207 }
208208 return uint_t (new_value & std::numeric_limits<uint_t >::max ());
209209 };
210- // NOLINTNEXTLINE(misc-redundant-expression)
211210 if constexpr (CHAR_BIT == 8 ) {
212211 if (!std::is_constant_evaluated ()) {
213212 constexpr auto const builtin_bswap = overloaded (
@@ -258,6 +257,11 @@ namespace detail {
258257#endif
259258 }
260259
260+ static_assert (byteswap_impl(uint8_t {0x35U }) == uint8_t {0x35U });
261+ static_assert (byteswap_impl(uint16_t {0x1357U }) == uint16_t {0x5713U });
262+ static_assert (byteswap_impl(0x01234567U ) == 0x67452301U );
263+ static_assert (byteswap_impl(0x0123456789abcdefULL ) == 0xefcdab8967452301ULL );
264+
261265 template <std::integral T>
262266 [[nodiscard]] CONST_INLINE constexpr T byteswap (T value) noexcept {
263267 // Need this to handle "(unsigned)? long long" and "(unsigned)? long".
0 commit comments