forked from boostorg/endian
Convert Endian Conversion Functions to asciidoc
This commit is contained in:
@ -18,6 +18,8 @@ Beman Dawes
|
|||||||
|
|
||||||
include::endian/overview.adoc[]
|
include::endian/overview.adoc[]
|
||||||
|
|
||||||
|
include::endian/conversion.adoc[]
|
||||||
|
|
||||||
include::endian/choosing_approach.adoc[]
|
include::endian/choosing_approach.adoc[]
|
||||||
|
|
||||||
include::endian/mini_review_topics.adoc[]
|
include::endian/mini_review_topics.adoc[]
|
||||||
|
341
doc/endian/conversion.adoc
Normal file
341
doc/endian/conversion.adoc
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
////
|
||||||
|
Copyright 2011-2016 Beman Dawes
|
||||||
|
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
////
|
||||||
|
|
||||||
|
[#conversion]
|
||||||
|
# Endian Conversion Functions
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
Functions are implemented `inline` if appropriate. For {cpp}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.
|
||||||
|
|
||||||
|
### Definitions
|
||||||
|
|
||||||
|
*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
|
||||||
|
http://en.wikipedia.org/wiki/Jonathan_Swift[Jonathan Swift]'s satirical novel
|
||||||
|
_http://en.wikipedia.org/wiki/Gulliver's_Travels[Gulliver's Travels]_, where
|
||||||
|
rival kingdoms opened their soft-boiled eggs at different ends. Wikipedia has an
|
||||||
|
extensive description of https://en.wikipedia.org/wiki/Endianness[Endianness].
|
||||||
|
|
||||||
|
The standard integral types ({cpp}std 3.9.1) except `bool` are collectively
|
||||||
|
called the *endian types*.
|
||||||
|
|
||||||
|
### Header `<boost/endian/conversion.hpp>` Synopsis
|
||||||
|
|
||||||
|
[subs=+quotes]
|
||||||
|
```
|
||||||
|
#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:
|
||||||
|
|
||||||
|
* equal to `order::big` if the execution environment is big endian, otherwise
|
||||||
|
* equal to `order::little` if the execution environment is little endian,
|
||||||
|
otherwise
|
||||||
|
* unequal to both `order::little` and `order::big`.
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
|
||||||
|
#### Template argument requirements
|
||||||
|
|
||||||
|
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 {cpp} program instantiating a template; `x` is a value of type (possibly
|
||||||
|
`const`) `T`; `mlx` is a modifiable lvalue of type `T`.
|
||||||
|
|
||||||
|
[#conversion_endianreversible]
|
||||||
|
##### EndianReversible requirements (in addition to `CopyConstructible`)
|
||||||
|
|
||||||
|
[%header,cols=3*]
|
||||||
|
|===
|
||||||
|
|Expression |Return |Requirements
|
||||||
|
|`endian_reverse(x)` |`T`
|
||||||
|
a|`T` is an endian type or a class type.
|
||||||
|
|
||||||
|
If `T` is an endian type, returns the value of `x` with the order of bytes
|
||||||
|
reversed.
|
||||||
|
|
||||||
|
If `T` is a class type, the function:
|
||||||
|
|
||||||
|
* Returns the value of `x` with the order of bytes reversed for all data members
|
||||||
|
of types or arrays of types that meet the `EndianReversible` requirements, and;
|
||||||
|
* Is a non-member function in the same namespace as `T` that can be found by
|
||||||
|
argument dependent lookup (ADL).
|
||||||
|
|===
|
||||||
|
|
||||||
|
[#conversion_endianreversibleinplace]
|
||||||
|
##### EndianReversibleInplace requirements (in addition to `CopyConstructible`)
|
||||||
|
|
||||||
|
[%header,cols=2*]
|
||||||
|
|===
|
||||||
|
|Expression |Requirements
|
||||||
|
|`endian_reverse_inplace(mlx)`
|
||||||
|
a|`T` is an endian type or a class type.
|
||||||
|
|
||||||
|
If `T` is an endian type, reverses the order of bytes in `mlx`.
|
||||||
|
|
||||||
|
If `T` is a class type, the function:
|
||||||
|
|
||||||
|
* Reverses the order of bytes of all data members of `mlx` that have types or
|
||||||
|
arrays of types that meet the `EndianReversible` or `EndianReversibleInplace`
|
||||||
|
requirements, and;
|
||||||
|
* Is a non-member function in the same namespace as `T` that can be found by
|
||||||
|
argument dependent lookup (ADL).
|
||||||
|
|===
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
#### Customization points for user-defined types (UDTs)
|
||||||
|
|
||||||
|
This subsection describes requirements on the Endian library's implementation.
|
||||||
|
|
||||||
|
The library's function templates requiring
|
||||||
|
`<<conversion_endianreversible,EndianReversible>>` are required to perform
|
||||||
|
reversal of endianness if needed by making an unqualified call to
|
||||||
|
`endian_reverse()`.
|
||||||
|
|
||||||
|
The library's function templates requiring
|
||||||
|
`<<conversion_endianreversibleinplace,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.
|
||||||
|
|
||||||
|
### Functions
|
||||||
|
|
||||||
|
```
|
||||||
|
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;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Returns:: `x`, with the order of its constituent bytes reversed.
|
||||||
|
Remarks:: The type of `x` meets the `EndianReversible` requirements.
|
||||||
|
|
||||||
|
NOTE: The Boost.Endian library does not provide overloads for the {cpp} standard
|
||||||
|
library supplied types.
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class EndianReversible>
|
||||||
|
EndianReversible big_to_native(EndianReversible x) noexcept;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Returns:: `conditional_reverse<order::big, order::native>(x)`.
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class EndianReversible>
|
||||||
|
EndianReversible native_to_big(EndianReversible x) noexcept;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Returns:: `conditional_reverse<order::native, order::big>(x)`.
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class EndianReversible>
|
||||||
|
EndianReversible little_to_native(EndianReversible x) noexcept;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Returns:: `conditional_reverse<order::little, order::native>(x)`.
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class EndianReversible>
|
||||||
|
EndianReversible native_to_little(EndianReversible x) noexcept;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Returns:: `conditional_reverse<order::native, order::little>(x)`.
|
||||||
|
|
||||||
|
```
|
||||||
|
template <order O1, order O2, class EndianReversible>
|
||||||
|
EndianReversible conditional_reverse(EndianReversible x) noexcept;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Returns:: `x` if `O1 == O2,` otherwise `endian_reverse(x)`.
|
||||||
|
Remarks:: Whether `x` or `endian_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;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Returns:: `order1 == order2 ? x : endian_reverse(x)`.
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class EndianReversible>
|
||||||
|
void endian_reverse_inplace(EndianReversible& x) noexcept;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Effects:: `x` `= endian_reverse(x)`.
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class EndianReversibleInplace>
|
||||||
|
void big_to_native_inplace(EndianReversibleInplace& x) noexcept;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Effects:: `conditional_reverse_inplace<order::big, order::native>(x)`.
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class EndianReversibleInplace>
|
||||||
|
void native_to_big_inplace(EndianReversibleInplace& x) noexcept;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Effects:: `conditional_reverse_inplace<order::native, order::big>(x)`.
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class EndianReversibleInplace>
|
||||||
|
void little_to_native_inplace(EndianReversibleInplace& x) noexcept;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Effects:: `conditional_reverse_inplace<order::little, order::native>(x)`.
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class EndianReversibleInplace>
|
||||||
|
void native_to_little_inplace(EndianReversibleInplace& x) noexcept;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Effects:: `conditional_reverse_inplace<order::native, order::little>(x)`.
|
||||||
|
|
||||||
|
```
|
||||||
|
template <order O1, order O2, class EndianReversibleInplace>
|
||||||
|
void conditional_reverse_inplace(EndianReversibleInplace& x) noexcept;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Effects:: None if `O1 == O2,` otherwise `endian_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;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Effects:: If `order1 == order2` then `endian_reverse_inplace(x)`.
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
See the <<overview_faq,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 {cpp} 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 {cpp} 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.
|
||||||
|
|
||||||
|
## Acknowledgements
|
||||||
|
|
||||||
|
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.
|
Reference in New Issue
Block a user