1 #ifndef BOOST_ENDIAN_DETAIL_ENDIAN_REVERSE_HPP_INCLUDED
2 #define BOOST_ENDIAN_DETAIL_ENDIAN_REVERSE_HPP_INCLUDED
4 // Copyright 2019 Peter Dimov
6 // Distributed under the Boost Software License, Version 1.0.
7 // http://www.boost.org/LICENSE_1_0.txt
9 #include <boost/endian/detail/integral_by_size.hpp>
10 #include <boost/endian/detail/intrinsic.hpp>
11 #include <boost/type_traits/is_integral.hpp>
12 #include <boost/type_traits/is_same.hpp>
13 #include <boost/static_assert.hpp>
14 #include <boost/cstdint.hpp>
15 #include <boost/config.hpp>
19 #if defined(BOOST_ENDIAN_NO_INTRINSICS)
20 # if defined(BOOST_NO_CXX14_CONSTEXPR)
21 # define BOOST_ENDIAN_CONSTEXPR
23 # define BOOST_ENDIAN_CONSTEXPR constexpr
26 # if defined(BOOST_ENDIAN_CONSTEXPR_INTRINSICS)
27 # define BOOST_ENDIAN_CONSTEXPR BOOST_CONSTEXPR
29 # define BOOST_ENDIAN_CONSTEXPR
41 // -- portable approach suggested by tymofey, with avoidance of undefined behavior
42 // as suggested by Giovanni Piero Deretta, with a further refinement suggested
44 // -- intrinsic approach suggested by reviewers, and by David Stone, who provided
45 // his Boost licensed macro implementation (detail/intrinsic.hpp)
47 inline uint8_t BOOST_CONSTEXPR endian_reverse_impl( uint8_t x ) BOOST_NOEXCEPT
52 inline uint16_t BOOST_ENDIAN_CONSTEXPR endian_reverse_impl( uint16_t x ) BOOST_NOEXCEPT
54 #ifdef BOOST_ENDIAN_NO_INTRINSICS
56 return (x << 8) | (x >> 8);
60 return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x);
65 inline uint32_t BOOST_ENDIAN_CONSTEXPR endian_reverse_impl( uint32_t x ) BOOST_NOEXCEPT
67 #ifdef BOOST_ENDIAN_NO_INTRINSICS
69 uint32_t step16 = x << 16 | x >> 16;
70 return ((step16 << 8) & 0xff00ff00) | ((step16 >> 8) & 0x00ff00ff);
74 return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x);
79 inline uint64_t BOOST_ENDIAN_CONSTEXPR endian_reverse_impl( uint64_t x ) BOOST_NOEXCEPT
81 #ifdef BOOST_ENDIAN_NO_INTRINSICS
83 uint64_t step32 = x << 32 | x >> 32;
84 uint64_t step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16 | (step32 & 0xFFFF0000FFFF0000ULL) >> 16;
85 return (step16 & 0x00FF00FF00FF00FFULL) << 8 | (step16 & 0xFF00FF00FF00FF00ULL) >> 8;
89 return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x);
94 #if defined(BOOST_HAS_INT128)
96 inline uint128_type BOOST_ENDIAN_CONSTEXPR endian_reverse_impl( uint128_type x ) BOOST_NOEXCEPT
98 return endian_reverse_impl( static_cast<uint64_t>( x >> 64 ) ) |
99 static_cast<uint128_type>( endian_reverse_impl( static_cast<uint64_t>( x ) ) ) << 64;
104 } // namespace detail
107 // T is non-bool integral
109 template<class T> inline BOOST_CONSTEXPR T endian_reverse( T x ) BOOST_NOEXCEPT
111 BOOST_STATIC_ASSERT( is_integral<T>::value && !(is_same<T, bool>::value) );
113 typedef typename detail::integral_by_size< sizeof(T) >::type uintN_t;
115 return static_cast<T>( detail::endian_reverse_impl( static_cast<uintN_t>( x ) ) );
118 template <class EndianReversible>
119 inline void endian_reverse_inplace(EndianReversible& x) BOOST_NOEXCEPT
121 x = endian_reverse( x );
124 } // namespace endian
127 #endif // BOOST_ENDIAN_DETAIL_ENDIAN_REVERSE_HPP_INCLUDED