...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Endian Home Conversion Functions Arithmetic Types Buffer Types Choosing Approach |
Contents |
Introduction Reference Synopsis Requirements EndianReversible Customization for UDTs Functions FAQ Acknowledgements |
Header boost/endian/conversion.hpp provides byte order reversal and conversion functions that convert objects of the built-in integer types between native, big, or little endian byte ordering. User defined types are also supported.
Functions are implemented inline
if appropriate.
For C++03 compilers, noexcept
is
elided.
Boost scoped enum emulation is used so that the library still works for compilers that do not support scoped enums.
Endianness refers to the ordering of bytes within internal or external integers and other arithmetic data. Most-significant byte first is called big endian ordering. Least-significant byte first is called little endian ordering. Other orderings are possible and some CPU architectures support both big and little ordering.
[Note: The names are derived from Jonathan Swift's satirical novel Gulliver’s Travels, where rival kingdoms opened their soft-boiled eggs at different ends. Wikipedia has an extensive description of Endianness. —end note]
The standard integral types (C++std 3.9.1) except bool
are collectively called the endian types.
<boost/endian/conversion.hpp>
Synopsis#define BOOST_ENDIAN_INTRINSIC_MSG \ "message describing presence or absence of intrinsics" namespace boost { namespace endian { enum class order { native = see below, big = see below, little = see below, }; int8_t endian_reverse(int8_t x) noexcept; int16_t endian_reverse(int16_t x) noexcept; int32_t endian_reverse(int32_t x) noexcept; int64_t endian_reverse(int64_t x) noexcept; uint8_t endian_reverse(uint8_t x) noexcept; uint16_t endian_reverse(uint16_t x) noexcept; uint32_t endian_reverse(uint32_t x) noexcept; uint64_t endian_reverse(uint64_t x) noexcept; template <class EndianReversible> EndianReversible big_to_native(EndianReversible x) noexcept; template <class EndianReversible> EndianReversible native_to_big(EndianReversible x) noexcept; template <class EndianReversible> EndianReversible little_to_native(EndianReversible x) noexcept; template <class EndianReversible> EndianReversible native_to_little(EndianReversible x) noexcept; template <order O1, order O2, class EndianReversible> EndianReversible conditional_reverse(EndianReversible x) noexcept; template <class EndianReversible> EndianReversible conditional_reverse(EndianReversible x, order order1, order order2) noexcept; template <class EndianReversible> void endian_reverse_inplace(EndianReversible& x) noexcept; template <class EndianReversibleInplace> void big_to_native_inplace(EndianReversibleInplace& x) noexcept; template <class EndianReversibleInplace> void native_to_big_inplace(EndianReversibleInplace& x) noexcept; template <class EndianReversibleInplace> void little_to_native_inplace(EndianReversibleInplace& x) noexcept; template <class EndianReversibleInplace> void native_to_little_inplace(EndianReversibleInplace& x) noexcept; template <order O1, order O2, class EndianReversibleInplace> void conditional_reverse_inplace(EndianReversibleInplace& x) noexcept; template <class EndianReversibleInplace> void conditional_reverse_inplace(EndianReversibleInplace& x, order order1, order order2) noexcept; } // namespace endian } // namespace boost
The values of order::little
and order::big
shall
not be equal to one another.
The value of order::native
shall be:
order::big
if the execution environment is big
endian, otherwiseorder::little
if the execution environment is little
endian, otherwiseorder::little
and order::big
.The template definitions in the boost/endian/conversion.hpp
header refer to various named requirements whose details are set out in the
tables in this subsection. In these tables, T
is an object or
reference type to be supplied by a C++ program instantiating a template; x
is a value of type (possibly const
) T
; mlx
is a
modifiable lvalue of type T
.
EndianReversible
requirements (in addition to CopyConstructible ) |
||
Expression | Return type |
Requirements |
endian_reverse(x) |
T |
T is an endian type or a class type.If If
|
EndianReversibleInplace
requirements (in addition to CopyConstructible ) |
|
Expression | Requirements |
endian_reverse_inplace(mlx) |
T is an endian type or a class type.If If
|
[Note: Because there is a function template for endian_reverse_inplace
that calls endian_reverse
, only endian_reverse
is required for a user-defined type to meet the EndianReversibleInplace
requirements. Although User-defined types are not required to supply an endian_reverse_inplace
function, doing so may improve efficiency. —end note]
This subsection describes requirements on the Endian library's implementation.
The library's function templates requiring
EndianReversible
are
required to perform reversal of endianness if needed by making an unqualified
call to endian_reverse()
.
The library's function templates requiring
EndianReversibleInplace
are required to perform reversal of endianness if needed by making an
unqualified call to endian_reverse_inplace()
.
See example/udt_conversion_example.cpp
for an example user-defined type.
int8_t endian_reverse(int8_t x) noexcept; int16_t endian_reverse(int16_t x) noexcept; int32_t endian_reverse(int32_t x) noexcept; int64_t endian_reverse(int64_t x) noexcept; uint8_t endian_reverse(uint8_t x) noexcept; uint16_t endian_reverse(uint16_t x) noexcept; uint32_t endian_reverse(uint32_t x) noexcept; uint64_t endian_reverse(uint64_t x) noexcept;
Returns:
x
, with the order of its constituent bytes reversed.Remarks: The type of
x
meets theEndianReversible
requirements.[Note: The Boost.Endian library does not provide overloads for the C++ standard library supplied types. —end note]
template <class EndianReversible> EndianReversible big_to_native(EndianReversible x) noexcept;
Returns:
conditional_reverse<order::big, order::native>(x)
.
template <class EndianReversible> EndianReversible native_to_big(EndianReversible x) noexcept;
Returns:
conditional_reverse<order::native, order::big>(x)
.
template <class EndianReversible> EndianReversible little_to_native(EndianReversible x) noexcept;
Returns:
conditional_reverse<order::little, order::native>(x)
.
template <class EndianReversible> EndianReversible native_to_little(EndianReversible x) noexcept;
Returns:
conditional_reverse<order::native, order::little>(x)
.
template <order O1, order O2, class EndianReversible> EndianReversible conditional_reverse(EndianReversible x) noexcept;
Returns:
x
ifO1 == O2,
otherwiseendian_reverse(x)
.Remarks: Whether
x
orendian_reverse(x)
is to be returned shall be determined at compile time.
template <class EndianReversible> EndianReversible conditional_reverse(EndianReversible x, order order1, order order2) noexcept;
Returns:
order1 == order2 ? x : endian_reverse(x)
.
template <class EndianReversible> void endian_reverse_inplace(EndianReversible& x) noexcept;
Effects:
x
= endian_reverse(x)
.
template <class EndianReversibleInplace> void big_to_native_inplace(EndianReversibleInplace& x) noexcept;
Effects:
conditional_reverse_inplace<order::big, order::native>(x)
.
template <class EndianReversibleInplace> void native_to_big_inplace(EndianReversibleInplace& x) noexcept;
Effects:
conditional_reverse_inplace<order::native, order::big>(x)
.
template <class EndianReversibleInplace> void little_to_native_inplace(EndianReversibleInplace& x) noexcept;
Effects:
conditional_reverse_inplace<order::little, order::native>(x)
.
template <class EndianReversibleInplace> void native_to_little_inplace(EndianReversibleInplace& x) noexcept;
Effects:
conditional_reverse_inplace<order::native, order::little>(x)
.
template <order O1, order O2, class EndianReversibleInplace> void conditional_reverse_inplace(EndianReversibleInplace& x) noexcept;
Effects: None if
O1 == O2,
otherwiseendian_reverse_inplace(x)
.Remarks: Which effect applies shall be determined at compile time.
template <class EndianReversibleInplace> void conditional_reverse_inplace(EndianReversibleInplace& x, order order1, order order2) noexcept;
Effects: If
order1 == order2
thenendian_reverse_inplace(x)
.
See the Endian home page FAQ for a library-wide FAQ.
Why are both value returning and modify-in-place functions provided?
Returning the result by value is the standard C and C++ idiom for functions that compute a value from an argument. Modify-in-place functions allow cleaner code in many real-world endian use cases and are more efficient for user-defined types that have members such as string data that do not need to be reversed. Thus both forms are provided.
Why are exact-length 8, 16, 32, and 64-bit integers supported rather than the built-in char, short, int, long, long long, etc?
The primary use case, portable file or network data, needs these de facto standard sizes. Using types that vary with the platform would greatly limit portability for both programs and data.
Why not use the Linux names (htobe16, htole16, be16toh, le16toh, etc.) ?
Those names are non-standard and vary even between POSIX-like operating systems. A C++ library TS was going to use those names, but found they were sometimes implemented as macros. Since macros do not respect scoping and namespace rules, to use them would be very error prone.
Tomas Puverle was instrumental
in identifying and articulating the need to support endian conversion as separate from
endian integer types. Phil Endecott suggested the form of the value returning signatures.
Vicente Botet and other reviewers suggested supporting user defined types.
General reverse template implementation approach using std::reverse suggested by Mathias Gaunard.
Portable implementation approach for 16, 32, and 64-bit integers suggested by tymofey,
with avoidance of undefined behavior as suggested by Giovanni Piero Deretta,
and a further refinement suggested by Pyry Jahkola.
Intrinsic builtins implementation approach for 16, 32, and 64-bit integers suggested by
several reviewers, and by David Stone, who provided his Boost licensed macro implementation
that became the starting point for boost/endian/detail/intrinsic.hpp
.
Pierre Talbot provided the int8_t endian_reverse()
and templated
endian_reverse_inplace()
implementations.
Last revised: 14 October, 2015
© Copyright Beman Dawes, 2011, 2013
Distributed under the Boost Software License, Version 1.0. See www.boost.org/ LICENSE_1_0.txt