2 Copyright 2011-2016 Beman Dawes
4 Distributed under the Boost Software License, Version 1.0.
5 (http://www.boost.org/LICENSE_1_0.txt)
9 # Endian Conversion Functions
10 :idprefix: conversion_
14 Header `boost/endian/conversion.hpp` provides byte order reversal and conversion
15 functions that convert objects of the built-in integer types between native,
16 big, or little endian byte ordering. User defined types are also supported.
20 Functions are implemented `inline` if appropriate. For {cpp}03 compilers,
21 `noexcept` is elided. Boost scoped enum emulation is used so that the library
22 still works for compilers that do not support scoped enums.
26 *Endianness* refers to the ordering of bytes within internal or external
27 integers and other arithmetic data. Most-significant byte first is called
28 *big endian* ordering. Least-significant byte first is called
29 *little endian* ordering. Other orderings are possible and some CPU
30 architectures support both big and little ordering.
32 NOTE: The names are derived from
33 http://en.wikipedia.org/wiki/Jonathan_Swift[Jonathan Swift]'s satirical novel
34 _http://en.wikipedia.org/wiki/Gulliver's_Travels[Gulliver's Travels]_, where
35 rival kingdoms opened their soft-boiled eggs at different ends. Wikipedia has an
36 extensive description of https://en.wikipedia.org/wiki/Endianness[Endianness].
38 The standard integral types ({cpp}std 3.9.1) except `bool` are collectively
39 called the *endian types*.
41 ### Header `<boost/endian/conversion.hpp>` Synopsis
45 #define BOOST_ENDIAN_INTRINSIC_MSG \
46 "`message describing presence or absence of intrinsics`"
59 // Byte reversal functions
61 template <class Endian>
62 Endian endian_reverse(Endian x) noexcept;
64 template <class EndianReversible>
65 EndianReversible big_to_native(EndianReversible x) noexcept;
66 template <class EndianReversible>
67 EndianReversible native_to_big(EndianReversible x) noexcept;
68 template <class EndianReversible>
69 EndianReversible little_to_native(EndianReversible x) noexcept;
70 template <class EndianReversible>
71 EndianReversible native_to_little(EndianReversible x) noexcept;
73 template <order O1, order O2, class EndianReversible>
74 EndianReversible conditional_reverse(EndianReversible x) noexcept;
75 template <class EndianReversible>
76 EndianReversible conditional_reverse(EndianReversible x,
77 order order1, order order2) noexcept;
79 // In-place byte reversal functions
81 template <class EndianReversible>
82 void endian_reverse_inplace(EndianReversible& x) noexcept;
84 template <class EndianReversibleInplace>
85 void big_to_native_inplace(EndianReversibleInplace& x) noexcept;
86 template <class EndianReversibleInplace>
87 void native_to_big_inplace(EndianReversibleInplace& x) noexcept;
88 template <class EndianReversibleInplace>
89 void little_to_native_inplace(EndianReversibleInplace& x) noexcept;
90 template <class EndianReversibleInplace>
91 void native_to_little_inplace(EndianReversibleInplace& x) noexcept;
93 template <order O1, order O2, class EndianReversibleInplace>
94 void conditional_reverse_inplace(EndianReversibleInplace& x) noexcept;
95 template <class EndianReversibleInplace>
96 void conditional_reverse_inplace(EndianReversibleInplace& x,
97 order order1, order order2) noexcept;
99 // Generic load and store functions
101 template<class T, std::size_t N, order Order>
102 T endian_load( unsigned char const * p ) noexcept;
104 template<class T, std::size_t N, order Order>
105 void endian_store( unsigned char * p, T const & v ) noexcept;
107 // Convenience load functions
109 boost::int16_t load_little_s16( unsigned char const * p ) noexcept;
110 boost::uint16_t load_little_u16( unsigned char const * p ) noexcept;
111 boost::int16_t load_big_s16( unsigned char const * p ) noexcept;
112 boost::uint16_t load_big_u16( unsigned char const * p ) noexcept;
114 boost::int32_t load_little_s24( unsigned char const * p ) noexcept;
115 boost::uint32_t load_little_u24( unsigned char const * p ) noexcept;
116 boost::int32_t load_big_s24( unsigned char const * p ) noexcept;
117 boost::uint32_t load_big_u24( unsigned char const * p ) noexcept;
119 boost::int32_t load_little_s32( unsigned char const * p ) noexcept;
120 boost::uint32_t load_little_u32( unsigned char const * p ) noexcept;
121 boost::int32_t load_big_s32( unsigned char const * p ) noexcept;
122 boost::uint32_t load_big_u32( unsigned char const * p ) noexcept;
124 boost::int64_t load_little_s40( unsigned char const * p ) noexcept;
125 boost::uint64_t load_little_u40( unsigned char const * p ) noexcept;
126 boost::int64_t load_big_s40( unsigned char const * p ) noexcept;
127 boost::uint64_t load_big_u40( unsigned char const * p ) noexcept;
129 boost::int64_t load_little_s48( unsigned char const * p ) noexcept;
130 boost::uint64_t load_little_u48( unsigned char const * p ) noexcept;
131 boost::int64_t load_big_s48( unsigned char const * p ) noexcept;
132 boost::uint64_t load_big_u48( unsigned char const * p ) noexcept;
134 boost::int64_t load_little_s56( unsigned char const * p ) noexcept;
135 boost::uint64_t load_little_u56( unsigned char const * p ) noexcept;
136 boost::int64_t load_big_s56( unsigned char const * p ) noexcept;
137 boost::uint64_t load_big_u56( unsigned char const * p ) noexcept;
139 boost::int64_t load_little_s64( unsigned char const * p ) noexcept;
140 boost::uint64_t load_little_u64( unsigned char const * p ) noexcept;
141 boost::int64_t load_big_s64( unsigned char const * p ) noexcept;
142 boost::uint64_t load_big_u64( unsigned char const * p ) noexcept;
144 // Convenience store functions
146 void store_little_s16( unsigned char * p, boost::int16_t v ) noexcept;
147 void store_little_u16( unsigned char * p, boost::uint16_t v ) noexcept;
148 void store_big_s16( unsigned char * p, boost::int16_t v ) noexcept;
149 void store_big_u16( unsigned char * p, boost::uint16_t v ) noexcept;
151 void store_little_s24( unsigned char * p, boost::int32_t v ) noexcept;
152 void store_little_u24( unsigned char * p, boost::uint32_t v ) noexcept;
153 void store_big_s24( unsigned char * p, boost::int32_t v ) noexcept;
154 void store_big_u24( unsigned char * p, boost::uint32_t v ) noexcept;
156 void store_little_s32( unsigned char * p, boost::int32_t v ) noexcept;
157 void store_little_u32( unsigned char * p, boost::uint32_t v ) noexcept;
158 void store_big_s32( unsigned char * p, boost::int32_t v ) noexcept;
159 void store_big_u32( unsigned char * p, boost::uint32_t v ) noexcept;
161 void store_little_s40( unsigned char * p, boost::int64_t v ) noexcept;
162 void store_little_u40( unsigned char * p, boost::uint64_t v ) noexcept;
163 void store_big_s40( unsigned char * p, boost::int64_t v ) noexcept;
164 void store_big_u40( unsigned char * p, boost::uint64_t v ) noexcept;
166 void store_little_s48( unsigned char * p, boost::int64_t v ) noexcept;
167 void store_little_u48( unsigned char * p, boost::uint64_t v ) noexcept;
168 void store_big_s48( unsigned char * p, boost::int64_t v ) noexcept;
169 void store_big_u48( unsigned char * p, boost::uint64_t v ) noexcept;
171 void store_little_s56( unsigned char * p, boost::int64_t v ) noexcept;
172 void store_little_u56( unsigned char * p, boost::uint64_t v ) noexcept;
173 void store_big_s56( unsigned char * p, boost::int64_t v ) noexcept;
174 void store_big_u56( unsigned char * p, boost::uint64_t v ) noexcept;
176 void store_little_s64( unsigned char * p, boost::int64_t v ) noexcept;
177 void store_little_u64( unsigned char * p, boost::uint64_t v ) noexcept;
178 void store_big_s64( unsigned char * p, boost::int64_t v ) noexcept;
179 void store_big_u64( unsigned char * p, boost::uint64_t v ) noexcept;
181 } // namespace endian
185 The values of `order::little` and `order::big` shall not be equal to one
188 The value of `order::native` shall be:
190 * equal to `order::big` if the execution environment is big endian, otherwise
191 * equal to `order::little` if the execution environment is little endian,
193 * unequal to both `order::little` and `order::big`.
197 #### Template argument requirements
199 The template definitions in the `boost/endian/conversion.hpp` header refer to
200 various named requirements whose details are set out in the tables in this
201 subsection. In these tables, `T` is an object or reference type to be supplied
202 by a {cpp} program instantiating a template; `x` is a value of type (possibly
203 `const`) `T`; `mlx` is a modifiable lvalue of type `T`.
205 [#conversion_endianreversible]
206 ##### EndianReversible requirements (in addition to `CopyConstructible`)
210 |Expression |Return |Requirements
211 |`endian_reverse(x)` |`T`
212 a|`T` is an endian type or a class type.
214 If `T` is an endian type, returns the value of `x` with the order of bytes
217 If `T` is a class type, the function:
219 * Returns the value of `x` with the order of bytes reversed for all data members
220 of types or arrays of types that meet the `EndianReversible` requirements, and;
221 * Is a non-member function in the same namespace as `T` that can be found by
222 argument dependent lookup (ADL).
225 [#conversion_endianreversibleinplace]
226 ##### EndianReversibleInplace requirements (in addition to `CopyConstructible`)
230 |Expression |Requirements
231 |`endian_reverse_inplace(mlx)`
232 a|`T` is an endian type or a class type.
234 If `T` is an endian type, reverses the order of bytes in `mlx`.
236 If `T` is a class type, the function:
238 * Reverses the order of bytes of all data members of `mlx` that have types or
239 arrays of types that meet the `EndianReversible` or `EndianReversibleInplace`
241 * Is a non-member function in the same namespace as `T` that can be found by
242 argument dependent lookup (ADL).
245 NOTE: Because there is a function template for `endian_reverse_inplace` that
246 calls `endian_reverse`, only `endian_reverse` is required for a user-defined
247 type to meet the `EndianReversibleInplace` requirements. Although User-defined
248 types are not required to supply an `endian_reverse_inplace` function, doing so
249 may improve efficiency.
251 #### Customization points for user-defined types (UDTs)
253 This subsection describes requirements on the Endian library's implementation.
255 The library's function templates requiring
256 `<<conversion_endianreversible,EndianReversible>>` are required to perform
257 reversal of endianness if needed by making an unqualified call to
260 The library's function templates requiring
261 `<<conversion_endianreversibleinplace,EndianReversibleInplace>>` are required to
262 perform reversal of endianness if needed by making an unqualified call to
263 `endian_reverse_inplace()`.
265 See `example/udt_conversion_example.cpp` for an example user-defined type.
267 ### Byte Reversal Functions
270 template <class Endian>
271 Endian endian_reverse(Endian x) noexcept;
276 Requires:: `Endian` must be a standard integral type that is not `bool`.
277 Returns:: `x`, with the order of its constituent bytes reversed.
280 template <class EndianReversible>
281 EndianReversible big_to_native(EndianReversible x) noexcept;
286 Returns:: `conditional_reverse<order::big, order::native>(x)`.
289 template <class EndianReversible>
290 EndianReversible native_to_big(EndianReversible x) noexcept;
295 Returns:: `conditional_reverse<order::native, order::big>(x)`.
298 template <class EndianReversible>
299 EndianReversible little_to_native(EndianReversible x) noexcept;
304 Returns:: `conditional_reverse<order::little, order::native>(x)`.
307 template <class EndianReversible>
308 EndianReversible native_to_little(EndianReversible x) noexcept;
313 Returns:: `conditional_reverse<order::native, order::little>(x)`.
316 template <order O1, order O2, class EndianReversible>
317 EndianReversible conditional_reverse(EndianReversible x) noexcept;
322 Returns:: `x` if `O1 == O2,` otherwise `endian_reverse(x)`.
323 Remarks:: Whether `x` or `endian_reverse(x)` is to be returned shall be
324 determined at compile time.
327 template <class EndianReversible>
328 EndianReversible conditional_reverse(EndianReversible x,
329 order order1, order order2) noexcept;
335 `order1 == order2? x: endian_reverse(x)`.
337 ### In-place Byte Reversal Functions
340 template <class EndianReversible>
341 void endian_reverse_inplace(EndianReversible& x) noexcept;
346 Effects:: `x = endian_reverse(x)`.
349 template <class EndianReversibleInplace>
350 void big_to_native_inplace(EndianReversibleInplace& x) noexcept;
355 Effects:: `conditional_reverse_inplace<order::big, order::native>(x)`.
358 template <class EndianReversibleInplace>
359 void native_to_big_inplace(EndianReversibleInplace& x) noexcept;
364 Effects:: `conditional_reverse_inplace<order::native, order::big>(x)`.
367 template <class EndianReversibleInplace>
368 void little_to_native_inplace(EndianReversibleInplace& x) noexcept;
373 Effects:: `conditional_reverse_inplace<order::little, order::native>(x)`.
376 template <class EndianReversibleInplace>
377 void native_to_little_inplace(EndianReversibleInplace& x) noexcept;
382 Effects:: `conditional_reverse_inplace<order::native, order::little>(x)`.
385 template <order O1, order O2, class EndianReversibleInplace>
386 void conditional_reverse_inplace(EndianReversibleInplace& x) noexcept;
391 Effects:: None if `O1 == O2,` otherwise `endian_reverse_inplace(x)`.
392 Remarks:: Which effect applies shall be determined at compile time.
395 template <class EndianReversibleInplace>
396 void conditional_reverse_inplace(EndianReversibleInplace& x,
397 order order1, order order2) noexcept;
403 If `order1 == order2` then `endian_reverse_inplace(x)`.
405 ### Generic Load and Store Functions
408 template<class T, std::size_t N, order Order>
409 T endian_load( unsigned char const * p ) noexcept;
414 Requires:: `sizeof(T)` must be 1, 2, 4, or 8. `N` must be between 1 and
415 `sizeof(T)`, inclusive. `T` must be trivially copyable. If `N` is not
416 equal to `sizeof(T)`, `T` must be integral or `enum`.
418 Effects:: Reads `N` bytes starting from `p`, in forward or reverse order
419 depending on whether `Order` matches the native endianness or not,
420 interprets the resulting bit pattern as a value of type `T`, and returns it.
421 If `sizeof(T)` is bigger than `N`, zero-extends when `T` is unsigned,
422 sign-extends otherwise.
425 template<class T, std::size_t N, order Order>
426 void endian_store( unsigned char * p, T const & v ) noexcept;
431 Requires:: `sizeof(T)` must be 1, 2, 4, or 8. `N` must be between 1 and
432 `sizeof(T)`, inclusive. `T` must be trivially copyable. If `N` is not
433 equal to `sizeof(T)`, `T` must be integral or `enum`.
435 Effects:: Writes to `p` the `N` least significant bytes from the object
436 representation of `v`, in forward or reverse order depending on whether
437 `Order` matches the native endianness or not.
439 ### Convenience Load Functions
442 inline boost::intM_t load_little_sN( unsigned char const * p ) noexcept;
447 Reads an N-bit signed little-endian integer from `p`.
449 Returns:: `endian_load<boost::intM_t, N/8, order::little>( p )`.
452 inline boost::uintM_t load_little_uN( unsigned char const * p ) noexcept;
457 Reads an N-bit unsigned little-endian integer from `p`.
459 Returns:: `endian_load<boost::uintM_t, N/8, order::little>( p )`.
462 inline boost::intM_t load_big_sN( unsigned char const * p ) noexcept;
467 Reads an N-bit signed big-endian integer from `p`.
469 Returns:: `endian_load<boost::intM_t, N/8, order::big>( p )`.
472 inline boost::uintM_t load_big_uN( unsigned char const * p ) noexcept;
477 Reads an N-bit unsigned big-endian integer from `p`.
480 `endian_load<boost::uintM_t, N/8, order::big>( p )`.
482 ### Convenience Store Functions
485 inline void store_little_sN( unsigned char * p, boost::intM_t v ) noexcept;
490 Writes an N-bit signed little-endian integer to `p`.
492 Effects:: `endian_store<boost::intM_t, N/8, order::little>( p, v )`.
495 inline void store_little_uN( unsigned char * p, boost::uintM_t v ) noexcept;
500 Writes an N-bit unsigned little-endian integer to `p`.
502 Effects:: `endian_store<boost::uintM_t, N/8, order::little>( p, v )`.
505 inline void store_big_sN( unsigned char * p, boost::intM_t v ) noexcept;
510 Writes an N-bit signed big-endian integer to `p`.
512 Effects:: `endian_store<boost::intM_t, N/8, order::big>( p, v )`.
515 inline void store_big_uN( unsigned char * p, boost::uintM_t v ) noexcept;
520 Writes an N-bit unsigned big-endian integer to `p`.
523 `endian_store<boost::uintM_t, N/8, order::big>( p, v )`.
527 See the <<overview_faq,Overview FAQ>> for a library-wide FAQ.
529 *Why are both value returning and modify-in-place functions provided?*
531 * Returning the result by value is the standard C and {cpp} idiom for functions
532 that compute a value from an argument. Modify-in-place functions allow cleaner
533 code in many real-world endian use cases and are more efficient for user-defined
534 types that have members such as string data that do not need to be reversed.
535 Thus both forms are provided.
537 *Why not use the Linux names (htobe16, htole16, be16toh, le16toh, etc.) ?*
539 * Those names are non-standard and vary even between POSIX-like operating
540 systems. A {cpp} library TS was going to use those names, but found they were
541 sometimes implemented as macros. Since macros do not respect scoping and
542 namespace rules, to use them would be very error prone.
546 Tomas Puverle was instrumental in identifying and articulating the need to
547 support endian conversion as separate from endian integer types. Phil Endecott
548 suggested the form of the value returning signatures. Vicente Botet and other
549 reviewers suggested supporting user defined types. General reverse template
550 implementation approach using `std::reverse` suggested by Mathias Gaunard.
551 Portable implementation approach for 16, 32, and 64-bit integers suggested by
552 tymofey, with avoidance of undefined behavior as suggested by Giovanni Piero
553 Deretta, and a further refinement suggested by Pyry Jahkola. Intrinsic builtins
554 implementation approach for 16, 32, and 64-bit integers suggested by several
555 reviewers, and by David Stone, who provided his Boost licensed macro
556 implementation that became the starting point for
557 `boost/endian/detail/intrinsic.hpp`. Pierre Talbot provided the
558 `int8_t endian_reverse()` and templated `endian_reverse_inplace()`