/src/boost/boost/endian/detail/endian_reverse.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | #ifndef BOOST_ENDIAN_DETAIL_ENDIAN_REVERSE_HPP_INCLUDED |
2 | | #define BOOST_ENDIAN_DETAIL_ENDIAN_REVERSE_HPP_INCLUDED |
3 | | |
4 | | // Copyright 2019, 2020 Peter Dimov |
5 | | // Distributed under the Boost Software License, Version 1.0. |
6 | | // https://www.boost.org/LICENSE_1_0.txt |
7 | | |
8 | | #include <boost/endian/detail/integral_by_size.hpp> |
9 | | #include <boost/endian/detail/intrinsic.hpp> |
10 | | #include <boost/endian/detail/is_scoped_enum.hpp> |
11 | | #include <boost/endian/detail/is_integral.hpp> |
12 | | #include <boost/endian/detail/static_assert.hpp> |
13 | | #include <boost/config.hpp> |
14 | | #include <type_traits> |
15 | | #include <cstdint> |
16 | | #include <cstddef> |
17 | | #include <cstring> |
18 | | |
19 | | #if defined(BOOST_ENDIAN_NO_INTRINSICS) |
20 | | # if defined(BOOST_NO_CXX14_CONSTEXPR) |
21 | | # define BOOST_ENDIAN_CONSTEXPR |
22 | | # else |
23 | | # define BOOST_ENDIAN_CONSTEXPR constexpr |
24 | | # endif |
25 | | #else |
26 | | # if defined(BOOST_ENDIAN_CONSTEXPR_INTRINSICS) |
27 | | # define BOOST_ENDIAN_CONSTEXPR BOOST_CONSTEXPR |
28 | | # else |
29 | | # define BOOST_ENDIAN_CONSTEXPR |
30 | | # endif |
31 | | #endif |
32 | | |
33 | | namespace boost |
34 | | { |
35 | | namespace endian |
36 | | { |
37 | | |
38 | | namespace detail |
39 | | { |
40 | | |
41 | | // -- portable approach suggested by tymofey, with avoidance of undefined behavior |
42 | | // as suggested by Giovanni Piero Deretta, with a further refinement suggested |
43 | | // by Pyry Jahkola. |
44 | | // -- intrinsic approach suggested by reviewers, and by David Stone, who provided |
45 | | // his Boost licensed macro implementation (detail/intrinsic.hpp) |
46 | | |
47 | | inline std::uint8_t BOOST_CONSTEXPR endian_reverse_impl( std::uint8_t x ) BOOST_NOEXCEPT |
48 | 0 | { |
49 | 0 | return x; |
50 | 0 | } |
51 | | |
52 | | inline std::uint16_t BOOST_ENDIAN_CONSTEXPR endian_reverse_impl( std::uint16_t x ) BOOST_NOEXCEPT |
53 | 0 | { |
54 | 0 | #ifdef BOOST_ENDIAN_NO_INTRINSICS |
55 | 0 |
|
56 | 0 | return (x << 8) | (x >> 8); |
57 | 0 |
|
58 | 0 | #else |
59 | 0 |
|
60 | 0 | return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x); |
61 | 0 |
|
62 | 0 | #endif |
63 | 0 | } |
64 | | |
65 | | inline std::uint32_t BOOST_ENDIAN_CONSTEXPR endian_reverse_impl( std::uint32_t x ) BOOST_NOEXCEPT |
66 | 0 | { |
67 | 0 | #ifdef BOOST_ENDIAN_NO_INTRINSICS |
68 | 0 |
|
69 | 0 | std::uint32_t step16 = x << 16 | x >> 16; |
70 | 0 | return ((step16 << 8) & 0xff00ff00) | ((step16 >> 8) & 0x00ff00ff); |
71 | 0 |
|
72 | 0 | #else |
73 | 0 |
|
74 | 0 | return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x); |
75 | 0 |
|
76 | 0 | #endif |
77 | 0 | } |
78 | | |
79 | | inline std::uint64_t BOOST_ENDIAN_CONSTEXPR endian_reverse_impl( std::uint64_t x ) BOOST_NOEXCEPT |
80 | 0 | { |
81 | 0 | #ifdef BOOST_ENDIAN_NO_INTRINSICS |
82 | 0 |
|
83 | 0 | std::uint64_t step32 = x << 32 | x >> 32; |
84 | 0 | std::uint64_t step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16 | (step32 & 0xFFFF0000FFFF0000ULL) >> 16; |
85 | 0 | return (step16 & 0x00FF00FF00FF00FFULL) << 8 | (step16 & 0xFF00FF00FF00FF00ULL) >> 8; |
86 | 0 |
|
87 | 0 | #else |
88 | 0 |
|
89 | 0 | return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x); |
90 | 0 |
|
91 | 0 | # endif |
92 | 0 | } |
93 | | |
94 | | #if defined(__SIZEOF_INT128__) |
95 | | |
96 | | inline __uint128_t BOOST_ENDIAN_CONSTEXPR endian_reverse_impl( __uint128_t x ) BOOST_NOEXCEPT |
97 | 0 | { |
98 | 0 | return endian_reverse_impl( static_cast<std::uint64_t>( x >> 64 ) ) | |
99 | 0 | static_cast<__uint128_t>( endian_reverse_impl( static_cast<std::uint64_t>( x ) ) ) << 64; |
100 | 0 | } |
101 | | |
102 | | #endif |
103 | | |
104 | | // is_endian_reversible |
105 | | |
106 | | template<class T> struct is_endian_reversible: std::integral_constant<bool, |
107 | | (is_integral<T>::value && !std::is_same<T, bool>::value) || is_scoped_enum<T>::value> |
108 | | { |
109 | | }; |
110 | | |
111 | | // is_endian_reversible_inplace |
112 | | |
113 | | template<class T> struct is_endian_reversible_inplace: std::integral_constant<bool, |
114 | | is_integral<T>::value || std::is_enum<T>::value || std::is_same<T, float>::value || std::is_same<T, double>::value> |
115 | | { |
116 | | }; |
117 | | |
118 | | } // namespace detail |
119 | | |
120 | | // Requires: |
121 | | // T is non-bool integral or scoped enumeration type |
122 | | |
123 | | template<class T> inline BOOST_CONSTEXPR |
124 | | typename std::enable_if< !std::is_class<T>::value, T >::type |
125 | | endian_reverse( T x ) BOOST_NOEXCEPT |
126 | | { |
127 | | BOOST_ENDIAN_STATIC_ASSERT( detail::is_endian_reversible<T>::value ); |
128 | | |
129 | | typedef typename detail::integral_by_size< sizeof(T) >::type uintN_t; |
130 | | |
131 | | return static_cast<T>( detail::endian_reverse_impl( static_cast<uintN_t>( x ) ) ); |
132 | | } |
133 | | |
134 | | // Requires: |
135 | | // T is integral, enumeration, float or double |
136 | | |
137 | | template<class T> inline |
138 | | typename std::enable_if< !std::is_class<T>::value >::type |
139 | | endian_reverse_inplace( T & x ) BOOST_NOEXCEPT |
140 | 0 | { |
141 | 0 | BOOST_ENDIAN_STATIC_ASSERT( detail::is_endian_reversible_inplace<T>::value ); |
142 | 0 |
|
143 | 0 | typename detail::integral_by_size< sizeof(T) >::type x2; |
144 | 0 |
|
145 | 0 | std::memcpy( &x2, &x, sizeof(T) ); |
146 | 0 |
|
147 | 0 | x2 = detail::endian_reverse_impl( x2 ); |
148 | 0 |
|
149 | 0 | std::memcpy( &x, &x2, sizeof(T) ); |
150 | 0 | } Unexecuted instantiation: _ZN5boost6endian22endian_reverse_inplaceItEENSt3__19enable_ifIXntsr3std8is_classIT_EE5valueEvE4typeERS4_ Unexecuted instantiation: _ZN5boost6endian22endian_reverse_inplaceIjEENSt3__19enable_ifIXntsr3std8is_classIT_EE5valueEvE4typeERS4_ Unexecuted instantiation: _ZN5boost6endian22endian_reverse_inplaceImEENSt3__19enable_ifIXntsr3std8is_classIT_EE5valueEvE4typeERS4_ |
151 | | |
152 | | // Default implementation for user-defined types |
153 | | |
154 | | template<class T> inline |
155 | | typename std::enable_if< std::is_class<T>::value >::type |
156 | | endian_reverse_inplace( T & x ) BOOST_NOEXCEPT |
157 | | { |
158 | | x = endian_reverse( x ); |
159 | | } |
160 | | |
161 | | // endian_reverse_inplace for arrays |
162 | | |
163 | | template<class T, std::size_t N> |
164 | | inline void endian_reverse_inplace( T (&x)[ N ] ) BOOST_NOEXCEPT |
165 | | { |
166 | | for( std::size_t i = 0; i < N; ++i ) |
167 | | { |
168 | | endian_reverse_inplace( x[i] ); |
169 | | } |
170 | | } |
171 | | |
172 | | } // namespace endian |
173 | | } // namespace boost |
174 | | |
175 | | #endif // BOOST_ENDIAN_DETAIL_ENDIAN_REVERSE_HPP_INCLUDED |