forked from boostorg/endian
Convert Endian buffer types to asciidoc
This commit is contained in:
@ -22,6 +22,8 @@ include::endian/conversion.adoc[]
|
|||||||
|
|
||||||
include::endian/arithmetic.adoc[]
|
include::endian/arithmetic.adoc[]
|
||||||
|
|
||||||
|
include::endian/buffers.adoc[]
|
||||||
|
|
||||||
include::endian/choosing_approach.adoc[]
|
include::endian/choosing_approach.adoc[]
|
||||||
|
|
||||||
include::endian/mini_review_topics.adoc[]
|
include::endian/mini_review_topics.adoc[]
|
||||||
|
@ -82,7 +82,7 @@ int main(int, char* [])
|
|||||||
// Low-level I/O such as POSIX read/write or <cstdio>
|
// Low-level I/O such as POSIX read/write or <cstdio>
|
||||||
// fread/fwrite is sometimes used for binary file operations
|
// fread/fwrite is sometimes used for binary file operations
|
||||||
// when ultimate efficiency is important. Such I/O is often
|
// when ultimate efficiency is important. Such I/O is often
|
||||||
// performed in some {cpp} wrapper class, but to drive home the
|
// performed in some C++ wrapper class, but to drive home the
|
||||||
// point that endian integers are often used in fairly
|
// point that endian integers are often used in fairly
|
||||||
// low-level code that does bulk I/O operations, <cstdio>
|
// low-level code that does bulk I/O operations, <cstdio>
|
||||||
// fopen/fwrite is used for I/O in this example.
|
// fopen/fwrite is used for I/O in this example.
|
||||||
@ -196,7 +196,9 @@ and 64-bit integer types.
|
|||||||
TIP: Prefer unaligned arithmetic types.
|
TIP: Prefer unaligned arithmetic types.
|
||||||
|
|
||||||
TIP: Protect yourself against alignment ills. For example:
|
TIP: Protect yourself against alignment ills. For example:
|
||||||
|
[none]
|
||||||
|
{blank}::
|
||||||
|
+
|
||||||
```
|
```
|
||||||
static_assert(sizeof(containing_struct) == 12, "sizeof(containing_struct) is wrong");
|
static_assert(sizeof(containing_struct) == 12, "sizeof(containing_struct) is wrong");
|
||||||
```
|
```
|
||||||
@ -222,7 +224,7 @@ namespace boost
|
|||||||
{
|
{
|
||||||
namespace endian
|
namespace endian
|
||||||
{
|
{
|
||||||
// {cpp}11 features emulated if not available
|
// C++11 features emulated if not available
|
||||||
|
|
||||||
enum class align {no, yes};
|
enum class align {no, yes};
|
||||||
|
|
||||||
@ -234,7 +236,7 @@ namespace boost
|
|||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
|
|
||||||
// if BOOST_ENDIAN_FORCE_PODNESS is defined && {cpp}11 PODs are not
|
// if BOOST_ENDIAN_FORCE_PODNESS is defined && C++11 PODs are not
|
||||||
// available then these two constructors will not be present
|
// available then these two constructors will not be present
|
||||||
endian_arithmetic() noexcept = default;
|
endian_arithmetic() noexcept = default;
|
||||||
endian_arithmetic(T v) noexcept;
|
endian_arithmetic(T v) noexcept;
|
||||||
@ -374,7 +376,7 @@ to the endianness of the platform.
|
|||||||
### Members
|
### Members
|
||||||
|
|
||||||
```
|
```
|
||||||
endian() = default; // {cpp}03: endian(){}
|
endian() = default; // C++03: endian(){}
|
||||||
```
|
```
|
||||||
[horizontal]
|
[horizontal]
|
||||||
Effects:: Constructs an uninitialized object of type
|
Effects:: Constructs an uninitialized object of type
|
||||||
@ -432,57 +434,53 @@ friend std::basic_istream<charT, traits>&
|
|||||||
```
|
```
|
||||||
[horizontal]
|
[horizontal]
|
||||||
Effects:: As if:
|
Effects:: As if:
|
||||||
|
+
|
||||||
```
|
```
|
||||||
T i;
|
T i;
|
||||||
if (is >> i)
|
if (is >> i)
|
||||||
x = i;
|
x = i;
|
||||||
```
|
```
|
||||||
[horizontal]
|
|
||||||
Returns:: `is`.
|
Returns:: `is`.
|
||||||
|
|
||||||
## FAQ
|
## FAQ
|
||||||
|
|
||||||
See the <<overview_faq,Endian home page>> FAQ for a library-wide FAQ.
|
See the <<overview_faq,Endian home page>> FAQ for a library-wide FAQ.
|
||||||
|
|
||||||
### Why not just use Boost.Serialization?
|
Why not just use Boost.Serialization?::
|
||||||
|
|
||||||
Serialization involves a conversion for every object involved in I/O. Endian
|
Serialization involves a conversion for every object involved in I/O. Endian
|
||||||
integers require no conversion or copying. They are already in the desired
|
integers require no conversion or copying. They are already in the desired
|
||||||
format for binary I/O. Thus they can be read or written in bulk.
|
format for binary I/O. Thus they can be read or written in bulk.
|
||||||
|
|
||||||
### Are endian types PODs?
|
Are endian types PODs?::
|
||||||
|
|
||||||
Yes for {cpp}11. No for {cpp}03, although several
|
Yes for {cpp}11. No for {cpp}03, although several
|
||||||
<<arithmetic_compilation,macros>> are available to force PODness in all cases.
|
<<arithmetic_compilation,macros>> are available to force PODness in all cases.
|
||||||
|
|
||||||
### What are the implications of endian integer types not being PODs with {cpp}03
|
What are the implications of endian integer types not being PODs with {cpp}03 compilers?::
|
||||||
compilers?
|
|
||||||
|
|
||||||
They can't be used in unions. Also, compilers aren't required to align or lay
|
They can't be used in unions. Also, compilers aren't required to align or lay
|
||||||
out storage in portable ways, although this potential problem hasn't prevented
|
out storage in portable ways, although this potential problem hasn't prevented
|
||||||
use of Boost.Endian with real compilers.
|
use of Boost.Endian with real compilers.
|
||||||
|
|
||||||
### What good is native endianness?
|
What good is native endianness?::
|
||||||
|
|
||||||
It provides alignment and size guarantees not available from the built-in
|
It provides alignment and size guarantees not available from the built-in
|
||||||
types. It eases generic programming.
|
types. It eases generic programming.
|
||||||
|
|
||||||
### Why bother with the aligned endian types?
|
Why bother with the aligned endian types?::
|
||||||
|
|
||||||
Aligned integer operations may be faster (as much as 10 to 20 times faster)
|
Aligned integer operations may be faster (as much as 10 to 20 times faster)
|
||||||
if the endianness and alignment of the type matches the endianness and
|
if the endianness and alignment of the type matches the endianness and
|
||||||
alignment requirements of the machine. The code, however, will be somewhat less
|
alignment requirements of the machine. The code, however, will be somewhat less
|
||||||
portable than with the unaligned types.
|
portable than with the unaligned types.
|
||||||
|
|
||||||
### Why provide the arithmetic operations?
|
Why provide the arithmetic operations?::
|
||||||
|
|
||||||
Providing a full set of operations reduces program clutter and makes code
|
Providing a full set of operations reduces program clutter and makes code
|
||||||
both easier to write and to read. Consider incrementing a variable in a record.
|
both easier to write and to read. Consider incrementing a variable in a record.
|
||||||
It is very convenient to write:
|
It is very convenient to write:
|
||||||
|
+
|
||||||
```
|
```
|
||||||
++record.foo;
|
++record.foo;
|
||||||
```
|
```
|
||||||
|
+
|
||||||
Rather than:
|
Rather than:
|
||||||
|
+
|
||||||
```
|
```
|
||||||
int temp(record.foo);
|
int temp(record.foo);
|
||||||
++temp;
|
++temp;
|
||||||
|
506
doc/endian/buffers.adoc
Normal file
506
doc/endian/buffers.adoc
Normal file
@ -0,0 +1,506 @@
|
|||||||
|
////
|
||||||
|
Copyright 2011-2016 Beman Dawes
|
||||||
|
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
////
|
||||||
|
|
||||||
|
[#buffers]
|
||||||
|
# Endian Buffer Types
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
The internal byte order of arithmetic types is traditionally called
|
||||||
|
*endianness*. See the http://en.wikipedia.org/wiki/Endian[Wikipedia] for a full
|
||||||
|
exploration of *endianness*, including definitions of *big endian* and *little
|
||||||
|
endian*.
|
||||||
|
|
||||||
|
Header `boost/endian/buffers.hpp` provides `endian_buffer`, a portable endian
|
||||||
|
integer binary buffer class template with control over byte order, value type,
|
||||||
|
size, and alignment independent of the platform's native endianness. Typedefs
|
||||||
|
provide easy-to-use names for common configurations.
|
||||||
|
|
||||||
|
Use cases primarily involve data portability, either via files or network
|
||||||
|
connections, but these byte-holders may also be used to reduce memory use, file
|
||||||
|
size, or network activity since they provide binary numeric sizes not otherwise
|
||||||
|
available.
|
||||||
|
|
||||||
|
Class `endian_buffer` is aimed at users who wish explicit control over when
|
||||||
|
endianness conversions occur. It also serves as the base class for the
|
||||||
|
<<arithmetic,endian_arithmetic>> class template, which is aimed at users who
|
||||||
|
wish fully automatic endianness conversion and direct support for all normal
|
||||||
|
arithmetic operations.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
The `example/endian_example.cpp` program writes a binary file containing
|
||||||
|
four-byte, big-endian and little-endian integers:
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <boost/endian/buffers.hpp> // see Synopsis below
|
||||||
|
#include <boost/static_assert.hpp>
|
||||||
|
|
||||||
|
using namespace boost::endian;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// This is an extract from a very widely used GIS file format.
|
||||||
|
// Why the designer decided to mix big and little endians in
|
||||||
|
// the same file is not known. But this is a real-world format
|
||||||
|
// and users wishing to write low level code manipulating these
|
||||||
|
// files have to deal with the mixed endianness.
|
||||||
|
|
||||||
|
struct header
|
||||||
|
{
|
||||||
|
big_int32_`buf_`t file_code;
|
||||||
|
big_int32_`buf_`t file_length;
|
||||||
|
little_int32_`buf_`t version;
|
||||||
|
little_int32_`buf_`t shape_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* filename = "test.dat";
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char* [])
|
||||||
|
{
|
||||||
|
header h;
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(sizeof(h) == 16U); // reality check
|
||||||
|
|
||||||
|
h.file_code = 0x01020304;
|
||||||
|
h.file_length = sizeof(header);
|
||||||
|
h.version = 1;
|
||||||
|
h.shape_type = 0x01020304;
|
||||||
|
|
||||||
|
// Low-level I/O such as POSIX read/write or <cstdio>
|
||||||
|
// fread/fwrite is sometimes used for binary file operations
|
||||||
|
// when ultimate efficiency is important. Such I/O is often
|
||||||
|
// performed in some {cpp} wrapper class, but to drive home the
|
||||||
|
// point that endian integers are often used in fairly
|
||||||
|
// low-level code that does bulk I/O operations, <cstdio>
|
||||||
|
// fopen/fwrite is used for I/O in this example.
|
||||||
|
|
||||||
|
std::FILE* fi = std::fopen(filename, "wb"); // MUST BE BINARY
|
||||||
|
|
||||||
|
if (!fi)
|
||||||
|
{
|
||||||
|
std::cout << "could not open " << filename << '\n';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::fwrite(&h, sizeof(header), 1, fi)!= 1)
|
||||||
|
{
|
||||||
|
std::cout << "write failure for " << filename << '\n';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::fclose(fi);
|
||||||
|
|
||||||
|
std::cout << "created file " << filename << '\n';
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After compiling and executing `example/endian_example.cpp`, a hex dump of
|
||||||
|
`test.dat` shows:
|
||||||
|
|
||||||
|
```
|
||||||
|
01020304 00000010 01000000 04030201
|
||||||
|
```
|
||||||
|
|
||||||
|
Notice that the first two 32-bit integers are big endian while the second two
|
||||||
|
are little endian, even though the machine this was compiled and run on was
|
||||||
|
little endian.
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
Requires `<climits>`, `CHAR_BIT == 8`. If `CHAR_BIT` is some other value,
|
||||||
|
compilation will result in an `#error`. This restriction is in place because the
|
||||||
|
design, implementation, testing, and documentation has only considered issues
|
||||||
|
related to 8-bit bytes, and there have been no real-world use cases presented
|
||||||
|
for other sizes.
|
||||||
|
|
||||||
|
In {cpp}03, `endian_buffer` does not meet the requirements for POD types because
|
||||||
|
it has constructors, private data members, and a base class. This means that
|
||||||
|
common use cases are relying on unspecified behavior in that the {cpp} Standard
|
||||||
|
does not guarantee memory layout for non-POD types. This has not been a problem
|
||||||
|
in practice since all known {cpp} compilers lay out memory as if `endian` were
|
||||||
|
a POD type. In {cpp}11, it is possible to specify the default constructor as
|
||||||
|
trivial, and private data members and base classes no longer disqualify a type
|
||||||
|
from being a POD type. Thus under {cpp}11, `endian_buffer` will no longer be
|
||||||
|
relying on unspecified behavior.
|
||||||
|
|
||||||
|
## Feature set
|
||||||
|
|
||||||
|
* Big endian| little endian | native endian byte ordering.
|
||||||
|
* Signed | unsigned
|
||||||
|
* Unaligned | aligned
|
||||||
|
* 1-8 byte (unaligned) | 1, 2, 4, 8 byte (aligned)
|
||||||
|
* Choice of value type
|
||||||
|
|
||||||
|
## Enums and typedefs
|
||||||
|
|
||||||
|
Two scoped enums are provided:
|
||||||
|
|
||||||
|
```
|
||||||
|
enum class order {big, little, native};
|
||||||
|
|
||||||
|
enum class align {no, yes};
|
||||||
|
```
|
||||||
|
|
||||||
|
One class template is provided:
|
||||||
|
|
||||||
|
```
|
||||||
|
template <order Order, typename T, std::size_t Nbits,
|
||||||
|
align Align = align::no>
|
||||||
|
class endian_buffer;
|
||||||
|
```
|
||||||
|
|
||||||
|
Typedefs, such as `big_int32_buf_t`, provide convenient naming conventions for
|
||||||
|
common use cases:
|
||||||
|
|
||||||
|
[%header,cols=5*]
|
||||||
|
|===
|
||||||
|
|Name |Alignment |Endianness |Sign |Sizes in bits (n)
|
||||||
|
|big_intn_buf_t |no |big |signed |8,16,24,32,40,48,56,64
|
||||||
|
|big_uintn_buf_t |no |big |unsigned |8,16,24,32,40,48,56,64
|
||||||
|
|little_intn_buf_t |no |little |signed |8,16,24,32,40,48,56,64
|
||||||
|
|little_uintn_buf_t |no |little |unsigned |8,16,24,32,40,48,56,64
|
||||||
|
|native_intn_buf_t |no |native |signed |8,16,24,32,40,48,56,64
|
||||||
|
|native_uintn_buf_t |no |native |unsigned |8,16,24,32,40,48,56,64
|
||||||
|
|big_intn_buf_at |yes |big |signed |8,16,32,64
|
||||||
|
|big_uintn_buf_at |yes |big |unsigned |8,16,32,64
|
||||||
|
|little_intn_buf_at |yes |little |signed |8,16,32,64
|
||||||
|
|little_uintn_buf_at |yes |little |unsigned |8,16,32,64
|
||||||
|
|===
|
||||||
|
|
||||||
|
The unaligned types do not cause compilers to insert padding bytes in classes
|
||||||
|
and structs. This is an important characteristic that can be exploited to
|
||||||
|
minimize wasted space in memory, files, and network transmissions.
|
||||||
|
|
||||||
|
CAUTION: Code that uses aligned types is possibly non-portable because alignment
|
||||||
|
requirements vary between hardware architectures and because alignment may be
|
||||||
|
affected by compiler switches or pragmas. For example, alignment of an 64-bit
|
||||||
|
integer may be to a 32-bit boundary on a 32-bit machine and to a 64-bit boundary
|
||||||
|
on a 64-bit machine. Furthermore, aligned types are only available on
|
||||||
|
architectures with 8, 16, 32, and 64-bit integer types.
|
||||||
|
|
||||||
|
TIP: Prefer unaligned buffer types.
|
||||||
|
|
||||||
|
TIP: Protect yourself against alignment ills. For example:
|
||||||
|
[none]
|
||||||
|
{blank}::
|
||||||
|
+
|
||||||
|
```
|
||||||
|
static_assert(sizeof(containing_struct) == 12, "sizeof(containing_struct) is wrong");
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: One-byte big and little buffer types have identical layout on all
|
||||||
|
platforms, so they never actually reverse endianness. They are provided to
|
||||||
|
enable generic code, and to improve code readability and searchability.
|
||||||
|
|
||||||
|
## Class template `endian_buffer`
|
||||||
|
|
||||||
|
An `endian_buffer` is a byte-holder for arithmetic types with
|
||||||
|
user-specified <<buffers_endianness,endianness>>, value type, size, and
|
||||||
|
<<buffers_alignment,alignment>>.
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <boost/endian/conversion.hpp
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
namespace endian
|
||||||
|
{
|
||||||
|
// C++11 features emulated if not available
|
||||||
|
|
||||||
|
enum class align {no, yes};
|
||||||
|
|
||||||
|
template <order Order, class T, std::size_t Nbits,
|
||||||
|
align Align = align::no>
|
||||||
|
class endian_buffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef T value_type;
|
||||||
|
|
||||||
|
endian_buffer() noexcept = default;
|
||||||
|
explicit endian_buffer(T v) noexcept;
|
||||||
|
|
||||||
|
endian_buffer& operator=(T v) noexcept;
|
||||||
|
value_type value() const noexcept;
|
||||||
|
const char* data() const noexcept;
|
||||||
|
protected:
|
||||||
|
implementaton-defined endian_value; // for exposition only
|
||||||
|
};
|
||||||
|
|
||||||
|
// stream inserter
|
||||||
|
template <class charT, class traits, order Order, class T,
|
||||||
|
std::size_t n_bits, align Align>
|
||||||
|
std::basic_ostream<charT, traits>&
|
||||||
|
operator<<(std::basic_ostream<charT, traits>& os,
|
||||||
|
const endian_buffer<Order, T, n_bits, Align>& x);
|
||||||
|
|
||||||
|
// stream extractor
|
||||||
|
template <class charT, class traits, order Order, class T,
|
||||||
|
std::size_t n_bits, align A>
|
||||||
|
std::basic_istream<charT, traits>&
|
||||||
|
operator>>(std::basic_istream<charT, traits>& is,
|
||||||
|
endian_buffer<Order, T, n_bits, Align>& x);
|
||||||
|
|
||||||
|
// typedefs
|
||||||
|
|
||||||
|
// unaligned big endian signed integer buffers
|
||||||
|
typedef endian_buffer<order::big, int_least8_t, 8> big_int8_buf_t;
|
||||||
|
typedef endian_buffer<order::big, int_least16_t, 16> big_int16_buf_t;
|
||||||
|
typedef endian_buffer<order::big, int_least32_t, 24> big_int24_buf_t;
|
||||||
|
typedef endian_buffer<order::big, int_least32_t, 32> big_int32_buf_t;
|
||||||
|
typedef endian_buffer<order::big, int_least64_t, 40> big_int40_buf_t;
|
||||||
|
typedef endian_buffer<order::big, int_least64_t, 48> big_int48_buf_t;
|
||||||
|
typedef endian_buffer<order::big, int_least64_t, 56> big_int56_buf_t;
|
||||||
|
typedef endian_buffer<order::big, int_least64_t, 64> big_int64_buf_t;
|
||||||
|
|
||||||
|
// unaligned big endian unsigned integer buffers
|
||||||
|
typedef endian_buffer<order::big, uint_least8_t, 8> big_uint8_buf_t;
|
||||||
|
typedef endian_buffer<order::big, uint_least16_t, 16> big_uint16_buf_t;
|
||||||
|
typedef endian_buffer<order::big, uint_least32_t, 24> big_uint24_buf_t;
|
||||||
|
typedef endian_buffer<order::big, uint_least32_t, 32> big_uint32_buf_t;
|
||||||
|
typedef endian_buffer<order::big, uint_least64_t, 40> big_uint40_buf_t;
|
||||||
|
typedef endian_buffer<order::big, uint_least64_t, 48> big_uint48_buf_t;
|
||||||
|
typedef endian_buffer<order::big, uint_least64_t, 56> big_uint56_buf_t;
|
||||||
|
typedef endian_buffer<order::big, uint_least64_t, 64> big_uint64_buf_t;
|
||||||
|
|
||||||
|
// unaligned little endian signed integer buffers
|
||||||
|
typedef endian_buffer<order::little, int_least8_t, 8> little_int8_buf_t;
|
||||||
|
typedef endian_buffer<order::little, int_least16_t, 16> little_int16_buf_t;
|
||||||
|
typedef endian_buffer<order::little, int_least32_t, 24> little_int24_buf_t;
|
||||||
|
typedef endian_buffer<order::little, int_least32_t, 32> little_int32_buf_t;
|
||||||
|
typedef endian_buffer<order::little, int_least64_t, 40> little_int40_buf_t;
|
||||||
|
typedef endian_buffer<order::little, int_least64_t, 48> little_int48_buf_t;
|
||||||
|
typedef endian_buffer<order::little, int_least64_t, 56> little_int56_buf_t;
|
||||||
|
typedef endian_buffer<order::little, int_least64_t, 64> little_int64_buf_t;
|
||||||
|
|
||||||
|
// unaligned little endian unsigned integer buffers
|
||||||
|
typedef endian_buffer<order::little, uint_least8_t, 8> little_uint8_buf_t;
|
||||||
|
typedef endian_buffer<order::little, uint_least16_t, 16> little_uint16_buf_t;
|
||||||
|
typedef endian_buffer<order::little, uint_least32_t, 24> little_uint24_buf_t;
|
||||||
|
typedef endian_buffer<order::little, uint_least32_t, 32> little_uint32_buf_t;
|
||||||
|
typedef endian_buffer<order::little, uint_least64_t, 40> little_uint40_buf_t;
|
||||||
|
typedef endian_buffer<order::little, uint_least64_t, 48> little_uint48_buf_t;
|
||||||
|
typedef endian_buffer<order::little, uint_least64_t, 56> little_uint56_buf_t;
|
||||||
|
typedef endian_buffer<order::little, uint_least64_t, 64> little_uint64_buf_t;
|
||||||
|
|
||||||
|
// unaligned native endian signed integer types
|
||||||
|
typedef implementation-defined_int8_buf_t native_int8_buf_t;
|
||||||
|
typedef implementation-defined_int16_buf_t native_int16_buf_t;
|
||||||
|
typedef implementation-defined_int24_buf_t native_int24_buf_t;
|
||||||
|
typedef implementation-defined_int32_buf_t native_int32_buf_t;
|
||||||
|
typedef implementation-defined_int40_buf_t native_int40_buf_t;
|
||||||
|
typedef implementation-defined_int48_buf_t native_int48_buf_t;
|
||||||
|
typedef implementation-defined_int56_buf_t native_int56_buf_t;
|
||||||
|
typedef implementation-defined_int64_buf_t native_int64_buf_t;
|
||||||
|
|
||||||
|
// unaligned native endian unsigned integer types
|
||||||
|
typedef implementation-defined_uint8_buf_t native_uint8_buf_t;
|
||||||
|
typedef implementation-defined_uint16_buf_t native_uint16_buf_t;
|
||||||
|
typedef implementation-defined_uint24_buf_t native_uint24_buf_t;
|
||||||
|
typedef implementation-defined_uint32_buf_t native_uint32_buf_t;
|
||||||
|
typedef implementation-defined_uint40_buf_t native_uint40_buf_t;
|
||||||
|
typedef implementation-defined_uint48_buf_t native_uint48_buf_t;
|
||||||
|
typedef implementation-defined_uint56_buf_t native_uint56_buf_t;
|
||||||
|
typedef implementation-defined_uint64_buf_t native_uint64_buf_t;
|
||||||
|
|
||||||
|
// aligned big endian signed integer buffers
|
||||||
|
typedef endian_buffer<order::big, int8_t, 8, align::yes> big_int8_buf_at;
|
||||||
|
typedef endian_buffer<order::big, int16_t, 16, align::yes> big_int16_buf_at;
|
||||||
|
typedef endian_buffer<order::big, int32_t, 32, align::yes> big_int32_buf_at;
|
||||||
|
typedef endian_buffer<order::big, int64_t, 64, align::yes> big_int64_buf_at;
|
||||||
|
|
||||||
|
// aligned big endian unsigned integer buffers
|
||||||
|
typedef endian_buffer<order::big, uint8_t, 8, align::yes> big_uint8_buf_at;
|
||||||
|
typedef endian_buffer<order::big, uint16_t, 16, align::yes> big_uint16_buf_at;
|
||||||
|
typedef endian_buffer<order::big, uint32_t, 32, align::yes> big_uint32_buf_at;
|
||||||
|
typedef endian_buffer<order::big, uint64_t, 64, align::yes> big_uint64_buf_at;
|
||||||
|
|
||||||
|
// aligned little endian signed integer buffers
|
||||||
|
typedef endian_buffer<order::little, int8_t, 8, align::yes> little_int8_buf_at;
|
||||||
|
typedef endian_buffer<order::little, int16_t, 16, align::yes> little_int16_buf_at;
|
||||||
|
typedef endian_buffer<order::little, int32_t, 32, align::yes> little_int32_buf_at;
|
||||||
|
typedef endian_buffer<order::little, int64_t, 64, align::yes> little_int64_buf_at;
|
||||||
|
|
||||||
|
// aligned little endian unsigned integer buffers
|
||||||
|
typedef endian_buffer<order::little, uint8_t, 8, align::yes> little_uint8_buf_at;
|
||||||
|
typedef endian_buffer<order::little, uint16_t, 16, align::yes> little_uint16_buf_at;
|
||||||
|
typedef endian_buffer<order::little, uint32_t, 32, align::yes> little_uint32_buf_at;
|
||||||
|
typedef endian_buffer<order::little, uint64_t, 64, align::yes> little_uint64_buf_at;
|
||||||
|
|
||||||
|
// aligned native endian typedefs are not provided because
|
||||||
|
// <cstdint> types are superior for this use case
|
||||||
|
|
||||||
|
} // namespace endian
|
||||||
|
} // namespace boost
|
||||||
|
```
|
||||||
|
|
||||||
|
The `implementation-defined` text in typedefs above is either `big` or `little`
|
||||||
|
according to the native endianness of the platform.
|
||||||
|
|
||||||
|
The expository data member `endian_value` stores the current value of an
|
||||||
|
`endian_value` object as a sequence of bytes ordered as specified by the
|
||||||
|
`Order` template parameter. The `implementation-defined` type of
|
||||||
|
`endian_value` is a type such as `char[Nbits/CHAR_BIT]` or `T` that meets the
|
||||||
|
requirements imposed by the `Nbits` and `Align` template parameters. The
|
||||||
|
`CHAR_BIT` macro is defined in `<climits>`. The only value of
|
||||||
|
`CHAR_BIT` that is required to be supported is 8.
|
||||||
|
|
||||||
|
Template parameter `T` is required to be a standard integer type ({cpp}std,
|
||||||
|
3.9.1) and `sizeof(T)*CHAR_BIT` is required to be greater or equal to `Nbits`.
|
||||||
|
|
||||||
|
### Members
|
||||||
|
|
||||||
|
```
|
||||||
|
endian_buffer() noexcept = default;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Effects:: Constructs an uninitialized object of type `endian_buffer<Order, T,
|
||||||
|
Nbits, Align>`.
|
||||||
|
|
||||||
|
```
|
||||||
|
explicit endian_buffer(T v) noexcept;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Effects:: Constructs an object of type `endian_buffer<Order, T, Nbits, Align>`.
|
||||||
|
Postcondition:: `value() == v & mask`, where `mask` is a constant of type
|
||||||
|
`value_type` with `Nbits` low-order bits set to one.
|
||||||
|
Remarks:: If `Align` is `align::yes` then endianness conversion, if required,
|
||||||
|
is performed by `boost::endian::endian_reverse`.
|
||||||
|
|
||||||
|
```
|
||||||
|
endian_buffer& operator=(T v) noexcept;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Postcondition:: `value() == v & mask`, where `mask` is a constant of type
|
||||||
|
`value_type` with `Nbits` low-order bits set to one.
|
||||||
|
Returns:: `*this`.
|
||||||
|
Remarks:: If `Align` is `align::yes` then endianness conversion, if required, is
|
||||||
|
performed by `boost::endian::endian_reverse`.
|
||||||
|
|
||||||
|
```
|
||||||
|
value_type value() const noexcept;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Returns:: `endian_value`, converted to `value_type`, if required, and having the
|
||||||
|
endianness of the native platform.
|
||||||
|
Remarks:: If `Align` is `align::yes` then endianness conversion, if required, is
|
||||||
|
performed by `boost::endian::endian_reverse`.
|
||||||
|
|
||||||
|
```
|
||||||
|
const char* data</a>() const noexcept;
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Returns:: A pointer to the first byte of `endian_value`.
|
||||||
|
|
||||||
|
### Non-member functions
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class charT, class traits, order Order, class T,
|
||||||
|
std::size_t n_bits, align Align>
|
||||||
|
std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os,
|
||||||
|
const endian_buffer<Order, T, n_bits, Align>& x);
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Returns:: `os << x.value()`.
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class charT, class traits, order Order, class T,
|
||||||
|
std::size_t n_bits, align A>
|
||||||
|
std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is,
|
||||||
|
endian_buffer<Order, T, n_bits, Align>& x);
|
||||||
|
```
|
||||||
|
[horizontal]
|
||||||
|
Effects:: As if:
|
||||||
|
+
|
||||||
|
```
|
||||||
|
T i;
|
||||||
|
if (is >> i)
|
||||||
|
x = i;
|
||||||
|
```
|
||||||
|
Returns:: `is`.
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
See the <<overview_faq,Endian home page>> FAQ for a library-wide FAQ.
|
||||||
|
|
||||||
|
Why not just use Boost.Serialization?::
|
||||||
|
Serialization involves a conversion for every object involved in I/O. Endian
|
||||||
|
integers require no conversion or copying. They are already in the desired
|
||||||
|
format for binary I/O. Thus they can be read or written in bulk.
|
||||||
|
|
||||||
|
Are endian types PODs?::
|
||||||
|
Yes for {cpp}11. No for {cpp}03, although several
|
||||||
|
<<buffers_compilation,macros>> are available to force PODness in all cases.
|
||||||
|
|
||||||
|
What are the implications of endian integer types not being PODs with {cpp}03 compilers?::
|
||||||
|
They can't be used in unions. Also, compilers aren't required to align or lay
|
||||||
|
out storage in portable ways, although this potential problem hasn't prevented
|
||||||
|
use of Boost.Endian with real compilers.
|
||||||
|
|
||||||
|
What good is native endianness?::
|
||||||
|
It provides alignment and size guarantees not available from the built-in
|
||||||
|
types. It eases generic programming.
|
||||||
|
|
||||||
|
Why bother with the aligned endian types?::
|
||||||
|
Aligned integer operations may be faster (as much as 10 to 20 times faster) if
|
||||||
|
the endianness and alignment of the type matches the endianness and alignment
|
||||||
|
requirements of the machine. The code, however, is likely to be somewhat less
|
||||||
|
portable than with the unaligned types.
|
||||||
|
|
||||||
|
## Design considerations for Boost.Endian buffers
|
||||||
|
|
||||||
|
* Must be suitable for I/O - in other words, must be memcpyable.
|
||||||
|
* Must provide exactly the size and internal byte ordering specified.
|
||||||
|
* Must work correctly when the internal integer representation has more bits
|
||||||
|
that the sum of the bits in the external byte representation. Sign extension
|
||||||
|
must work correctly when the internal integer representation type has more
|
||||||
|
bits than the sum of the bits in the external bytes. For example, using
|
||||||
|
a 64-bit integer internally to represent 40-bit (5 byte) numbers must work for
|
||||||
|
both positive and negative values.
|
||||||
|
* Must work correctly (including using the same defined external
|
||||||
|
representation) regardless of whether a compiler treats char as signed or
|
||||||
|
unsigned.
|
||||||
|
* Unaligned types must not cause compilers to insert padding bytes.
|
||||||
|
* The implementation should supply optimizations with great care. Experience
|
||||||
|
has shown that optimizations of endian integers often become pessimizations
|
||||||
|
when changing machines or compilers. Pessimizations can also happen when
|
||||||
|
changing compiler switches, compiler versions, or CPU models of the same
|
||||||
|
architecture.
|
||||||
|
|
||||||
|
## {cpp}11
|
||||||
|
|
||||||
|
The availability of the {cpp}11
|
||||||
|
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm[Defaulted
|
||||||
|
Functions] feature is detected automatically, and will be used if present to
|
||||||
|
ensure that objects of `class endian_buffer` are trivial, and thus
|
||||||
|
PODs.
|
||||||
|
|
||||||
|
## Compilation
|
||||||
|
|
||||||
|
Boost.Endian is implemented entirely within headers, with no need to link to
|
||||||
|
any Boost object libraries.
|
||||||
|
|
||||||
|
Several macros allow user control over features:
|
||||||
|
|
||||||
|
* BOOST_ENDIAN_NO_CTORS causes `class endian_buffer` to have no
|
||||||
|
constructors. The intended use is for compiling user code that must be
|
||||||
|
portable between compilers regardless of {cpp}11
|
||||||
|
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm[Defaulted
|
||||||
|
Functions] support. Use of constructors will always fail,
|
||||||
|
* BOOST_ENDIAN_FORCE_PODNESS causes BOOST_ENDIAN_NO_CTORS to be defined if the
|
||||||
|
compiler does not support {cpp}11
|
||||||
|
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm[Defaulted
|
||||||
|
Functions]. This is ensures that objects of `class endian_buffer` are PODs, and
|
||||||
|
so can be used in {cpp}03 unions. In {cpp}11, `class endian_buffer` objects are
|
||||||
|
PODs, even though they have constructors, so can always be used in unions.
|
@ -14,78 +14,104 @@ resolved before a mini-review.
|
|||||||
|
|
||||||
The issues are shown in *bold* below, with the resolution indicated.
|
The issues are shown in *bold* below, with the resolution indicated.
|
||||||
|
|
||||||
1. *Common use case scenarios should be developed.*
|
*Common use case scenarios should be developed.*
|
||||||
* Done. The documentation have been refactored. A page is now devoted to
|
|
||||||
|
{blank}::
|
||||||
|
Done. The documentation have been refactored. A page is now devoted to
|
||||||
<<choosing,Choosing the Approach>> to endianness. See
|
<<choosing,Choosing the Approach>> to endianness. See
|
||||||
<<choosing_use_cases,Use cases>> for use case scenarios.
|
<<choosing_use_cases,Use cases>> for use case scenarios.
|
||||||
|
|
||||||
2. *Example programs should be developed for the common use case scenarios.*
|
*Example programs should be developed for the common use case scenarios.*
|
||||||
* Done. See <<choosing,Choosing the Approach>>. Example code has been added
|
|
||||||
|
{blank}::
|
||||||
|
Done. See <<choosing,Choosing the Approach>>. Example code has been added
|
||||||
throughout.
|
throughout.
|
||||||
|
|
||||||
3. *Documentation should illuminate the differences between endian
|
*Documentation should illuminate the differences between endian
|
||||||
integer/float type and endian conversion approaches to the common use case
|
integer/float type and endian conversion approaches to the common use case
|
||||||
scenarios, and provide guidelines for choosing the most appropriate approach in
|
scenarios, and provide guidelines for choosing the most appropriate approach in
|
||||||
user's applications.*
|
user's applications.*
|
||||||
* Done. See <<choosing,Choosing the Approach>>.
|
|
||||||
|
|
||||||
4. *Conversion functions supplying results via return should be provided.*
|
{blank}::
|
||||||
* Done. See <<conversion,Conversion Functions>>.
|
Done. See <<choosing,Choosing the Approach>>.
|
||||||
|
|
||||||
5. *Platform specific performance enhancements such as use of compiler
|
*Conversion functions supplying results via return should be provided.*
|
||||||
|
|
||||||
|
{blank}::
|
||||||
|
Done. See <<conversion,Conversion Functions>>.
|
||||||
|
|
||||||
|
*Platform specific performance enhancements such as use of compiler
|
||||||
intrinsics or relaxed alignment requirements should be supported.*
|
intrinsics or relaxed alignment requirements should be supported.*
|
||||||
* Done. Compiler (Clang, GCC, Visual{cpp}, etc.) intrinsics and built-in
|
|
||||||
|
{blank}::
|
||||||
|
Done. Compiler (Clang, GCC, Visual{cpp}, etc.) intrinsics and built-in
|
||||||
functions are used in the implementation where appropriate, as requested. See
|
functions are used in the implementation where appropriate, as requested. See
|
||||||
<<overview_intrinsic,Built-in support for Intrinsics>>. See
|
<<overview_intrinsic,Built-in support for Intrinsics>>. See
|
||||||
<<overview_timings,Timings for Example 2>> to gauge the impact of intrinsics.
|
<<overview_timings,Timings for Example 2>> to gauge the impact of intrinsics.
|
||||||
|
|
||||||
6. *Endian integer (and floating) types should be implemented via the
|
*Endian integer (and floating) types should be implemented via the
|
||||||
conversion functions. If that can't be done efficiently, consideration should
|
conversion functions. If that can't be done efficiently, consideration should
|
||||||
be given to expanding the conversion function signatures to resolve the
|
be given to expanding the conversion function signatures to resolve the
|
||||||
inefficiencies.*
|
inefficiencies.*
|
||||||
* Done. For the endian types, the implementation uses the endian conversion
|
|
||||||
|
{blank}::
|
||||||
|
Done. For the endian types, the implementation uses the endian conversion
|
||||||
functions, and thus the intrinsics, as requested.
|
functions, and thus the intrinsics, as requested.
|
||||||
|
|
||||||
7. *Benchmarks that measure performance should be provided. It should be
|
*Benchmarks that measure performance should be provided. It should be
|
||||||
possible to compare platform specific performance enhancements against portable
|
possible to compare platform specific performance enhancements against portable
|
||||||
base implementations, and to compare endian integer approaches against endian
|
base implementations, and to compare endian integer approaches against endian
|
||||||
conversion approaches for the common use case scenarios.*
|
conversion approaches for the common use case scenarios.*
|
||||||
* Done. See <<overview_timings,Timings for Example 2>>. The `endian/test`
|
|
||||||
|
{blank}::
|
||||||
|
Done. See <<overview_timings,Timings for Example 2>>. The `endian/test`
|
||||||
directory also contains several additional benchmark and speed test programs.
|
directory also contains several additional benchmark and speed test programs.
|
||||||
|
|
||||||
8. *Float (32-bits) and double (64-bits) should be supported. IEEE 754 is
|
*Float (32-bits) and double (64-bits) should be supported. IEEE 754 is
|
||||||
the primary use case.*
|
the primary use case.*
|
||||||
* Done. The <<buffers,endian buffer types>>,
|
|
||||||
|
{blank}::
|
||||||
|
Done. The <<buffers,endian buffer types>>,
|
||||||
<<arithmetic,endian arithmetic types>> and
|
<<arithmetic,endian arithmetic types>> and
|
||||||
<<conversion,endian conversion functions>> now support 32-bit `(float)`
|
<<conversion,endian conversion functions>> now support 32-bit `(float)`
|
||||||
and 64-bit `(double)` floating point, as requested.
|
and 64-bit `(double)` floating point, as requested.
|
||||||
|
|
||||||
9. *Support for user defined types (UDTs) is desirable, and should be
|
*Support for user defined types (UDTs) is desirable, and should be
|
||||||
provided where there would be no conflict with the other concerns.*
|
provided where there would be no conflict with the other concerns.*
|
||||||
* Done. See <<conversion_customization,Customization points for user-defined
|
|
||||||
|
{blank}::
|
||||||
|
Done. See <<conversion_customization,Customization points for user-defined
|
||||||
types (UDTs)>>.
|
types (UDTs)>>.
|
||||||
|
|
||||||
10. *There is some concern that endian integer/float arithmetic operations
|
*There is some concern that endian integer/float arithmetic operations
|
||||||
might used inadvertently or inappropriately. The impact of adding an
|
might used inadvertently or inappropriately. The impact of adding an
|
||||||
endian_buffer class without arithmetic operations should be investigated.*
|
endian_buffer class without arithmetic operations should be investigated.*
|
||||||
* Done. The endian types have been decomposed into class template
|
|
||||||
|
{blank}::
|
||||||
|
Done. The endian types have been decomposed into class template
|
||||||
`<<buffers,endian_buffer>>` and class template
|
`<<buffers,endian_buffer>>` and class template
|
||||||
`<<arithmetic,endian_arithmetic>>`. Class `endian_buffer` is a public base
|
`<<arithmetic,endian_arithmetic>>`. Class `endian_buffer` is a public base
|
||||||
class for `endian_arithmetic`, and can also be used by users as a stand-alone
|
class for `endian_arithmetic`, and can also be used by users as a stand-alone
|
||||||
class.
|
class.
|
||||||
|
|
||||||
11. *Stream insertion and extraction of the endian integer/float types should
|
*Stream insertion and extraction of the endian integer/float types should
|
||||||
be documented and included in the test coverage.*
|
be documented and included in the test coverage.*
|
||||||
* Done. See <<buffers_stream_inserter,Stream inserter>> and
|
|
||||||
|
{blank}::
|
||||||
|
Done. See <<buffers_stream_inserter,Stream inserter>> and
|
||||||
<<buffers_stream_extractor,Stream extractor>>.
|
<<buffers_stream_extractor,Stream extractor>>.
|
||||||
|
|
||||||
12. *Binary I/O support that was investigated during development of the
|
*Binary I/O support that was investigated during development of the
|
||||||
Endian library should be put up for mini-review for inclusion in the Boost I/O
|
Endian library should be put up for mini-review for inclusion in the Boost I/O
|
||||||
library.*
|
library.*
|
||||||
* Not done yet. Will be handled as a separate min-review soon after the Endian
|
|
||||||
|
{blank}::
|
||||||
|
Not done yet. Will be handled as a separate min-review soon after the Endian
|
||||||
mini-review.
|
mini-review.
|
||||||
|
|
||||||
13. *Other requested changes.*
|
*Other requested changes.*
|
||||||
|
|
||||||
|
{blank}::
|
||||||
* In addition to the named-endianness conversion functions, functions that
|
* In addition to the named-endianness conversion functions, functions that
|
||||||
perform compile-time (via template) and run-time (via function argument)
|
perform compile-time (via template) and run-time (via function argument)
|
||||||
dispatch are now provided.
|
dispatch are now provided.
|
||||||
@ -93,4 +119,4 @@ dispatch are now provided.
|
|||||||
to the endianness of the platform. This reduces the number of template
|
to the endianness of the platform. This reduces the number of template
|
||||||
specializations required.
|
specializations required.
|
||||||
* Headers have been reorganized to make them easier to read, with a synopsis
|
* Headers have been reorganized to make them easier to read, with a synopsis
|
||||||
at the front and implementation following.s
|
at the front and implementation following.
|
||||||
|
Reference in New Issue
Block a user