Coverage Report

Created: 2025-06-24 06:38

/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