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/conversion.adoc[]
|
||||
|
||||
include::endian/choosing_approach.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