1 // boost/endian/conversion.hpp -------------------------------------------------------//
3 // Copyright Beman Dawes 2010, 2011, 2014
5 // Distributed under the Boost Software License, Version 1.0.
6 // http://www.boost.org/LICENSE_1_0.txt
8 #ifndef BOOST_ENDIAN_CONVERSION_HPP
9 #define BOOST_ENDIAN_CONVERSION_HPP
11 #include <boost/endian/detail/endian_reverse.hpp>
12 #include <boost/endian/detail/endian_load.hpp>
13 #include <boost/endian/detail/endian_store.hpp>
14 #include <boost/endian/detail/order.hpp>
15 #include <boost/type_traits/is_class.hpp>
16 #include <boost/type_traits/is_array.hpp>
17 #include <boost/type_traits/integral_constant.hpp>
18 #include <boost/static_assert.hpp>
19 #include <boost/cstdint.hpp>
20 #include <boost/config.hpp>
22 //------------------------------------- synopsis ---------------------------------------//
29 //--------------------------------------------------------------------------------------//
31 // return-by-value interfaces //
32 // suggested by Phil Endecott //
34 // user-defined types (UDTs) //
36 // All return-by-value conversion function templates are required to be implemented in //
37 // terms of an unqualified call to "endian_reverse(x)", a function returning the //
38 // value of x with endianness reversed. This provides a customization point for any //
39 // UDT that provides a "endian_reverse" free-function meeting the requirements. //
40 // It must be defined in the same namespace as the UDT itself so that it will be found //
41 // by argument dependent lookup (ADL). //
43 //--------------------------------------------------------------------------------------//
46 // requires T to be a non-bool integral type
47 // in detail/endian_reverse.hpp
49 // template<class T> inline BOOST_CONSTEXPR T endian_reverse( T x ) BOOST_NOEXCEPT;
51 // reverse byte order unless native endianness is big
52 template <class EndianReversible >
53 inline BOOST_CONSTEXPR EndianReversible big_to_native(EndianReversible x) BOOST_NOEXCEPT;
54 // Returns: x if native endian order is big, otherwise endian_reverse(x)
55 template <class EndianReversible >
56 inline BOOST_CONSTEXPR EndianReversible native_to_big(EndianReversible x) BOOST_NOEXCEPT;
57 // Returns: x if native endian order is big, otherwise endian_reverse(x)
59 // reverse byte order unless native endianness is little
60 template <class EndianReversible >
61 inline BOOST_CONSTEXPR EndianReversible little_to_native(EndianReversible x) BOOST_NOEXCEPT;
62 // Returns: x if native endian order is little, otherwise endian_reverse(x)
63 template <class EndianReversible >
64 inline BOOST_CONSTEXPR EndianReversible native_to_little(EndianReversible x) BOOST_NOEXCEPT;
65 // Returns: x if native endian order is little, otherwise endian_reverse(x)
67 // generic conditional reverse byte order
68 template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
69 class EndianReversible>
70 inline BOOST_CONSTEXPR EndianReversible conditional_reverse(EndianReversible from) BOOST_NOEXCEPT;
71 // Returns: If From == To have different values, from.
72 // Otherwise endian_reverse(from).
73 // Remarks: The From == To test, and as a consequence which form the return takes, is
74 // is determined at compile time.
76 // runtime conditional reverse byte order
77 template <class EndianReversible >
78 inline BOOST_CONSTEXPR EndianReversible conditional_reverse(EndianReversible from,
79 BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order)
81 // Returns: from_order == to_order ? from : endian_reverse(from).
83 //------------------------------------------------------------------------------------//
86 // Q: What happened to bswap, htobe, and the other synonym functions based on names
87 // popularized by BSD, OS X, and Linux?
88 // A: Turned out these may be implemented as macros on some systems. Ditto POSIX names
89 // for such functionality. Since macros would cause endless problems with functions
90 // of the same names, and these functions are just synonyms anyhow, they have been
94 //------------------------------------------------------------------------------------//
96 // reverse in place interfaces //
98 // user-defined types (UDTs) //
100 // All reverse in place function templates are required to be implemented in terms //
101 // of an unqualified call to "endian_reverse_inplace(x)", a function reversing //
102 // the endianness of x, which is a non-const reference. This provides a //
103 // customization point for any UDT that provides a "reverse_inplace" free-function //
104 // meeting the requirements. The free-function must be declared in the same //
105 // namespace as the UDT itself so that it will be found by argument-dependent //
108 //------------------------------------------------------------------------------------//
111 // in detail/endian_reverse.hpp
113 // template <class EndianReversible>
114 // inline void endian_reverse_inplace(EndianReversible& x) BOOST_NOEXCEPT;
116 // Effects: x = endian_reverse(x)
118 // reverse in place unless native endianness is big
119 template <class EndianReversibleInplace>
120 inline void big_to_native_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
121 // Effects: none if native byte-order is big, otherwise endian_reverse_inplace(x)
122 template <class EndianReversibleInplace>
123 inline void native_to_big_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
124 // Effects: none if native byte-order is big, otherwise endian_reverse_inplace(x)
126 // reverse in place unless native endianness is little
127 template <class EndianReversibleInplace>
128 inline void little_to_native_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
129 // Effects: none if native byte-order is little, otherwise endian_reverse_inplace(x);
130 template <class EndianReversibleInplace>
131 inline void native_to_little_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
132 // Effects: none if native byte-order is little, otherwise endian_reverse_inplace(x);
134 // generic conditional reverse in place
135 template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
136 class EndianReversibleInplace>
137 inline void conditional_reverse_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
139 // runtime reverse in place
140 template <class EndianReversibleInplace>
141 inline void conditional_reverse_inplace(EndianReversibleInplace& x,
142 BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order)
145 //----------------------------------- end synopsis -------------------------------------//
147 template <class EndianReversible>
148 inline BOOST_CONSTEXPR EndianReversible big_to_native( EndianReversible x ) BOOST_NOEXCEPT
150 return boost::endian::conditional_reverse<order::big, order::native>( x );
153 template <class EndianReversible>
154 inline BOOST_CONSTEXPR EndianReversible native_to_big( EndianReversible x ) BOOST_NOEXCEPT
156 return boost::endian::conditional_reverse<order::native, order::big>( x );
159 template <class EndianReversible>
160 inline BOOST_CONSTEXPR EndianReversible little_to_native( EndianReversible x ) BOOST_NOEXCEPT
162 return boost::endian::conditional_reverse<order::little, order::native>( x );
165 template <class EndianReversible>
166 inline BOOST_CONSTEXPR EndianReversible native_to_little( EndianReversible x ) BOOST_NOEXCEPT
168 return boost::endian::conditional_reverse<order::native, order::little>( x );
174 template<class EndianReversible>
175 inline BOOST_CONSTEXPR EndianReversible conditional_reverse_impl( EndianReversible x, boost::true_type ) BOOST_NOEXCEPT
180 template<class EndianReversible>
181 inline BOOST_CONSTEXPR EndianReversible conditional_reverse_impl( EndianReversible x, boost::false_type ) BOOST_NOEXCEPT
183 return endian_reverse( x );
186 } // namespace detail
188 // generic conditional reverse
189 template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To, class EndianReversible>
190 inline BOOST_CONSTEXPR EndianReversible conditional_reverse( EndianReversible x ) BOOST_NOEXCEPT
192 BOOST_STATIC_ASSERT( boost::is_class<EndianReversible>::value || detail::is_endian_reversible<EndianReversible>::value );
193 return detail::conditional_reverse_impl( x, boost::integral_constant<bool, From == To>() );
196 // runtime conditional reverse
197 template <class EndianReversible>
198 inline BOOST_CONSTEXPR EndianReversible conditional_reverse( EndianReversible x,
199 BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order ) BOOST_NOEXCEPT
201 BOOST_STATIC_ASSERT( boost::is_class<EndianReversible>::value || detail::is_endian_reversible<EndianReversible>::value );
202 return from_order == to_order? x: endian_reverse( x );
205 //--------------------------------------------------------------------------------------//
206 // reverse-in-place implementation //
207 //--------------------------------------------------------------------------------------//
209 template <class EndianReversibleInplace>
210 inline void big_to_native_inplace( EndianReversibleInplace& x ) BOOST_NOEXCEPT
212 boost::endian::conditional_reverse_inplace<order::big, order::native>( x );
215 template <class EndianReversibleInplace>
216 inline void native_to_big_inplace( EndianReversibleInplace& x ) BOOST_NOEXCEPT
218 boost::endian::conditional_reverse_inplace<order::native, order::big>( x );
221 template <class EndianReversibleInplace>
222 inline void little_to_native_inplace( EndianReversibleInplace& x ) BOOST_NOEXCEPT
224 boost::endian::conditional_reverse_inplace<order::little, order::native>( x );
227 template <class EndianReversibleInplace>
228 inline void native_to_little_inplace( EndianReversibleInplace& x ) BOOST_NOEXCEPT
230 boost::endian::conditional_reverse_inplace<order::native, order::little>( x );
236 template<class EndianReversibleInplace>
237 inline void conditional_reverse_inplace_impl( EndianReversibleInplace&, boost::true_type ) BOOST_NOEXCEPT
241 template<class EndianReversibleInplace>
242 inline void conditional_reverse_inplace_impl( EndianReversibleInplace& x, boost::false_type ) BOOST_NOEXCEPT
244 endian_reverse_inplace( x );
247 } // namespace detail
249 // generic conditional reverse in place
250 template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To, class EndianReversibleInplace>
251 inline void conditional_reverse_inplace( EndianReversibleInplace& x ) BOOST_NOEXCEPT
254 boost::is_class<EndianReversibleInplace>::value ||
255 boost::is_array<EndianReversibleInplace>::value ||
256 detail::is_endian_reversible_inplace<EndianReversibleInplace>::value );
258 detail::conditional_reverse_inplace_impl( x, boost::integral_constant<bool, From == To>() );
261 // runtime reverse in place
262 template <class EndianReversibleInplace>
263 inline void conditional_reverse_inplace( EndianReversibleInplace& x,
264 BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order ) BOOST_NOEXCEPT
267 boost::is_class<EndianReversibleInplace>::value ||
268 boost::is_array<EndianReversibleInplace>::value ||
269 detail::is_endian_reversible_inplace<EndianReversibleInplace>::value );
271 if( from_order != to_order )
273 endian_reverse_inplace( x );
277 // load/store convenience functions
281 inline boost::int16_t load_little_s16( unsigned char const * p ) BOOST_NOEXCEPT
283 return boost::endian::endian_load<boost::int16_t, 2, order::little>( p );
286 inline boost::uint16_t load_little_u16( unsigned char const * p ) BOOST_NOEXCEPT
288 return boost::endian::endian_load<boost::uint16_t, 2, order::little>( p );
291 inline boost::int16_t load_big_s16( unsigned char const * p ) BOOST_NOEXCEPT
293 return boost::endian::endian_load<boost::int16_t, 2, order::big>( p );
296 inline boost::uint16_t load_big_u16( unsigned char const * p ) BOOST_NOEXCEPT
298 return boost::endian::endian_load<boost::uint16_t, 2, order::big>( p );
303 inline boost::int32_t load_little_s24( unsigned char const * p ) BOOST_NOEXCEPT
305 return boost::endian::endian_load<boost::int32_t, 3, order::little>( p );
308 inline boost::uint32_t load_little_u24( unsigned char const * p ) BOOST_NOEXCEPT
310 return boost::endian::endian_load<boost::uint32_t, 3, order::little>( p );
313 inline boost::int32_t load_big_s24( unsigned char const * p ) BOOST_NOEXCEPT
315 return boost::endian::endian_load<boost::int32_t, 3, order::big>( p );
318 inline boost::uint32_t load_big_u24( unsigned char const * p ) BOOST_NOEXCEPT
320 return boost::endian::endian_load<boost::uint32_t, 3, order::big>( p );
325 inline boost::int32_t load_little_s32( unsigned char const * p ) BOOST_NOEXCEPT
327 return boost::endian::endian_load<boost::int32_t, 4, order::little>( p );
330 inline boost::uint32_t load_little_u32( unsigned char const * p ) BOOST_NOEXCEPT
332 return boost::endian::endian_load<boost::uint32_t, 4, order::little>( p );
335 inline boost::int32_t load_big_s32( unsigned char const * p ) BOOST_NOEXCEPT
337 return boost::endian::endian_load<boost::int32_t, 4, order::big>( p );
340 inline boost::uint32_t load_big_u32( unsigned char const * p ) BOOST_NOEXCEPT
342 return boost::endian::endian_load<boost::uint32_t, 4, order::big>( p );
347 inline boost::int64_t load_little_s40( unsigned char const * p ) BOOST_NOEXCEPT
349 return boost::endian::endian_load<boost::int64_t, 5, order::little>( p );
352 inline boost::uint64_t load_little_u40( unsigned char const * p ) BOOST_NOEXCEPT
354 return boost::endian::endian_load<boost::uint64_t, 5, order::little>( p );
357 inline boost::int64_t load_big_s40( unsigned char const * p ) BOOST_NOEXCEPT
359 return boost::endian::endian_load<boost::int64_t, 5, order::big>( p );
362 inline boost::uint64_t load_big_u40( unsigned char const * p ) BOOST_NOEXCEPT
364 return boost::endian::endian_load<boost::uint64_t, 5, order::big>( p );
369 inline boost::int64_t load_little_s48( unsigned char const * p ) BOOST_NOEXCEPT
371 return boost::endian::endian_load<boost::int64_t, 6, order::little>( p );
374 inline boost::uint64_t load_little_u48( unsigned char const * p ) BOOST_NOEXCEPT
376 return boost::endian::endian_load<boost::uint64_t, 6, order::little>( p );
379 inline boost::int64_t load_big_s48( unsigned char const * p ) BOOST_NOEXCEPT
381 return boost::endian::endian_load<boost::int64_t, 6, order::big>( p );
384 inline boost::uint64_t load_big_u48( unsigned char const * p ) BOOST_NOEXCEPT
386 return boost::endian::endian_load<boost::uint64_t, 6, order::big>( p );
391 inline boost::int64_t load_little_s56( unsigned char const * p ) BOOST_NOEXCEPT
393 return boost::endian::endian_load<boost::int64_t, 7, order::little>( p );
396 inline boost::uint64_t load_little_u56( unsigned char const * p ) BOOST_NOEXCEPT
398 return boost::endian::endian_load<boost::uint64_t, 7, order::little>( p );
401 inline boost::int64_t load_big_s56( unsigned char const * p ) BOOST_NOEXCEPT
403 return boost::endian::endian_load<boost::int64_t, 7, order::big>( p );
406 inline boost::uint64_t load_big_u56( unsigned char const * p ) BOOST_NOEXCEPT
408 return boost::endian::endian_load<boost::uint64_t, 7, order::big>( p );
413 inline boost::int64_t load_little_s64( unsigned char const * p ) BOOST_NOEXCEPT
415 return boost::endian::endian_load<boost::int64_t, 8, order::little>( p );
418 inline boost::uint64_t load_little_u64( unsigned char const * p ) BOOST_NOEXCEPT
420 return boost::endian::endian_load<boost::uint64_t, 8, order::little>( p );
423 inline boost::int64_t load_big_s64( unsigned char const * p ) BOOST_NOEXCEPT
425 return boost::endian::endian_load<boost::int64_t, 8, order::big>( p );
428 inline boost::uint64_t load_big_u64( unsigned char const * p ) BOOST_NOEXCEPT
430 return boost::endian::endian_load<boost::uint64_t, 8, order::big>( p );
435 inline void store_little_s16( unsigned char * p, boost::int16_t v )
437 boost::endian::endian_store<boost::int16_t, 2, order::little>( p, v );
440 inline void store_little_u16( unsigned char * p, boost::uint16_t v )
442 boost::endian::endian_store<boost::uint16_t, 2, order::little>( p, v );
445 inline void store_big_s16( unsigned char * p, boost::int16_t v )
447 boost::endian::endian_store<boost::int16_t, 2, order::big>( p, v );
450 inline void store_big_u16( unsigned char * p, boost::uint16_t v )
452 boost::endian::endian_store<boost::uint16_t, 2, order::big>( p, v );
457 inline void store_little_s24( unsigned char * p, boost::int32_t v )
459 boost::endian::endian_store<boost::int32_t, 3, order::little>( p, v );
462 inline void store_little_u24( unsigned char * p, boost::uint32_t v )
464 boost::endian::endian_store<boost::uint32_t, 3, order::little>( p, v );
467 inline void store_big_s24( unsigned char * p, boost::int32_t v )
469 boost::endian::endian_store<boost::int32_t, 3, order::big>( p, v );
472 inline void store_big_u24( unsigned char * p, boost::uint32_t v )
474 boost::endian::endian_store<boost::uint32_t, 3, order::big>( p, v );
479 inline void store_little_s32( unsigned char * p, boost::int32_t v )
481 boost::endian::endian_store<boost::int32_t, 4, order::little>( p, v );
484 inline void store_little_u32( unsigned char * p, boost::uint32_t v )
486 boost::endian::endian_store<boost::uint32_t, 4, order::little>( p, v );
489 inline void store_big_s32( unsigned char * p, boost::int32_t v )
491 boost::endian::endian_store<boost::int32_t, 4, order::big>( p, v );
494 inline void store_big_u32( unsigned char * p, boost::uint32_t v )
496 boost::endian::endian_store<boost::uint32_t, 4, order::big>( p, v );
501 inline void store_little_s40( unsigned char * p, boost::int64_t v )
503 boost::endian::endian_store<boost::int64_t, 5, order::little>( p, v );
506 inline void store_little_u40( unsigned char * p, boost::uint64_t v )
508 boost::endian::endian_store<boost::uint64_t, 5, order::little>( p, v );
511 inline void store_big_s40( unsigned char * p, boost::int64_t v )
513 boost::endian::endian_store<boost::int64_t, 5, order::big>( p, v );
516 inline void store_big_u40( unsigned char * p, boost::uint64_t v )
518 boost::endian::endian_store<boost::uint64_t, 5, order::big>( p, v );
523 inline void store_little_s48( unsigned char * p, boost::int64_t v )
525 boost::endian::endian_store<boost::int64_t, 6, order::little>( p, v );
528 inline void store_little_u48( unsigned char * p, boost::uint64_t v )
530 boost::endian::endian_store<boost::uint64_t, 6, order::little>( p, v );
533 inline void store_big_s48( unsigned char * p, boost::int64_t v )
535 boost::endian::endian_store<boost::int64_t, 6, order::big>( p, v );
538 inline void store_big_u48( unsigned char * p, boost::uint64_t v )
540 boost::endian::endian_store<boost::uint64_t, 6, order::big>( p, v );
545 inline void store_little_s56( unsigned char * p, boost::int64_t v )
547 boost::endian::endian_store<boost::int64_t, 7, order::little>( p, v );
550 inline void store_little_u56( unsigned char * p, boost::uint64_t v )
552 boost::endian::endian_store<boost::uint64_t, 7, order::little>( p, v );
555 inline void store_big_s56( unsigned char * p, boost::int64_t v )
557 boost::endian::endian_store<boost::int64_t, 7, order::big>( p, v );
560 inline void store_big_u56( unsigned char * p, boost::uint64_t v )
562 boost::endian::endian_store<boost::uint64_t, 7, order::big>( p, v );
567 inline void store_little_s64( unsigned char * p, boost::int64_t v )
569 boost::endian::endian_store<boost::int64_t, 8, order::little>( p, v );
572 inline void store_little_u64( unsigned char * p, boost::uint64_t v )
574 boost::endian::endian_store<boost::uint64_t, 8, order::little>( p, v );
577 inline void store_big_s64( unsigned char * p, boost::int64_t v )
579 boost::endian::endian_store<boost::int64_t, 8, order::big>( p, v );
582 inline void store_big_u64( unsigned char * p, boost::uint64_t v )
584 boost::endian::endian_store<boost::uint64_t, 8, order::big>( p, v );
587 } // namespace endian
590 #endif // BOOST_ENDIAN_CONVERSION_HPP