forked from boostorg/endian
Delete original .html files
This commit is contained in:
@ -1,639 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>Endian Arithmetic Types</title>
|
||||
<link href="styles.css" rel="stylesheet">
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
|
||||
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="100%">
|
||||
<tr>
|
||||
<td>
|
||||
<a href="../../../index.html">
|
||||
<img src="../../../boost.png" alt="Boost logo" align="middle" border="0" width="277" height="86"></a></td>
|
||||
<td align="middle">
|
||||
<b>
|
||||
<font size="6">Endian Arithmetic Types</font> </b>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF" width="100%">
|
||||
<tr>
|
||||
<td><b>
|
||||
<a href="index.html">Endian Home</a>
|
||||
<a href="conversion.html">Conversion Functions</a>
|
||||
<a href="arithmetic.html">Arithmetic Types</a>
|
||||
<a href="buffers.html">Buffer Types</a>
|
||||
<a href="choosing_approach.html">Choosing Approach</a></b></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p></p>
|
||||
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" align="right">
|
||||
<tr>
|
||||
<td width="100%" bgcolor="#D7EEFF" align="center">
|
||||
<i><b>Contents</b></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100%" bgcolor="#E8F5FF">
|
||||
<a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Example">Example</a><br>
|
||||
<a href="#Limitations">Limitations</a><br>
|
||||
<a href="#Feature-set">Feature set</a><br>
|
||||
<a href="#Types">Enums and typedefs</a><br>
|
||||
<a href="#Class_template_endian">Class template <code>endian</code></a><br>
|
||||
|
||||
<a href="#Synopsis">Synopsis</a><br>
|
||||
<a href="#Members">Members</a><br>
|
||||
<a href="#Stream-inserter">Stream inserter</a><br>
|
||||
<a href="#Stream-extractor">Stream extractor</a><br>
|
||||
<a href="#FAQ">FAQ</a><br>
|
||||
<a href="#Design">Design</a><br>
|
||||
<a href="#Experience">Experience</a><br>
|
||||
<a href="#Motivating-use-cases">Motivating use cases</a><br>
|
||||
<a href="#C++0x">C++11</a><br>
|
||||
<a href="#Compilation">Compilation</a><br>
|
||||
<a href="#Acknowledgements">Acknowledgements</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
<p>Header <a href="arithmetic.html">boost/endian/arithmetic.hpp</a>
|
||||
provides integer binary types with control over
|
||||
byte order, value type, size, and alignment. Typedefs provide easy-to-use names
|
||||
for common configurations.</p>
|
||||
<p>These types provide portable byte-holders for integer data, independent of
|
||||
particular computer architectures. Use cases almost always involve I/O, either via files or
|
||||
network connections. Although data portability is the primary motivation, these
|
||||
integer byte-holders may
|
||||
also be used to reduce memory use, file size, or network activity since they
|
||||
provide binary integer sizes not otherwise available.</p>
|
||||
<p>Such integer byte-holder types are traditionally called <b><i>
|
||||
endian</i></b> types. See the
|
||||
<a href="http://en.wikipedia.org/wiki/Endian" name="endianness">Wikipedia</a> for
|
||||
a full
|
||||
exploration of <b><i>endianness</i></b>, including definitions of <i><b>big
|
||||
endian</b></i> and <i><b>little endian</b></i>.</p>
|
||||
<p>Boost endian integers provide the same full set of C++ assignment,
|
||||
arithmetic, and relational operators as C++ standard integral types, with
|
||||
the standard semantics.</p>
|
||||
<p>Unary arithmetic operators are <b> <code><font face="Courier New">+</font></code></b>,
|
||||
<b> <code>-</code></b>, <b> <code>~</code></b>, <b>
|
||||
<code>!</code></b>, plus both prefix and postfix <b> <code>--</code></b> and <b> <code>++</code></b>. Binary
|
||||
arithmetic operators are <b> <code>+</code></b>, <b> <code>+=</code></b>, <b> <code>-</code></b>,
|
||||
<b> <code>
|
||||
-=</code></b>, <b> <code>*</code></b>, <b> <code>*=</code></b>, <b> <code>/</code></b>,
|
||||
<b> <code>/=</code></b>, <b> <code>&</code></b>, <b> <code>&=</code></b>,
|
||||
<b> <code>|</code></b>, <b> <code>|=</code></b>, <b>
|
||||
<code>^</code></b>, <b> <code>^=</code></b>, <b> <code><<</code></b>, <b> <code><<=</code></b>, <code>
|
||||
<b>>></b></code>, and <b>
|
||||
<code>>>=</code></b>. Binary relational operators are <b> <code>==</code></b>,
|
||||
<b> <code>!=</code></b>, <b>
|
||||
<code><</code></b>, <b> <code><=</code></b>, <b> <code>></code></b>,
|
||||
and <b> <code>>=</code></b>.</p>
|
||||
<p>Implicit conversion to the underlying value type is provided. An implicit
|
||||
constructor converting from the underlying value type is provided. </p>
|
||||
<h2><a name="Example">Example</a></h2>
|
||||
<p>The <a href="../example/endian_example.cpp">endian_example.cpp</a> program writes a
|
||||
binary file containing four-byte, big-endian and little-endian integers:</p>
|
||||
<blockquote>
|
||||
<pre>#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <boost/endian/arithmetic.hpp>
|
||||
#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_t file_code;
|
||||
big_int32_t file_length;
|
||||
little_int32_t version;
|
||||
little_int32_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 C++ 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;
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>After compiling and executing <a href="../example/endian_example.cpp">endian_example.cpp</a>,
|
||||
a hex dump of <code>test.dat</code> shows:</p>
|
||||
<blockquote>
|
||||
<pre>01020304 00000010 01000000 04030201</pre>
|
||||
</blockquote>
|
||||
<p>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.</p>
|
||||
<h2><a name="Limitations">Limitations</a></h2>
|
||||
<p>Requires <code><climits></code> <code>CHAR_BIT == 8</code>. If <code>CHAR_BIT</code>
|
||||
is some other value, compilation will result in an <code>#error</code>. 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.</p>
|
||||
<p>In C++03, <code>endian_arithmetic</code> 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 C++
|
||||
Standard does not guarantee memory layout for non-POD types. This has not been a
|
||||
problem in practice since all known C++ compilers lay out memory as if <code>
|
||||
endian</code> were a POD type. In C++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 C++11, <code>endian_arithmetic</code>
|
||||
will no longer be relying on unspecified behavior.</p>
|
||||
<h2><a name="Feature-set">Feature set</a></h2>
|
||||
<ul>
|
||||
<li>Big endian| little endian | native endian byte ordering.</li>
|
||||
<li>Signed | unsigned</li>
|
||||
<li>Unaligned | aligned</li>
|
||||
<li>1-8 byte (unaligned) | 1, 2, 4, 8 byte (aligned)</li>
|
||||
<li>Choice of value type</li>
|
||||
</ul>
|
||||
<h2>Enums and t<a name="Types">ypedefs</a></h2>
|
||||
<p>Two scoped enums are provided:</p>
|
||||
<blockquote>
|
||||
<pre>enum class order {big, little, native};
|
||||
|
||||
enum class align {no, yes}; </pre>
|
||||
</blockquote>
|
||||
<p>One class template is provided:</p>
|
||||
<blockquote>
|
||||
<pre>template <order Order, typename T, std::size_t n_bits,
|
||||
align Align = align::no>
|
||||
class endian_arithmetic;
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>Typedefs, such as <code>big_int32_t</code>, provide convenient naming
|
||||
conventions for common use cases:</p>
|
||||
<blockquote>
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="49%">
|
||||
<tr>
|
||||
<td width="18%" align="center"><b><i>Name</i></b></td>
|
||||
<td width="49%" align="center"><b><i>Alignment</i></b></td>
|
||||
<td width="10%" align="center"><b><i>Endianness</i></b></td>
|
||||
<td width="10%" align="center"><b><i>Sign</i></b></td>
|
||||
<td width="15%" align="center"><b><i>Sizes in bits (n)</i></b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%"><code>big_int</code><b><i>n</i></b><code>_t</code></td>
|
||||
<td width="49%" align="center"><code>no</code></td>
|
||||
<td width="10%" align="center"><code>big</code></td>
|
||||
<td width="10%" align="center">signed</td>
|
||||
<td width="15%">8,16,24,32,40,48,56,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%"><code>big_uint</code><i><b>n</b></i><code>_t</code></td>
|
||||
<td width="49%" align="center"><code>no</code></td>
|
||||
<td width="10%" align="center"><code>big</code></td>
|
||||
<td width="10%" align="center">unsigned</td>
|
||||
<td width="15%">8,16,24,32,40,48,56,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%"><code>little_int</code><i><b>n</b></i><code>_t</code></td>
|
||||
<td width="49%" align="center"><code>no</code></td>
|
||||
<td width="10%" align="center"><code>little</code></td>
|
||||
<td width="10%" align="center">signed</td>
|
||||
<td width="15%">8,16,24,32,40,48,56,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%"><code>little_uint</code><i><b>n</b></i><code>_t</code></td>
|
||||
<td width="49%" align="center"><code>no</code></td>
|
||||
<td width="10%" align="center"><code>little</code></td>
|
||||
<td width="10%" align="center">unsigned</td>
|
||||
<td width="15%">8,16,24,32,40,48,56,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%"><code>native_int</code><i><b>n</b></i><code>_t</code></td>
|
||||
<td width="49%" align="center"><code>no</code></td>
|
||||
<td width="10%" align="center"><code>native</code></td>
|
||||
<td width="10%" align="center">signed</td>
|
||||
<td width="15%">8,16,24,32,40,48,56,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%"><code>native_uint</code><i><b>n</b></i><code>_t</code></td>
|
||||
<td width="49%" align="center"><code>no</code></td>
|
||||
<td width="10%" align="center"><code>native</code></td>
|
||||
<td width="10%" align="center">unsigned</td>
|
||||
<td width="15%">8,16,24,32,40,48,56,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%"><code>big_int</code><i><b>n</b></i><code>_at</code></td>
|
||||
<td width="49%" align="center"><code>yes</code></td>
|
||||
<td width="10%" align="center"><code>big</code></td>
|
||||
<td width="10%" align="center">signed</td>
|
||||
<td width="15%">8,16,32,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%"><code>big_uint</code><i><b>n</b></i><code>_at</code></td>
|
||||
<td width="49%" align="center"><code>yes</code></td>
|
||||
<td width="10%" align="center"><code>big</code></td>
|
||||
<td width="10%" align="center">unsigned</td>
|
||||
<td width="15%">8,16,32,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%" dir="ltr"><code>little_int</code><i><b>n</b></i><code>_at</code></td>
|
||||
<td width="49%" align="center" dir="ltr"><code>yes</code></td>
|
||||
<td width="10%" align="center" dir="ltr"><code>little</code></td>
|
||||
<td width="10%" align="center" dir="ltr">signed</td>
|
||||
<td width="15%" dir="ltr">8,16,32,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%" dir="ltr"><code>little_uint</code><i><b>n</b></i><code>_at</code></td>
|
||||
<td width="49%" align="center" dir="ltr"><code>yes</code></td>
|
||||
<td width="10%" align="center" dir="ltr"><code>little</code></td>
|
||||
<td width="10%" align="center" dir="ltr">unsigned</td>
|
||||
<td width="15%" dir="ltr">8,16,32,64</td>
|
||||
</tr>
|
||||
</table>
|
||||
</blockquote>
|
||||
<p>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. </p>
|
||||
<p><font color="#FF0000"><b><i><span style="background-color: #FFFFFF">Warning:</span></i></b></font><span style="background-color: #FFFFFF">
|
||||
Code that uses a</span>ligned 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. Furthermore, aligned types
|
||||
are only available on architectures with 8, 16, 32, and 64-bit integer types.</p>
|
||||
<p><i><b>Recommendation:</b></i> Prefer unaligned arithmetic types.</p>
|
||||
<p><i><b>Recommendation:</b></i> Protect yourself against alignment ills. For
|
||||
example:</p>
|
||||
<blockquote>
|
||||
<pre>static_assert(sizeof(containing_struct) == 12, "sizeof(containing_struct) is wrong"); </pre>
|
||||
</blockquote>
|
||||
<p><b><i>Note:</i></b> <b><i>Note:</i></b> One-byte arithmetic 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.</p>
|
||||
<h2><a name="Class_template_endian">Class template <code>endian</code></a><code>_arithmetic</code></h2>
|
||||
<p>An <code>endian_integer</code> is an integer byte-holder with user-specified <a href="#endianness">
|
||||
endianness</a>, value type, size, and <a href="#alignment">alignment</a>. The
|
||||
usual operations on arithmetic types are supplied.</p>
|
||||
<h3><a name="Synopsis">Synopsis</a></h3>
|
||||
<pre>#include <boost/endian/conversion.hpp>
|
||||
#include <boost/endian/buffers.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace endian
|
||||
{
|
||||
// C++11 features emulated if not available
|
||||
|
||||
enum class <a name="alignment">align</a> {no, yes};
|
||||
|
||||
template <order Order, class T, std::size_t n_bits,
|
||||
align Align = align::no>
|
||||
class endian_arithmetic
|
||||
: public endian_buffer<Order, T, n_bits, Align>
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
// if BOOST_ENDIAN_FORCE_PODNESS is defined && C++11 PODs are not
|
||||
// available then these two constructors will not be present
|
||||
<a href="#endian">endian_arithmetic</a>() noexcept = default;
|
||||
<a href="#explicit-endian">endian_arithmetic</a>(T v) noexcept;
|
||||
|
||||
endian_arithmetic& <a href="#operator-eq">operator=</a>(T v) noexcept;
|
||||
<a href="#operator-T">operator value_type</a>() const noexcept;
|
||||
value_type value() const noexcept; // for exposition; see endian_buffer
|
||||
const char* <a href="#data">data</a>() const noexcept; // for exposition; see endian_buffer
|
||||
|
||||
// arithmetic operations
|
||||
// note that additional operations are provided by the value_type
|
||||
value_type operator+(const endian& x) noexcept;
|
||||
endian& operator+=(endian& x, value_type y) noexcept;
|
||||
endian& operator-=(endian& x, value_type y) noexcept;
|
||||
endian& operator*=(endian& x, value_type y) noexcept;
|
||||
endian& operator/=(endian& x, value_type y) noexcept;
|
||||
endian& operator%=(endian& x, value_type y) noexcept;
|
||||
endian& operator&=(endian& x, value_type y) noexcept;
|
||||
endian& operator|=(endian& x, value_type y) noexcept;
|
||||
endian& operator^=(endian& x, value_type y) noexcept;
|
||||
endian& operator<<=(endian& x, value_type y) noexcept;
|
||||
endian& operator>>=(endian& x, value_type y noexcept;
|
||||
value_type operator<<(const endian& x, value_type y) noexcept;
|
||||
value_type operator>>(const endian& x, value_type y) noexcept;
|
||||
endian& operator++(endian& x) noexcept;
|
||||
endian& operator--(endian& x) noexcept;
|
||||
endian operator++(endian& x, int) noexcept;
|
||||
endian operator--(endian& x, int) noexcept;
|
||||
|
||||
// Stream inserter
|
||||
template <class charT, class traits>
|
||||
friend std::basic_ostream<charT, traits>&
|
||||
operator<<(std::basic_ostream<charT, traits>& os, const T& x);
|
||||
|
||||
// Stream extractor
|
||||
template <class charT, class traits>
|
||||
friend std::basic_istream<charT, traits>&
|
||||
operator>>(std::basic_istream<charT, traits>& is, T& x);
|
||||
};
|
||||
|
||||
// typedefs
|
||||
|
||||
// unaligned big endian signed integer types
|
||||
typedef endian<order::big, int_least8_t, 8> big_int8_t;
|
||||
typedef endian<order::big, int_least16_t, 16> big_int16_t;
|
||||
typedef endian<order::big, int_least32_t, 24> big_int24_t;
|
||||
typedef endian<order::big, int_least32_t, 32> big_int32_t;
|
||||
typedef endian<order::big, int_least64_t, 40> big_int40_t;
|
||||
typedef endian<order::big, int_least64_t, 48> big_int48_t;
|
||||
typedef endian<order::big, int_least64_t, 56> big_int56_t;
|
||||
typedef endian<order::big, int_least64_t, 64> big_int64_t;
|
||||
|
||||
// unaligned big endian unsigned integer types
|
||||
typedef endian<order::big, uint_least8_t, 8> big_uint8_t;
|
||||
typedef endian<order::big, uint_least16_t, 16> big_uint16_t;
|
||||
typedef endian<order::big, uint_least32_t, 24> big_uint24_t;
|
||||
typedef endian<order::big, uint_least32_t, 32> big_uint32_t;
|
||||
typedef endian<order::big, uint_least64_t, 40> big_uint40_t;
|
||||
typedef endian<order::big, uint_least64_t, 48> big_uint48_t;
|
||||
typedef endian<order::big, uint_least64_t, 56> big_uint56_t;
|
||||
typedef endian<order::big, uint_least64_t, 64> big_uint64_t;
|
||||
|
||||
// unaligned little endian signed integer types
|
||||
typedef endian<order::little, int_least8_t, 8> little_int8_t;
|
||||
typedef endian<order::little, int_least16_t, 16> little_int16_t;
|
||||
typedef endian<order::little, int_least32_t, 24> little_int24_t;
|
||||
typedef endian<order::little, int_least32_t, 32> little_int32_t;
|
||||
typedef endian<order::little, int_least64_t, 40> little_int40_t;
|
||||
typedef endian<order::little, int_least64_t, 48> little_int48_t;
|
||||
typedef endian<order::little, int_least64_t, 56> little_int56_t;
|
||||
typedef endian<order::little, int_least64_t, 64> little_int64_t;
|
||||
|
||||
// unaligned little endian unsigned integer types
|
||||
typedef endian<order::little, uint_least8_t, 8> little_uint8_t;
|
||||
typedef endian<order::little, uint_least16_t, 16> little_uint16_t;
|
||||
typedef endian<order::little, uint_least32_t, 24> little_uint24_t;
|
||||
typedef endian<order::little, uint_least32_t, 32> little_uint32_t;
|
||||
typedef endian<order::little, uint_least64_t, 40> little_uint40_t;
|
||||
typedef endian<order::little, uint_least64_t, 48> little_uint48_t;
|
||||
typedef endian<order::little, uint_least64_t, 56> little_uint56_t;
|
||||
typedef endian<order::little, uint_least64_t, 64> little_uint64_t;
|
||||
|
||||
// unaligned native endian signed integer types
|
||||
typedef <b><i>implementation-defined</i></b>_int8_t native_int8_t;
|
||||
typedef <b><i>implementation-defined</i></b>_int16_t native_int16_t;
|
||||
typedef <b><i>implementation-defined</i></b>_int24_t native_int24_t;
|
||||
typedef <b><i>implementation-defined</i></b>_int32_t native_int32_t;
|
||||
typedef <b><i>implementation-defined</i></b>_int40_t native_int40_t;
|
||||
typedef <b><i>implementation-defined</i></b>_int48_t native_int48_t;
|
||||
typedef <b><i>implementation-defined</i></b>_int56_t native_int56_t;
|
||||
typedef <b><i>implementation-defined</i></b>_int64_t native_int64_t;
|
||||
|
||||
// unaligned native endian unsigned integer types
|
||||
typedef <b><i>implementation-defined</i></b>_uint8_t native_uint8_t;
|
||||
typedef <b><i>implementation-defined</i></b>_uint16_t native_uint16_t;
|
||||
typedef <b><i>implementation-defined</i></b>_uint24_t native_uint24_t;
|
||||
typedef <b><i>implementation-defined</i></b>_uint32_t native_uint32_t;
|
||||
typedef <b><i>implementation-defined</i></b>_uint40_t native_uint40_t;
|
||||
typedef <b><i>implementation-defined</i></b>_uint48_t native_uint48_t;
|
||||
typedef <b><i>implementation-defined</i></b>_uint56_t native_uint56_t;
|
||||
typedef <b><i>implementation-defined</i></b>_uint64_t native_uint64_t;
|
||||
|
||||
// aligned big endian signed integer types
|
||||
typedef endian<order::big, int8_t, 8, align::yes> big_int8_at;
|
||||
typedef endian<order::big, int16_t, 16, align::yes> big_int16_at;
|
||||
typedef endian<order::big, int32_t, 32, align::yes> big_int32_at;
|
||||
typedef endian<order::big, int64_t, 64, align::yes> big_int64_at;
|
||||
|
||||
// aligned big endian unsigned integer types
|
||||
typedef endian<order::big, uint8_t, 8, align::yes> big_uint8_at;
|
||||
typedef endian<order::big, uint16_t, 16, align::yes> big_uint16_at;
|
||||
typedef endian<order::big, uint32_t, 32, align::yes> big_uint32_at;
|
||||
typedef endian<order::big, uint64_t, 64, align::yes> big_uint64_at;
|
||||
|
||||
// aligned little endian signed integer types
|
||||
typedef endian<order::little, int8_t, 8, align::yes> little_int8_at;
|
||||
typedef endian<order::little, int16_t, 16, align::yes> little_int16_at;
|
||||
typedef endian<order::little, int32_t, 32, align::yes> little_int32_at;
|
||||
typedef endian<order::little, int64_t, 64, align::yes> little_int64_at;
|
||||
|
||||
// aligned little endian unsigned integer types
|
||||
typedef endian<order::little, uint8_t, 8, align::yes> little_uint8_at;
|
||||
typedef endian<order::little, uint16_t, 16, align::yes> little_uint16_at;
|
||||
typedef endian<order::little, uint32_t, 32, align::yes> little_uint32_at;
|
||||
typedef endian<order::little, uint64_t, 64, align::yes> little_uint64_at;
|
||||
|
||||
// aligned native endian typedefs are not provided because
|
||||
// <cstdint> types are superior for that use case
|
||||
|
||||
} // namespace endian
|
||||
} // namespace boost</pre>
|
||||
<p>The <i><b><code>implementation-defined</code></b></i> text above is either
|
||||
<code>big</code> or <code>little</code> according to the endianness of the
|
||||
platform.</p>
|
||||
<h3><a name="Members">Members</a></h3>
|
||||
<div dir="ltr">
|
||||
<pre><code><a name="endian">endian</a>() = default; // C++03: endian(){}</code></pre>
|
||||
</div>
|
||||
<blockquote>
|
||||
<p><i>Effects:</i> Constructs an uninitialized object of type <code>endian_arithmetic<E, T, n_bits, A></code>.</p>
|
||||
</blockquote>
|
||||
<pre><code><a name="explicit-endian">endian</a>(T v);</code></pre>
|
||||
<blockquote>
|
||||
<p><i>Effects:</i> Constructs an object of type <code>endian_arithmetic<E, T, n_bits, A></code>.</p>
|
||||
<p><i>Postcondition:</i> <code>x == v,</code> where <code>x</code> is the
|
||||
constructed object.</p>
|
||||
</blockquote>
|
||||
<pre><code>endian& <a name="operator-eq">operator=</a>(T v);</code></pre>
|
||||
<blockquote>
|
||||
<p><i>Postcondition:</i> <code>x == v,</code> where <code>x</code> is the
|
||||
constructed object.</p>
|
||||
<p><i>Returns:</i> <code>*this</code>.</p>
|
||||
</blockquote>
|
||||
<pre><code><a name="operator-T">operator T</a>() const;</code></pre>
|
||||
<blockquote>
|
||||
<p><i>Returns:</i> The current value stored in <code>*this</code>, converted to
|
||||
<code>value_type</code>.</p>
|
||||
</blockquote>
|
||||
<pre><code>const char* <a name="data">data</a>() const;</code></pre>
|
||||
<blockquote>
|
||||
<p><i>Returns:</i> A pointer to the first byte of the endian binary value stored
|
||||
in <code>*this</code>.</p>
|
||||
</blockquote>
|
||||
<h3>Other operators</h3>
|
||||
<p>Other operators on endian objects are forwarded to the equivalent
|
||||
operator on <code>value_type</code>.</p>
|
||||
<h3><a name="Stream-inserter">Stream inserter</a></h3>
|
||||
<pre>template <class charT, class traits>
|
||||
friend std::basic_ostream<charT, traits>&
|
||||
operator<<(std::basic_ostream<charT, traits>& os, const T& x);
|
||||
</pre>
|
||||
<blockquote>
|
||||
<p><i>Returns:</i> <code>os << +x</code>.</p>
|
||||
</blockquote>
|
||||
<h3><a name="Stream-extractor">Stream extractor</a></h3>
|
||||
<pre>template <class charT, class traits>
|
||||
friend std::basic_istream<charT, traits>&
|
||||
operator>>(std::basic_istream<charT, traits>& is, T& x);
|
||||
</pre>
|
||||
<blockquote>
|
||||
<p><i>Effects: </i>As if:</p>
|
||||
<blockquote>
|
||||
<pre>T i;
|
||||
if (is >> i)
|
||||
x = i;
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p><i>Returns: </i><code>is</code><i>.</i></p>
|
||||
</blockquote>
|
||||
<h2><a name="FAQ">FAQ</a></h2>
|
||||
|
||||
<p>See the <a href="index.html#FAQ">Endian home page</a> FAQ for a library-wide
|
||||
FAQ.</p>
|
||||
|
||||
<p><b>Why not just use Boost.Serialization?</b> 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.</p>
|
||||
<p><b>Are endian types PODs?</b> Yes for C++11. No for C++03, although several
|
||||
<a href="#Compilation">macros</a> are available to force PODness in all cases.</p>
|
||||
<p><b>What are the implications of endian integer types not being PODs with C++03
|
||||
compilers?</b> 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.</p>
|
||||
<p><b>What good is <i>native </i>endianness?</b> It provides alignment and
|
||||
size guarantees not available from the built-in types. It eases generic
|
||||
programming.</p>
|
||||
<p><b>Why bother with the aligned endian types?</b> 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, will be somewhat less portable than with the unaligned types.</p>
|
||||
<p><b>Why provide the arithmetic operations?</b> 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. It is very convenient to write:</p>
|
||||
<pre wrap> ++record.foo;</pre>
|
||||
<p wrap>Rather than:</p>
|
||||
<pre wrap> int temp(record.foo);
|
||||
++temp;
|
||||
record.foo = temp;</pre>
|
||||
<h2><a name="Design">Design</a> considerations for Boost.Endian types</h2>
|
||||
<ul>
|
||||
<li>Must be suitable for I/O - in other words, must be memcpyable.</li>
|
||||
<li>Must provide exactly the size and internal byte ordering specified.</li>
|
||||
<li>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.</li>
|
||||
<li>Must work correctly (including using the same defined external
|
||||
representation) regardless of whether a compiler treats char as signed or
|
||||
unsigned.</li>
|
||||
<li>Unaligned types must not cause compilers to insert padding bytes.</li>
|
||||
<li>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.</li>
|
||||
</ul>
|
||||
<h2><a name="Experience">Experience</a></h2>
|
||||
<p>Classes with similar functionality have been independently developed by
|
||||
several Boost programmers and used very successful in high-value, high-use
|
||||
applications for many years. These independently developed endian libraries
|
||||
often evolved from C libraries that were also widely used. Endian types have proven widely useful across a wide
|
||||
range of computer architectures and applications.</p>
|
||||
<h2><a name="Motivating-use-cases">Motivating use cases</a></h2>
|
||||
<p>Neil Mayhew writes: "I can also provide a meaningful use-case for this
|
||||
library: reading TrueType font files from disk and processing the contents. The
|
||||
data format has fixed endianness (big) and has unaligned values in various
|
||||
places. Using Boost.Endian simplifies and cleans the code wonderfully."</p>
|
||||
<h2><a name="C++0x">C++11</a></h2>
|
||||
<p>The availability of the C++11
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">
|
||||
Defaulted Functions</a> feature is detected automatically, and will be used if
|
||||
present to ensure that objects of <code>class endian_arithmetic</code> are trivial, and
|
||||
thus PODs.</p>
|
||||
<h2><a name="Compilation">Compilation</a></h2>
|
||||
<p>Boost.Endian is implemented entirely within headers, with no need to link to
|
||||
any Boost object libraries.</p>
|
||||
<p>Several macros allow user control over features:</p>
|
||||
<ul>
|
||||
<li>BOOST_ENDIAN_NO_CTORS causes <code>class endian_arithmetic</code> to have no
|
||||
constructors. The intended use is for compiling user code that must be
|
||||
portable between compilers regardless of C++11
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">
|
||||
Defaulted Functions</a> support. Use of constructors will always fail, <br>
|
||||
</li>
|
||||
<li>BOOST_ENDIAN_FORCE_PODNESS causes BOOST_ENDIAN_NO_CTORS to be defined if
|
||||
the compiler does not support C++11
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">
|
||||
Defaulted Functions</a>. This is ensures that objects of <code>class endian_arithmetic</code>
|
||||
are PODs, and so can be used in C++03 unions.
|
||||
In C++11, <code>class endian_arithmetic</code> objects are PODs, even though they have
|
||||
constructors, so can always be used in unions.</li>
|
||||
</ul>
|
||||
<h2><a name="Acknowledgements">Acknowledgements</a></h2>
|
||||
<p>Original design developed by Darin Adler based on classes developed by Mark
|
||||
Borgerding. Four original class templates combined into a single <code>endian_arithmetic</code>
|
||||
class template by Beman Dawes, who put the library together, provided
|
||||
documentation, added the typedefs, and also added the <code>unrolled_byte_loops</code>
|
||||
sign partial specialization to correctly extend the sign when cover integer size
|
||||
differs from endian representation size.</p>
|
||||
<hr>
|
||||
<p>Last revised:
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->14 October, 2015<!--webbot bot="Timestamp" endspan i-checksum="38874" --></p>
|
||||
<p>© Copyright Beman Dawes, 2006-2009, 2013</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. See
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/ LICENSE_1_0.txt</a></p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,79 +0,0 @@
|
||||
Conversion function naming bikeshed
|
||||
|
||||
return-by-value modify-argument
|
||||
------------------ ---------------
|
||||
|
||||
reverse_endianness reverse_endianness_in_place
|
||||
" reverse_endianness_arg
|
||||
endian_reverse endian_reverse_in_place
|
||||
" endian_reverse_inplace
|
||||
" endian_reverse_replace
|
||||
" endian_reverse_in_situ
|
||||
" endian_reverse_here
|
||||
" endian_reverse_this
|
||||
" endian_reverse_self
|
||||
" endian_reverse_arg
|
||||
" endian_reverse_in
|
||||
|
||||
reverse reverse_in_place
|
||||
reverse_endian reverse_endian_in_place
|
||||
|
||||
swap_endianness swap_endianness_in_place
|
||||
swap_endian swap_endian_in_place
|
||||
endian_swap endian_swap_this
|
||||
|
||||
flip_endianness flip_endianness_in_place
|
||||
flip_endian flip_endian_in_place
|
||||
endian_flip endian_flip_in_place
|
||||
|
||||
|
||||
reverse_order reverse_order_in_place
|
||||
|
||||
|
||||
Key points:
|
||||
|
||||
* The above names are defined in a user namespace as customization points to be found by
|
||||
ADL, and so cannot depend on the enclosing namespace name to signal readers that they
|
||||
are related to endianness.
|
||||
* The above functions are rarely called directly by user code, which is more likely to use
|
||||
the various conditional functions instead. So explicitness is more important than
|
||||
brevity.
|
||||
|
||||
Conditional names
|
||||
|
||||
big_to_native native_to_big little_to_native native_to_little
|
||||
|
||||
big_to_host host_to_big
|
||||
|
||||
be_to_ne ne_to_be
|
||||
|
||||
from_big, to_big
|
||||
|
||||
big_to_native big_to_native
|
||||
native_to_big native_to_big
|
||||
|
||||
conditional_reverse runtime_conditional_reverse
|
||||
conditional_reverse conditional_reverse <------
|
||||
|
||||
merriam-webster.com/dictionary
|
||||
|
||||
reverse [1] (adjective): opposite or contrary to a previous or normal condition <reverse order>
|
||||
reverse [2] (verb) : to change (something) to an opposite state or condition
|
||||
|
||||
swap (verb) : to give something to someone and receive something in return : to trade or exchange (things)
|
||||
|
||||
flip (verb)
|
||||
|
||||
: to turn (something) over by throwing it up in the air with a quick movement
|
||||
|
||||
: to cause (something) to turn or turn over quickly
|
||||
|
||||
: to move (something) with a quick light movement
|
||||
|
||||
--------------------------------------------------
|
||||
|
||||
Copyright Beman Dawes, 2014
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
See www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
|
600
doc/buffers.html
600
doc/buffers.html
@ -1,600 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>Endian Buffer Types</title>
|
||||
<link href="styles.css" rel="stylesheet">
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
|
||||
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="100%">
|
||||
<tr>
|
||||
<td>
|
||||
<a href="../../../index.html">
|
||||
<img src="../../../boost.png" alt="Boost logo" align="middle" border="0" width="277" height="86"></a></td>
|
||||
<td align="middle">
|
||||
<b>
|
||||
<font size="6">Endian Buffer Types</font> </b>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF" width="100%">
|
||||
<tr>
|
||||
<td><b>
|
||||
<a href="index.html">Endian Home</a>
|
||||
<a href="conversion.html">Conversion Functions</a>
|
||||
<a href="arithmetic.html">Arithmetic Types</a>
|
||||
<a href="buffers.html">Buffer Types</a>
|
||||
<a href="choosing_approach.html">Choosing Approach</a></b></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p></p>
|
||||
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" align="right">
|
||||
<tr>
|
||||
<td width="100%" bgcolor="#D7EEFF" align="center">
|
||||
<i><b>Contents</b></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100%" bgcolor="#E8F5FF">
|
||||
<a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Example">Example</a><br>
|
||||
<a href="#Limitations">Limitations</a><br>
|
||||
<a href="#Feature-set">Feature set</a><br>
|
||||
<a href="#Types">Enums and typedefs</a><br>
|
||||
<a href="#Class_template_endian">Class template <code>endian_buffer</code></a><br>
|
||||
|
||||
<a href="#Synopsis">Synopsis</a><br>
|
||||
<a href="#Members">Members</a><br>
|
||||
<a href="#Non-member-functions">Non-Members</a><br>
|
||||
<a href="#FAQ">FAQ</a><br>
|
||||
<a href="#Design">Design</a><br>
|
||||
<a href="#C++0x">C++11</a><br>
|
||||
<a href="#Compilation">Compilation</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
<p>The internal byte order of arithmetic types is traditionally called <b><i>endianness</i></b>. See
|
||||
the
|
||||
<a href="http://en.wikipedia.org/wiki/Endian" name="endianness">Wikipedia</a> for
|
||||
a full
|
||||
exploration of <b><i>endianness</i></b>, including definitions of <i><b>big
|
||||
endian</b></i> and <i><b>little endian</b></i>.</p>
|
||||
<p>Header <b><code>boost/endian/buffers.hpp</code></b>
|
||||
provides <code>endian_buffer</code>, 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.</p>
|
||||
<p>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.</p>
|
||||
<p dir="ltr">Class <code>endian_buffer</code> is aimed at users who wish
|
||||
explicit control over when endianness conversions occur. It also serves as the
|
||||
base class for the <code><a href="arithmetic.html">endian_arithmetic</a></code>
|
||||
class template, which is aimed at users who wish fully automatic endianness
|
||||
conversion and direct support for all normal arithmetic operations.</p>
|
||||
<h2><a name="Example">Example</a></h2>
|
||||
<p>The <b><code>example/endian_example.cpp</code></b> program writes a
|
||||
binary file containing four-byte, big-endian and little-endian integers:</p>
|
||||
<blockquote>
|
||||
<pre>#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <boost/endian/buffers.hpp> // see <a href="#Synopsis">Synopsis</a> 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_<code>buf_</code>t file_code;
|
||||
big_int32_<code>buf_</code>t file_length;
|
||||
little_int32_<code>buf_</code>t version;
|
||||
little_int32_<code>buf_</code>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 C++ 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;
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>After compiling and executing <b><code>example/endian_example.cpp</code></b>,
|
||||
a hex dump of <code>test.dat</code> shows:</p>
|
||||
<blockquote>
|
||||
<pre>01020304 00000010 01000000 04030201</pre>
|
||||
</blockquote>
|
||||
<p>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.</p>
|
||||
<h2><a name="Limitations">Limitations</a></h2>
|
||||
<p>Requires <code><climits></code> <code>CHAR_BIT == 8</code>. If <code>CHAR_BIT</code>
|
||||
is some other value, compilation will result in an <code>#error</code>. 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.</p>
|
||||
<p>In C++03, <code>endian_buffer</code> 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 C++
|
||||
Standard does not guarantee memory layout for non-POD types. This has not been a
|
||||
problem in practice since all known C++ compilers lay out memory as if <code>
|
||||
endian</code> were a POD type. In C++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 C++11, <code>endian_buffer</code>
|
||||
will no longer be relying on unspecified behavior.</p>
|
||||
<h2><a name="Feature-set">Feature set</a></h2>
|
||||
<ul>
|
||||
<li>Big endian| little endian | native endian byte ordering.</li>
|
||||
<li>Signed | unsigned</li>
|
||||
<li>Unaligned | aligned</li>
|
||||
<li>1-8 byte (unaligned) | 1, 2, 4, 8 byte (aligned)</li>
|
||||
<li>Choice of value type</li>
|
||||
</ul>
|
||||
<h2>Enums and t<a name="Types">ypedefs</a></h2>
|
||||
<p>Two scoped enums are provided:</p>
|
||||
<blockquote>
|
||||
<pre>enum class order {big, little, native};
|
||||
|
||||
enum class align {no, yes}; </pre>
|
||||
</blockquote>
|
||||
<p>One class template is provided:</p>
|
||||
<blockquote>
|
||||
<pre>template <order Order, typename T, std::size_t Nbits,
|
||||
align Align = align::no>
|
||||
class endian_buffer;
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>Typedefs, such as <code>big_int32_buf_t</code>, provide convenient naming
|
||||
conventions for common use cases:</p>
|
||||
<blockquote>
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="49%">
|
||||
<tr>
|
||||
<td width="18%" align="center"><b><i>Name</i></b></td>
|
||||
<td width="49%" align="center"><b><i>Alignment</i></b></td>
|
||||
<td width="10%" align="center"><b><i>Endianness</i></b></td>
|
||||
<td width="10%" align="center"><b><i>Sign</i></b></td>
|
||||
<td width="15%" align="center"><b><i>Sizes in bits (n)</i></b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%" dir="ltr"><code>big_int</code><b><i>n</i></b><code>_buf_t</code></td>
|
||||
<td width="49%" align="center" dir="ltr"><code>no</code></td>
|
||||
<td width="10%" align="center" dir="ltr"><code>big</code></td>
|
||||
<td width="10%" align="center" dir="ltr">signed</td>
|
||||
<td width="15%" dir="ltr">8,16,24,32,40,48,56,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%" dir="ltr"><code>big_uint</code><i><b>n</b></i><code>_buf_t</code></td>
|
||||
<td width="49%" align="center" dir="ltr"><code>no</code></td>
|
||||
<td width="10%" align="center" dir="ltr"><code>big</code></td>
|
||||
<td width="10%" align="center" dir="ltr">unsigned</td>
|
||||
<td width="15%" dir="ltr">8,16,24,32,40,48,56,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%"><code>little_int</code><i><b>n</b></i><code>_buf_t</code></td>
|
||||
<td width="49%" align="center"><code>no</code></td>
|
||||
<td width="10%" align="center"><code>little</code></td>
|
||||
<td width="10%" align="center">signed</td>
|
||||
<td width="15%">8,16,24,32,40,48,56,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%"><code>little_uint</code><i><b>n</b></i><code>_buf_t</code></td>
|
||||
<td width="49%" align="center"><code>no</code></td>
|
||||
<td width="10%" align="center"><code>little</code></td>
|
||||
<td width="10%" align="center">unsigned</td>
|
||||
<td width="15%">8,16,24,32,40,48,56,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%"><code>native_int</code><i><b>n</b></i><code>_buf_t</code></td>
|
||||
<td width="49%" align="center"><code>no</code></td>
|
||||
<td width="10%" align="center"><code>native</code></td>
|
||||
<td width="10%" align="center">signed</td>
|
||||
<td width="15%">8,16,24,32,40,48,56,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%"><code>native_uint</code><i><b>n</b></i><code>_buf_t</code></td>
|
||||
<td width="49%" align="center"><code>no</code></td>
|
||||
<td width="10%" align="center"><code>native</code></td>
|
||||
<td width="10%" align="center">unsigned</td>
|
||||
<td width="15%">8,16,24,32,40,48,56,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%"><code>big_int</code><i><b>n</b></i><code>_buf_at</code></td>
|
||||
<td width="49%" align="center"><code>yes</code></td>
|
||||
<td width="10%" align="center"><code>big</code></td>
|
||||
<td width="10%" align="center">signed</td>
|
||||
<td width="15%">8,16,32,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%"><code>big_uint</code><i><b>n</b></i><code>_</code><code>buf_at</code></td>
|
||||
<td width="49%" align="center"><code>yes</code></td>
|
||||
<td width="10%" align="center"><code>big</code></td>
|
||||
<td width="10%" align="center">unsigned</td>
|
||||
<td width="15%">8,16,32,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%"><code>little_int</code><i><b>n</b></i><code>_</code><code>buf_at</code></td>
|
||||
<td width="49%" align="center"><code>yes</code></td>
|
||||
<td width="10%" align="center"><code>little</code></td>
|
||||
<td width="10%" align="center">signed</td>
|
||||
<td width="15%">8,16,32,64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="18%"><code>little_uint</code><i><b>n</b></i><code>_</code><code>buf_at</code></td>
|
||||
<td width="49%" align="center"><code>yes</code></td>
|
||||
<td width="10%" align="center"><code>little</code></td>
|
||||
<td width="10%" align="center">unsigned</td>
|
||||
<td width="15%">8,16,32,64</td>
|
||||
</tr>
|
||||
</table>
|
||||
</blockquote>
|
||||
<p>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. </p>
|
||||
<p><font color="#FF0000"><b><i><span style="background-color: #FFFFFF">Warning:</span></i></b></font><span style="background-color: #FFFFFF">
|
||||
Code that uses a</span>ligned 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. </p>
|
||||
<p><i><b>Recommendation:</b></i> Prefer unaligned buffer types.</p>
|
||||
<p><i><b>Recommendation:</b></i> Protect yourself against alignment ills. For
|
||||
example:</p>
|
||||
<blockquote>
|
||||
<pre>static_assert(sizeof(containing_struct) == 12, "sizeof(containing_struct) is wrong"); </pre>
|
||||
</blockquote>
|
||||
<p><b><i>Note:</i></b> 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.</p>
|
||||
<h2><a name="Class_template_endian">Class template <code>endian</code></a><code>_buffer</code></h2>
|
||||
<p>An <code>endian_buffer</code> is a byte-holder for arithmetic types with user-specified <a href="#endianness">
|
||||
endianness</a>, value type, size, and <a href="#alignment">alignment</a>.</p>
|
||||
<h3><a name="Synopsis">Synopsis</a></h3>
|
||||
<pre>#include <boost/endian/conversion.hpp
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace endian
|
||||
{
|
||||
// C++11 features emulated if not available
|
||||
|
||||
enum class <a name="alignment">align</a> {no, yes};
|
||||
|
||||
template <order Order, class T, std::size_t Nbits,
|
||||
align Align = align::no>
|
||||
class endian_buffer
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
<a href="#endian">endian_buffer</a>() noexcept = default;
|
||||
explicit <a href="#explicit-endian">endian_buffer</a>(T v) noexcept;
|
||||
|
||||
endian_buffer& <a href="#operator-eq">operator=</a>(T v) noexcept;
|
||||
value_type <a href="#value">value</a>() const noexcept;
|
||||
const char* <a href="#data">data</a>() const noexcept;
|
||||
protected:
|
||||
<b><i>implementaton-defined</i></b> 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>&
|
||||
<a href="#inserter">operator<<</a>(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>&
|
||||
<a href="#extractor">operator>></a>(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 <b><i>implementation-defined</i></b>_int8_buf_t native_int8_buf_t;
|
||||
typedef <b><i>implementation-defined</i></b>_int16_buf_t native_int16_buf_t;
|
||||
typedef <b><i>implementation-defined</i></b>_int24_buf_t native_int24_buf_t;
|
||||
typedef <b><i>implementation-defined</i></b>_int32_buf_t native_int32_buf_t;
|
||||
typedef <b><i>implementation-defined</i></b>_int40_buf_t native_int40_buf_t;
|
||||
typedef <b><i>implementation-defined</i></b>_int48_buf_t native_int48_buf_t;
|
||||
typedef <b><i>implementation-defined</i></b>_int56_buf_t native_int56_buf_t;
|
||||
typedef <b><i>implementation-defined</i></b>_int64_buf_t native_int64_buf_t;
|
||||
|
||||
// unaligned native endian unsigned integer types
|
||||
typedef <b><i>implementation-defined</i></b>_uint8_buf_t native_uint8_buf_t;
|
||||
typedef <b><i>implementation-defined</i></b>_uint16_buf_t native_uint16_buf_t;
|
||||
typedef <b><i>implementation-defined</i></b>_uint24_buf_t native_uint24_buf_t;
|
||||
typedef <b><i>implementation-defined</i></b>_uint32_buf_t native_uint32_buf_t;
|
||||
typedef <b><i>implementation-defined</i></b>_uint40_buf_t native_uint40_buf_t;
|
||||
typedef <b><i>implementation-defined</i></b>_uint48_buf_t native_uint48_buf_t;
|
||||
typedef <b><i>implementation-defined</i></b>_uint56_buf_t native_uint56_buf_t;
|
||||
typedef <b><i>implementation-defined</i></b>_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</pre>
|
||||
<p>The <i><b><code>implementation-defined</code></b></i> text in typedefs above is either
|
||||
<code>big</code> or <code>little</code> according to the native endianness of the
|
||||
platform.</p>
|
||||
<p>The expository data member <code>endian_value</code> stores the current value
|
||||
of an <code>endian_value</code> object as a sequence of bytes ordered as
|
||||
specified by the <code>Order</code> template parameter. The <i><b><code>
|
||||
implementation-defined</code></b></i> type of <code>endian_value</code> is a
|
||||
type such as <code><span style="font-size: 85%">char[Nbits/CHAR_BIT]</span></code>
|
||||
or <code><span style="font-size: 85%">T</span></code> that meets the
|
||||
requirements imposed by the <code>Nbits</code> and <code>Align</code> template
|
||||
parameters. The <code><span style="font-size: 85%">CHAR_BIT</span></code>
|
||||
macro is defined in <code><span style="font-size: 85%"><climits></span></code>.
|
||||
The only value of <code><span style="font-size: 85%">CHAR_BIT</span></code> that
|
||||
is required to be supported is 8.</p>
|
||||
<p>Template parameter <code><span style="font-size: 85%">T</span></code> is
|
||||
required to be a standard integer type (C++std, 3.9.1) and <code>
|
||||
<span style="font-size: 85%">sizeof(T)*CHAR_BIT</span></code> is required to be
|
||||
greater or equal to <span style="font-size: 85%"> <code>Nbits</code>.</span></p>
|
||||
<h3><a name="Members">Members</a></h3>
|
||||
<pre><code><a name="endian">endian</a>_buffer() noexcept = default;</code></pre>
|
||||
<blockquote>
|
||||
<p><i>Effects:</i> Constructs an uninitialized object of type <code>endian_buffer<Order, T,
|
||||
Nbits, Align></code>.</p>
|
||||
</blockquote>
|
||||
<pre><code>explicit <a name="explicit-endian">endian</a>_buffer(T v) noexcept;</code></pre>
|
||||
<blockquote>
|
||||
<p><i>Effects:</i> Constructs an object of type <code>endian_buffer<Order, T,
|
||||
Nbits, Align></code>.</p>
|
||||
<p><i>Postcondition:</i> <code>value() == v & mask</code>, where <code>mask</code>
|
||||
is a constant of type <code>value_type</code> with <code>Nbits</code> low-order
|
||||
bits set to one.</p>
|
||||
<p><i>Remarks:</i> If <code>Align</code> is <code>align::yes</code> then
|
||||
endianness conversion, if required, is performed by <code>
|
||||
boost::endian::endian_reverse</code>.</p>
|
||||
</blockquote>
|
||||
<pre><code>endian_buffer& <a name="operator-eq">operator=</a>(T v) noexcept;</code></pre>
|
||||
<blockquote>
|
||||
<p><i>Postcondition:</i> <code>value() == v & mask</code>, where <code>mask</code>
|
||||
is a constant of type <code>value_type</code> with <code>Nbits</code>
|
||||
low-order bits set to one.</p>
|
||||
<p><i>Returns:</i> <code>*this</code>.</p>
|
||||
<p><i>Remarks:</i> If <code>Align</code> is <code>align::yes</code> then
|
||||
endianness conversion, if required, is performed by <code>
|
||||
boost::endian::endian_reverse</code>.</p>
|
||||
</blockquote>
|
||||
<pre>value_type <a name="value">value</a>()<code> const noexcept;</code></pre>
|
||||
<blockquote>
|
||||
<p><i>Returns:</i> <code>endian_value</code>, converted to <code>value_type</code>,
|
||||
if required, and having the endianness of the native platform.</p>
|
||||
<p><i>Remarks:</i> If <code>Align</code> is <code>align::yes</code> then
|
||||
endianness conversion, if required, is performed by <code>
|
||||
boost::endian::endian_reverse</code>.</p>
|
||||
</blockquote>
|
||||
<pre><code>const char* <a name="data">data</a>() const noexcept;</code></pre>
|
||||
<blockquote>
|
||||
<p><i>Returns:</i> A pointer to the first byte of <code>endian_value</code>.</p>
|
||||
</blockquote>
|
||||
<h3><a name="Non-member-functions">Non-member functions</a></h3>
|
||||
<pre>template <class charT, class traits, order Order, class T,
|
||||
std::size_t n_bits, align Align>
|
||||
std::basic_ostream<charT, traits>& <a name="inserter">operator<<</a>(std::basic_ostream<charT, traits>& os,
|
||||
const endian_buffer<Order, T, n_bits, Align>& x);
|
||||
</pre>
|
||||
<blockquote>
|
||||
<p><i>Returns:</i> <code>os << x.value()</code>.</p>
|
||||
</blockquote>
|
||||
<pre>template <class charT, class traits, order Order, class T,
|
||||
std::size_t n_bits, align A>
|
||||
std::basic_istream<charT, traits>& <a name="extractor">operator>></a>(std::basic_istream<charT, traits>& is,
|
||||
endian_buffer<Order, T, n_bits, Align>& x);
|
||||
</pre>
|
||||
<blockquote>
|
||||
<p><i>Effects: </i>As if:</p>
|
||||
<blockquote>
|
||||
<pre>T i;
|
||||
if (is >> i)
|
||||
x = i;
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p><i>Returns:</i> <code>is</code>.</p>
|
||||
</blockquote>
|
||||
<h2><a name="FAQ">FAQ</a></h2>
|
||||
|
||||
<p>See the <a href="index.html#FAQ">Endian home page</a> FAQ for a library-wide
|
||||
FAQ.</p>
|
||||
|
||||
<p><b>Why not just use Boost.Serialization?</b> 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.</p>
|
||||
<p><b>Are endian types PODs?</b> Yes for C++11. No for C++03, although several
|
||||
<a href="#Compilation">macros</a> are available to force PODness in all cases.</p>
|
||||
<p><b>What are the implications of endian integer types not being PODs with C++03
|
||||
compilers?</b> 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.</p>
|
||||
<p><b>What good is <i>native </i>endianness?</b> It provides alignment and
|
||||
size guarantees not available from the built-in types. It eases generic
|
||||
programming.</p>
|
||||
<p><b>Why bother with the aligned endian types?</b> 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.</p>
|
||||
<h2><a name="Design">Design</a> considerations for Boost.Endian buffers</h2>
|
||||
<ul>
|
||||
<li>Must be suitable for I/O - in other words, must be memcpyable.</li>
|
||||
<li>Must provide exactly the size and internal byte ordering specified.</li>
|
||||
<li>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.</li>
|
||||
<li>Must work correctly (including using the same defined external
|
||||
representation) regardless of whether a compiler treats char as signed or
|
||||
unsigned.</li>
|
||||
<li>Unaligned types must not cause compilers to insert padding bytes.</li>
|
||||
<li>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.</li>
|
||||
</ul>
|
||||
<h2><a name="C++0x">C++11</a></h2>
|
||||
<p>The availability of the C++11
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">
|
||||
Defaulted Functions</a> feature is detected automatically, and will be used if
|
||||
present to ensure that objects of <code>class endian_buffer</code> are trivial, and
|
||||
thus PODs.</p>
|
||||
<h2><a name="Compilation">Compilation</a></h2>
|
||||
<p>Boost.Endian is implemented entirely within headers, with no need to link to
|
||||
any Boost object libraries.</p>
|
||||
<p>Several macros allow user control over features:</p>
|
||||
<ul>
|
||||
<li>BOOST_ENDIAN_NO_CTORS causes <code>class endian_buffer</code> to have no
|
||||
constructors. The intended use is for compiling user code that must be
|
||||
portable between compilers regardless of C++11
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">
|
||||
Defaulted Functions</a> support. Use of constructors will always fail, <br>
|
||||
</li>
|
||||
<li>BOOST_ENDIAN_FORCE_PODNESS causes BOOST_ENDIAN_NO_CTORS to be defined if
|
||||
the compiler does not support C++11
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">
|
||||
Defaulted Functions</a>. This is ensures that objects of <code>class endian_buffer</code>
|
||||
are PODs, and so can be used in C++03 unions.
|
||||
In C++11, <code>class endian_buffer</code> objects are PODs, even though they have
|
||||
constructors, so can always be used in unions.</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last revised:
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->14 October, 2015<!--webbot bot="Timestamp" endspan i-checksum="38874" --></p>
|
||||
<p>© Copyright Beman Dawes, 2006-2009, 2013</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. See
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/ LICENSE_1_0.txt</a></p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,412 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>Choosing Approach</title>
|
||||
<link href="styles.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="100%">
|
||||
<tr>
|
||||
<td width="339">
|
||||
<a href="../../../index.html">
|
||||
<img src="../../../boost.png" alt="Boost logo" align="middle" border="0" width="277" height="86"></a></td>
|
||||
<td align="middle" width="1253">
|
||||
<font size="6"><b>Choosing the Approach</b></font></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse"
|
||||
bordercolor="#111111" bgcolor="#D7EEFF" width="100%">
|
||||
<tr>
|
||||
<td><b>
|
||||
<a href="index.html">Endian Home</a>
|
||||
<a href="conversion.html">Conversion Functions</a>
|
||||
<a href="arithmetic.html">Arithmetic Types</a>
|
||||
<a href="buffers.html">Buffer Types</a>
|
||||
<a href="choosing_approach.html">Choosing Approach</a></b></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p></p>
|
||||
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" align="right">
|
||||
<tr>
|
||||
<td width="100%" bgcolor="#D7EEFF" align="center">
|
||||
<i><b>Contents</b></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100%" bgcolor="#E8F5FF">
|
||||
<a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Choosing">Choosing between conversion functions,</a><br>
|
||||
<a href="#Choosing">buffer types, and arithmetic types</a><br>
|
||||
<a href="#Characteristics">Characteristics</a><br>
|
||||
<a href="#Endianness-invariants">Endianness invariants</a><br>
|
||||
<a href="#Conversion-explicitness">Conversion explicitness</a><br>
|
||||
<a href="#Arithmetic-operations">Arithmetic operations</a><br>
|
||||
<a href="#Sizes">Sizes</a><br>
|
||||
<a href="#Alignments">Alignments</a><br>
|
||||
<a href="#Design-patterns">Design patterns</a><br>
|
||||
<a href="#As-needed">Convert only as needed (i.e. lazy)</a><br>
|
||||
<a href="#Anticipating-need">Convert in anticipation of need</a><br>
|
||||
<a href="#Convert-generally-as-needed-locally-in-anticipation">Generally
|
||||
as needed, locally in anticipation</a><br>
|
||||
<a href="#Use-cases">Use case examples</a><br>
|
||||
<a href="#Porting-endian-unaware-codebase">Porting endian unaware codebase</a><br>
|
||||
<a href="#Porting-endian-aware-codebase">Porting endian aware codebase</a><br>
|
||||
<a href="#Reliability-arithmetic-speed">Reliability and arithmetic-speed</a><br>
|
||||
<a href="#Reliability-ease-of-use">Reliability and ease-of-use</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>Deciding which is the best endianness approach (conversion functions, buffer
|
||||
types, or arithmetic types) for a particular application involves complex
|
||||
engineering trade-offs. It is hard to assess those trade-offs without some
|
||||
understanding of the different interfaces, so you might want to read the
|
||||
<a href="conversion.html">conversion functions</a>, <a href="buffers.html">
|
||||
buffer types</a>, and <a href="arithmetic.html">arithmetic types</a> pages
|
||||
before diving into this page.</p>
|
||||
|
||||
<h2><a name="Choosing">Choosing</a> between conversion functions, buffer types,
|
||||
and arithmetic types</h2>
|
||||
|
||||
<p>The best approach to endianness for a particular application depends on the interaction between
|
||||
the application's needs and the characteristics of each of the three approaches.</p>
|
||||
|
||||
<p><b>Recommendation:</b> If you are new to endianness, uncertain, or don't want to invest
|
||||
the time to
|
||||
study
|
||||
engineering trade-offs, use <a href="arithmetic.html">endian arithmetic types</a>. They are safe, easy
|
||||
to use, and easy to maintain. Use the
|
||||
<a href="#Anticipating-need"> <i>
|
||||
anticipating need</i></a> design pattern locally around performance hot spots
|
||||
like lengthy loops, if needed.</p>
|
||||
|
||||
<h3><a name="Background">Background</a> </h3>
|
||||
|
||||
<p>A dealing with endianness usually implies a program portability or a data
|
||||
portability requirement, and often both. That means real programs dealing with
|
||||
endianness are usually complex, so the examples shown here would really be
|
||||
written as multiple functions spread across multiple translation units. They
|
||||
would involve interfaces that can not be altered as they are supplied by
|
||||
third-parties or the standard library. </p>
|
||||
|
||||
<h3><a name="Characteristics">Characteristics</a></h3>
|
||||
|
||||
<p>The characteristics that differentiate the three approaches to endianness are the endianness
|
||||
invariants, conversion explicitness, arithmetic operations, sizes available, and
|
||||
alignment requirements.</p>
|
||||
|
||||
<h4><a name="Endianness-invariants">Endianness invariants</a></h4>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p><b>Endian conversion functions</b> use objects of the ordinary C++ arithmetic
|
||||
types like <code>int</code> or <code>unsigned short</code> to hold values. That
|
||||
breaks the implicit invariant that the C++ language rules apply. The usual
|
||||
language rules only apply if the endianness of the object is currently set to the native endianness for the platform. That can
|
||||
make it very hard to reason about logic flow, and result in difficult to
|
||||
find bugs.</p>
|
||||
|
||||
<p>For example:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>struct data_t // big endian
|
||||
{
|
||||
int32_t v1; // description ...
|
||||
int32_t v2; // description ...
|
||||
... additional character data members (i.e. non-endian)
|
||||
int32_t v3; // description ...
|
||||
};
|
||||
|
||||
data_t data;
|
||||
|
||||
read(data);
|
||||
big_to_native_inplace(data.v1);
|
||||
big_to_native_inplace(data.v2);
|
||||
|
||||
...
|
||||
|
||||
++v1;
|
||||
third_party::func(data.v2);
|
||||
|
||||
...
|
||||
|
||||
native_to_big_inplace(data.v1);
|
||||
native_to_big_inplace(data.v2);
|
||||
write(data);
|
||||
</pre>
|
||||
<p>The programmer didn't bother to convert <code>data.v3</code> to native
|
||||
endianness because that member isn't used. A later maintainer needs to pass
|
||||
<code>data.v3</code> to the third-party function, so adds <code>third_party::func(data.v3);</code>
|
||||
somewhere deep in the code. This causes a silent failure because the usual
|
||||
invariant that an object of type <code>int32_t</code> holds a value as
|
||||
described by the C++ core language does not apply.</p>
|
||||
</blockquote>
|
||||
<p><b>Endian buffer and arithmetic types</b> hold values internally as arrays of
|
||||
characters with an invariant that the endianness of the array never changes.
|
||||
That makes these types easier to use and programs easier to maintain. </p>
|
||||
<p>Here is the same example, using an endian arithmetic type:</p>
|
||||
<blockquote>
|
||||
<pre>struct data_t
|
||||
{
|
||||
big_int32_t v1; // description ...
|
||||
big_int32_t v2; // description ...
|
||||
... additional character data members (i.e. non-endian)
|
||||
big_int32_t v3; // description ...
|
||||
};
|
||||
|
||||
data_t data;
|
||||
|
||||
read(data);
|
||||
|
||||
...
|
||||
|
||||
++v1;
|
||||
third_party::func(data.v2);
|
||||
|
||||
...
|
||||
|
||||
write(data);
|
||||
</pre>
|
||||
<p>A later maintainer can add <code>third_party::func(data.v3)</code>and it
|
||||
will just-work.</p>
|
||||
</blockquote>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="Conversion-explicitness">Conversion explicitness</a></h4>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p><b>Endian conversion functions</b> and <b>buffer types</b> never perform
|
||||
implicit conversions. This gives users explicit control of when conversion
|
||||
occurs, and may help avoid unnecessary conversions.</p>
|
||||
|
||||
<p><b>Endian arithmetic types</b> perform conversion implicitly. That makes
|
||||
these types very easy to use, but can result in unnecessary conversions. Failure
|
||||
to hoist conversions out of inner loops can bring a performance penalty.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="Arithmetic-operations">Arithmetic operations</a></h4>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p><b>Endian conversion functions</b> do not supply arithmetic
|
||||
operations, but this is not a concern since this approach uses ordinary C++
|
||||
arithmetic types to hold values.</p>
|
||||
|
||||
<p><b>Endian buffer types</b> do not supply arithmetic operations. Although this
|
||||
approach avoids unnecessary conversions, it can result in the introduction of
|
||||
additional variables and confuse maintenance programmers.</p>
|
||||
|
||||
<p><b>Endian</b> <b>arithmetic types</b> do supply arithmetic operations. They
|
||||
are very easy to use if lots of arithmetic is involved. </p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="Sizes">Sizes</a></h4>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p><b>Endianness conversion functions</b> only support 1, 2, 4, and 8 byte
|
||||
integers. That's sufficient for many applications.</p>
|
||||
|
||||
<p><b>Endian buffer and arithmetic types</b> support 1, 2, 3, 4, 5, 6, 7, and 8
|
||||
byte integers. For an application where memory use or I/O speed is the limiting
|
||||
factor, using sizes tailored to application needs can be useful.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="Alignments">Alignments</a></h4>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p><b>Endianness conversion functions</b> only support aligned integer and
|
||||
floating-point types. That's sufficient for most applications.</p>
|
||||
|
||||
<p><b>Endian buffer and arithmetic types</b> support both aligned and unaligned
|
||||
integer and floating-point types. Unaligned types are rarely needed, but when
|
||||
needed they are often very useful and workarounds are painful. For example,</p>
|
||||
|
||||
<blockquote>
|
||||
<p>Non-portable code like this:<blockquote>
|
||||
<pre>struct S {
|
||||
uint16_t a; // big endian
|
||||
uint32_t b; // big endian
|
||||
} __attribute__ ((packed));</pre>
|
||||
</blockquote>
|
||||
<p>Can be replaced with portable code like this:</p>
|
||||
<blockquote>
|
||||
<pre>struct S {
|
||||
big_uint16_ut a;
|
||||
big_uint32_ut b;
|
||||
};</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<h3><a name="Design-patterns">Design patterns</a></h3>
|
||||
|
||||
<p>Applications often traffic in endian data as records or packets containing
|
||||
multiple endian data elements. For simplicity, we will just call them records.</p>
|
||||
|
||||
<p>If desired endianness differs from native endianness, a conversion has to be
|
||||
performed. When should that conversion occur? Three design patterns have
|
||||
evolved.</p>
|
||||
|
||||
<h4><a name="As-needed">Convert only as needed</a> (i.e. lazy)</h4>
|
||||
|
||||
<p>This pattern defers conversion to the point in the code where the data
|
||||
element is actually used.</p>
|
||||
|
||||
<p>This pattern is appropriate when which endian element is actually used varies
|
||||
greatly according to record content or other circumstances</p>
|
||||
|
||||
<h4><a name="Anticipating-need">Convert in anticipation of need</a></h4>
|
||||
|
||||
<p>This pattern performs conversion to native endianness in anticipation of use,
|
||||
such as immediately after reading records. If needed, conversion to the output
|
||||
endianness is performed after all possible needs have passed, such as just
|
||||
before writing records.</p>
|
||||
|
||||
<p>One implementation of this pattern is to create a proxy record with
|
||||
endianness converted to native in a read function, and expose only that proxy to
|
||||
the rest of the implementation. If a write function, if needed, handles the
|
||||
conversion from native to the desired output endianness.</p>
|
||||
|
||||
<p>This pattern is appropriate when all endian elements in a record are
|
||||
typically used regardless of record content or other circumstances</p>
|
||||
|
||||
<h4><a name="Convert-generally-as-needed-locally-in-anticipation">Convert
|
||||
only as needed, except locally in anticipation of need</a></h4>
|
||||
|
||||
<p>This pattern in general defers conversion but for specific local needs does
|
||||
anticipatory conversion. Although particularly appropriate when coupled with the endian buffer
|
||||
or arithmetic types, it also works well with the conversion functions.</p>
|
||||
|
||||
<p>Example:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>struct data_t
|
||||
{
|
||||
big_int32_t v1;
|
||||
big_int32_t v2;
|
||||
big_int32_t v3;
|
||||
};
|
||||
|
||||
data_t data;
|
||||
|
||||
read(data);
|
||||
|
||||
...
|
||||
++v1;
|
||||
...
|
||||
|
||||
int32_t v3_temp = data.v3; // hoist conversion out of loop
|
||||
|
||||
for (int32_t i = 0; i < <i><b>large-number</b></i>; ++i)
|
||||
{
|
||||
... <i><b>lengthy computation that accesses </b></i>v3_temp<i><b> many times</b></i> ...
|
||||
}
|
||||
data.v3 = v3_temp;
|
||||
|
||||
write(data);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p dir="ltr">In general the above pseudo-code leaves conversion up to the endian
|
||||
arithmetic type <code>big_int32_t</code>. But to avoid conversion inside the
|
||||
loop, a temporary is created before the loop is entered, and then used to set
|
||||
the new value of <code>data.v3</code> after the loop is complete.</p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p dir="ltr">Question: Won't the compiler's optimizer hoist the conversion out
|
||||
of the loop anyhow?</p>
|
||||
|
||||
<p dir="ltr">Answer: VC++ 2015 Preview, and probably others, does not, even for
|
||||
a toy test program. Although the savings is small (two register <code>
|
||||
<span style="font-size: 85%">bswap</span></code> instructions), the cost might
|
||||
be significant if the loop is repeated enough times. On the other hand, the
|
||||
program may be so dominated by I/O time that even a lengthy loop will be
|
||||
immaterial.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<h3><a name="Use-cases">Use case examples</a></h3>
|
||||
|
||||
<h4><a name="Porting-endian-unaware-codebase">Porting endian unaware codebase</a></h4>
|
||||
|
||||
<p>An existing codebase runs on big endian systems. It does not
|
||||
currently deal with endianness. The codebase needs to be modified so it can run
|
||||
on little endian systems under various operating systems. To ease
|
||||
transition and protect value of existing files, external data will continue to
|
||||
be maintained as big endian.</p>
|
||||
|
||||
<p dir="ltr">The <a href="arithmetic.html">endian
|
||||
arithmetic approach</a> is recommended to meet these needs. A relatively small
|
||||
number of header files dealing with binary I/O layouts need to change types. For
|
||||
example,
|
||||
<code>short</code> or <code>int16_t</code> would change to <code>big_int16_t</code>. No
|
||||
changes are required for <code>.cpp</code> files.</p>
|
||||
|
||||
<h4><a name="Porting-endian-aware-codebase">Porting endian aware codebase</a></h4>
|
||||
|
||||
<p>An existing codebase runs on little-endian Linux systems. It already
|
||||
deals with endianness via
|
||||
<a href="http://man7.org/linux/man-pages/man3/endian.3.html">Linux provided
|
||||
functions</a>. Because of a business merger, the codebase has to be quickly
|
||||
modified for Windows and possibly other operating systems, while still
|
||||
supporting Linux. The codebase is reliable and the programmers are all
|
||||
well-aware of endian issues. </p>
|
||||
|
||||
<p dir="ltr">These factors all argue for an <a href="conversion.html">endian conversion
|
||||
approach</a> that just mechanically changes the calls to <code>htobe32</code>,
|
||||
etc. to <code>boost::endian::native_to_big</code>, etc. and replaces <code><endian.h></code>
|
||||
with <code><boost/endian/conversion.hpp></code>.</p>
|
||||
|
||||
<h4><a name="Reliability-arithmetic-speed">Reliability and arithmetic-speed</a></h4>
|
||||
|
||||
<p>A new, complex, multi-threaded application is to be developed that must run
|
||||
on little endian machines, but do big endian network I/O. The developers believe
|
||||
computational speed for endian variable is critical but have seen numerous bugs
|
||||
result from inability to reason about endian conversion state. They are also
|
||||
worried that future maintenance changes could inadvertently introduce a lot of
|
||||
slow conversions if full-blown endian arithmetic types are used.</p>
|
||||
|
||||
<p>The <a href="buffers.html">endian buffers</a> approach is made-to-order for
|
||||
this use case.</p>
|
||||
|
||||
<h4><a name="Reliability-ease-of-use">Reliability and ease-of-use</a></h4>
|
||||
|
||||
<p>A new, complex, multi-threaded application is to be developed that must run
|
||||
on little endian machines, but do big endian network I/O. The developers believe
|
||||
computational speed for endian variables is <b>not critical</b> but have seen
|
||||
numerous bugs result from inability to reason about endian conversion state.
|
||||
They are also concerned about ease-of-use both during development and long-term
|
||||
maintenance.</p>
|
||||
|
||||
<p>Removing concern about conversion speed and adding concern about ease-of-use
|
||||
tips the balance strongly in favor the <a href="arithmetic.html">endian
|
||||
arithmetic approach</a>.</p>
|
||||
|
||||
<hr>
|
||||
<p>Last revised:
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->19 January, 2015<!--webbot bot="Timestamp" endspan i-checksum="38903" --></p>
|
||||
<p>© Copyright Beman Dawes, 2011, 2013, 2014</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. See
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/ LICENSE_1_0.txt</a></p>
|
||||
|
||||
<p> </p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,405 +0,0 @@
|
||||
<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns="http://www.w3.org/TR/REC-html40">
|
||||
|
||||
<head>
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
|
||||
<title>Endian Conversion Functions</title>
|
||||
<link href="styles.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="100%">
|
||||
<tr>
|
||||
<td>
|
||||
<a href="../../../index.html">
|
||||
<img src="../../../boost.png" alt="Boost logo" align="middle" border="0" width="277" height="86" ></a></td>
|
||||
<td align="middle">
|
||||
<b>
|
||||
<font size="6">Endian Conversion Functions</font></b></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF" width="100%">
|
||||
<tr>
|
||||
<td><b>
|
||||
<a href="index.html">Endian Home</a>
|
||||
<a href="conversion.html">Conversion Functions</a>
|
||||
<a href="arithmetic.html">Arithmetic Types</a>
|
||||
<a href="buffers.html">Buffer Types</a>
|
||||
<a href="choosing_approach.html">Choosing Approach</a></b></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p></p>
|
||||
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" align="right">
|
||||
<tr>
|
||||
<td width="100%" bgcolor="#D7EEFF" align="center">
|
||||
<i><b>Contents</b></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100%" bgcolor="#E8F5FF">
|
||||
<a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Reference">Reference</a><br>
|
||||
<a href="#Synopsis">Synopsis</a><br>
|
||||
<a href="#Requirements">Requirements</a><br>
|
||||
<code><a href="#EndianReversible">EndianReversible</a></code><br>
|
||||
<a href="#Customization-points">Customization for
|
||||
UDTs</a><br>
|
||||
<a href="#Functions">Functions</a><br>
|
||||
<a href="#FAQ">FAQ</a><br>
|
||||
<a href="#Acknowledgements">Acknowledgements</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>Header <a href="../include/boost/endian/conversion.hpp">boost/endian/conversion.hpp</a>
|
||||
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.</p>
|
||||
|
||||
<h2><a name="Reference">Reference</a></h2>
|
||||
|
||||
<p>Functions are implemented <code>inline</code> if appropriate.<code> </code>
|
||||
For C++03 compilers, <code> noexcept</code> is
|
||||
elided.
|
||||
Boost scoped enum emulation is used so that the library still works for compilers that do not support scoped enums.</p>
|
||||
|
||||
<h3><a name="Definitions">Definitions</a></h3>
|
||||
<p><b><i>Endianness</i></b> refers to the ordering of bytes within internal or
|
||||
external integers and other arithmetic data. Most-significant byte first is
|
||||
called <b><i>big endian</i></b> ordering. Least-significant byte first is called
|
||||
<b><i>little endian</i></b> ordering. Other orderings are possible and some CPU
|
||||
architectures support both big and little ordering.</p>
|
||||
<blockquote>
|
||||
<p>[<i>Note:</i> The names are derived from
|
||||
<a href="http://en.wikipedia.org/wiki/Jonathan_Swift" title="Jonathan Swift">
|
||||
Jonathan Swift</a>'s satirical novel <i>
|
||||
<a href="http://en.wikipedia.org/wiki/Gulliver's_Travels" title="Gulliver's Travels">
|
||||
Gulliver’s Travels</a></i>, where rival kingdoms opened their soft-boiled eggs
|
||||
at different ends. Wikipedia has an extensive description of
|
||||
<a href="https://en.wikipedia.org/wiki/Endianness">Endianness</a>. <i>—end note</i>]</p>
|
||||
</blockquote>
|
||||
<p>The standard integral types (C++std 3.9.1) except <code>bool</code>
|
||||
are collectively called the <b> <i>endian types</i></b>.</p>
|
||||
|
||||
<h3>
|
||||
Header <code><boost/endian/conversion.hpp></code>
|
||||
<a name="Synopsis">Synopsis</a></h3>
|
||||
|
||||
<pre>#define BOOST_ENDIAN_INTRINSIC_MSG \
|
||||
"<b><font face="Arial"><i>message describing presence or absence of intrinsics</i></font></b>"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace endian
|
||||
{
|
||||
enum class <a name="order">order</a>
|
||||
{
|
||||
native = <b><i>see below,
|
||||
</i></b> big = <b><i>see below</i></b>,
|
||||
little = <b><i>see below</i></b>,
|
||||
<b><i> </i></b>};
|
||||
|
||||
int8_t <a href="#endian_reverse">endian_reverse</a>(int8_t x) noexcept;
|
||||
int16_t <a href="#endian_reverse">endian_reverse</a>(int16_t x) noexcept;
|
||||
int32_t <a href="#endian_reverse">endian_reverse</a>(int32_t x) noexcept;
|
||||
int64_t <a href="#endian_reverse">endian_reverse</a>(int64_t x) noexcept;
|
||||
uint8_t <a href="#endian_reverse">endian_reverse</a>(uint8_t x) noexcept;
|
||||
uint16_t <a href="#endian_reverse">endian_reverse</a>(uint16_t x) noexcept;
|
||||
uint32_t <a href="#endian_reverse">endian_reverse</a>(uint32_t x) noexcept;
|
||||
uint64_t <a href="#endian_reverse">endian_reverse</a>(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</pre>
|
||||
<p>The values of <code>order::little</code> and <code>order::big</code> shall
|
||||
not be equal to one another. </p>
|
||||
<p><a name="native-order-specification"></a>The value of <code>order::native</code>
|
||||
shall be:</p>
|
||||
<ul>
|
||||
<li>equal to <code>order::big</code> if the execution environment is big
|
||||
endian, otherwise</li>
|
||||
<li>equal to <code>order::little</code> if the execution environment is little
|
||||
endian, otherwise</li>
|
||||
<li>unequal to both <code>order::little</code> and <code>order::big</code>.</li>
|
||||
</ul>
|
||||
<h3><a name="Requirements">Requirements</a></h3>
|
||||
<h4><a name="Template-argument-requirements">Template argument requirements</a></h4>
|
||||
<p>The template definitions in the <code>boost/endian/conversion.hpp</code>
|
||||
header refer to various named requirements whose details are set out in the
|
||||
tables in this subsection. In these tables, <code>T</code> is an object or
|
||||
reference type to be supplied by a C++ program instantiating a template; <code>x</code>
|
||||
is a value of type (possibly <code>const</code>) <code>T</code>; <code>mlx</code> is a
|
||||
modifiable lvalue of type <code>T</code>.</p>
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
|
||||
<tr>
|
||||
<td colspan="3" align="center"><b><code><a name="EndianReversible">EndianReversible</a></code></b>
|
||||
requirements (in addition to <b><code>CopyConstructible</code></b>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Expression</b></td>
|
||||
<td><b>Return<br>
|
||||
type</b></td>
|
||||
<td><b>Requirements</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>endian_reverse(x)</code></td>
|
||||
<td align="center" valign="top"><code>T</code></td>
|
||||
<td> <code>T</code> is an endian type or a class type.<p>If <code>T</code> is
|
||||
an endian type, returns the value of <code>x</code> with the order of bytes
|
||||
reversed.</p>
|
||||
<p>If <code>T</code> is a class type, the function:</p>
|
||||
<ul>
|
||||
<li>Returns the value of <code>x</code>
|
||||
with the order of bytes reversed for all data members of types or arrays of
|
||||
types that meet the <code>EndianReversible</code> requirements, and;</li>
|
||||
<li>Is a non-member function in the same namespace as <code>T</code> that
|
||||
can be found by argument dependent lookup (ADL). </li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p> </p>
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
|
||||
<tr>
|
||||
<td colspan="2" align="center"><b><code><a name="EndianReversibleInplace">EndianReversibleInplace</a></code></b>
|
||||
requirements (in addition to <b><code>CopyConstructible</code></b>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Expression</b></td>
|
||||
<td><b>Requirements</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>endian_reverse_inplace(mlx)</code></td>
|
||||
<td> <code>T</code> is an endian type or a class type.<p>If <code>T</code> is
|
||||
an endian type, reverses the order of bytes in <code>mlx</code>.</p>
|
||||
<p>If <code>T</code> is a class type, the function:</p>
|
||||
<ul>
|
||||
<li>Reverses the order of bytes of all data members of <code>mlx</code>
|
||||
that have types or arrays of
|
||||
types that meet the <code>EndianReversible</code> or <code>EndianReversibleInplace</code>
|
||||
requirements, and;</li>
|
||||
<li>Is a non-member function in the same namespace as <code>T</code> that
|
||||
can be found by argument dependent lookup (ADL). </li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p> [<i>Note:</i> Because there is a function template for <code>endian_reverse_inplace</code>
|
||||
that calls <code>endian_reverse</code>, only <code>endian_reverse</code>
|
||||
is required for a user-defined type to meet the <code>EndianReversibleInplace</code>
|
||||
requirements. Although User-defined types are not required to supply an <code>endian_reverse_inplace</code>
|
||||
function, doing so may improve efficiency. <i> —end note</i>]</p>
|
||||
|
||||
<h4> <a name="Customization-points">Customization points</a> for user-defined types (<a name="UDT">UDT</a>s)</h4>
|
||||
|
||||
<p> This subsection describes requirements on the Endian library's implementation.</p>
|
||||
|
||||
<p> The library's function templates requiring <code>
|
||||
<a href="#EndianReversible">EndianReversible</a></code> are
|
||||
required to perform reversal of endianness if needed by making an unqualified
|
||||
call to <code>endian_reverse()</code>.</p>
|
||||
|
||||
<p> The library's function templates requiring <code>
|
||||
<a href="#EndianReversibleInplace">EndianReversibleInplace</a></code> are required to perform reversal of endianness if needed by making an
|
||||
unqualified call to <code>endian_reverse_inplace()</code>.</p>
|
||||
|
||||
<p> See <b><code>example/udt_conversion_example.cpp</code></b> for an example user-defined type.</p>
|
||||
|
||||
<h3><a name="Functions">Functions</a></h3>
|
||||
<pre><a name="endian_reverse"></a>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;</pre>
|
||||
<blockquote>
|
||||
<p><i>Returns:</i> <i><code>x</code></i>, with the order of its
|
||||
constituent bytes reversed.</p>
|
||||
<p><i>Remarks:</i> The type of <i><code>x</code></i> meets the <code>EndianReversible</code> requirements.</p>
|
||||
<p>[<i>Note:</i> The Boost.Endian library does not provide overloads for the C++ standard library
|
||||
supplied types. <i>—end note</i>]</p>
|
||||
</blockquote>
|
||||
|
||||
<pre>template <class EndianReversible>
|
||||
EndianReversible big_to_native(EndianReversible x) noexcept;</pre>
|
||||
<blockquote>
|
||||
<p>
|
||||
<i>Returns:</i> <code>conditional_reverse<order::big, order::native>(x)</code>.</p>
|
||||
</blockquote>
|
||||
<pre>template <class EndianReversible>
|
||||
EndianReversible native_to_big(EndianReversible x) noexcept; </pre>
|
||||
<blockquote>
|
||||
<p><i>Returns:</i> <code>conditional_reverse<order::native, order::big>(x)</code>.</p>
|
||||
</blockquote>
|
||||
<pre>template <class EndianReversible>
|
||||
EndianReversible little_to_native(EndianReversible x) noexcept; </pre>
|
||||
<blockquote>
|
||||
<p><i>Returns:</i> <code>conditional_reverse<order::little, order::native>(x)</code>.</p>
|
||||
</blockquote>
|
||||
<pre>template <class EndianReversible>
|
||||
EndianReversible native_to_little(EndianReversible x) noexcept; </pre>
|
||||
<blockquote>
|
||||
<p><i>Returns:</i> <code>conditional_reverse<order::native, order::little>(x)</code>.</p>
|
||||
</blockquote>
|
||||
<pre>template <order O1, order O2, class EndianReversible>
|
||||
EndianReversible conditional_reverse(EndianReversible x) noexcept; </pre>
|
||||
<blockquote>
|
||||
<p><i>Returns:</i> <code>x</code> if <code>O1 == O2,</code> otherwise <code>endian_reverse(x)</code>.</p>
|
||||
<p><i>Remarks: </i>Whether <code>x</code> or <code>endian_reverse(x)</code> is to be returned shall be determined at compile time.</p>
|
||||
</blockquote>
|
||||
<pre>template <class EndianReversible>
|
||||
EndianReversible conditional_reverse(EndianReversible x,
|
||||
order order1, order order2) noexcept; </pre>
|
||||
<blockquote>
|
||||
<p><i>Returns:</i> <code>order1 == order2 ? x : endian_reverse(x)</code>.</p>
|
||||
</blockquote>
|
||||
|
||||
<pre>template <class EndianReversible>
|
||||
void endian_reverse_inplace(EndianReversible& x) noexcept; </pre>
|
||||
|
||||
<blockquote>
|
||||
<p><i>Effects:</i> <code>x</code> <code>= endian_reverse(x)</code>.</p>
|
||||
</blockquote>
|
||||
|
||||
<pre>template <class EndianReversibleInplace>
|
||||
void big_to_native_inplace(EndianReversibleInplace& x) noexcept; </pre>
|
||||
<blockquote>
|
||||
<p>
|
||||
<i>Effects:</i> <code>conditional_reverse_inplace<order::big, order::native>(x)</code>.</p>
|
||||
</blockquote>
|
||||
<pre>template <class EndianReversibleInplace>
|
||||
void native_to_big_inplace(EndianReversibleInplace& x) noexcept; </pre>
|
||||
<blockquote>
|
||||
<p>
|
||||
<i>Effects:</i> <code>conditional_reverse_inplace<order::native, order::big>(x)</code>.</p>
|
||||
</blockquote>
|
||||
<pre>template <class EndianReversibleInplace>
|
||||
void little_to_native_inplace(EndianReversibleInplace& x) noexcept; </pre>
|
||||
<blockquote>
|
||||
<p>
|
||||
<i>Effects:</i> <code>conditional_reverse_inplace<order::little, order::native>(x)</code>.</p>
|
||||
</blockquote>
|
||||
<pre>template <class EndianReversibleInplace>
|
||||
void native_to_little_inplace(EndianReversibleInplace& x) noexcept; </pre>
|
||||
<blockquote>
|
||||
<p>
|
||||
<i>Effects:</i> <code>conditional_reverse_inplace<order::native, order::little>(x)</code>.</p>
|
||||
</blockquote>
|
||||
<pre>template <order O1, order O2, class EndianReversibleInplace>
|
||||
void conditional_reverse_inplace(EndianReversibleInplace& x) noexcept; </pre>
|
||||
<blockquote>
|
||||
<p><i>Effects:</i> None if <code>O1 == O2,</code> otherwise <code>endian_reverse_inplace(x)</code>.</p>
|
||||
<p><i>Remarks: </i>Which effect applies shall be determined at compile time.</p>
|
||||
</blockquote>
|
||||
<pre>template <class EndianReversibleInplace>
|
||||
void conditional_reverse_inplace(EndianReversibleInplace& x,
|
||||
order order1, order order2) noexcept; </pre>
|
||||
|
||||
|
||||
<blockquote>
|
||||
<p><i>Effects: </i>If <code>order1 == order2</code> then <code>endian_reverse_inplace(x)</code>.</p>
|
||||
</blockquote>
|
||||
|
||||
|
||||
<h2> <a name="FAQ">FAQ</a></h2>
|
||||
|
||||
<p>See the <a href="index.html#FAQ">Endian home page</a> FAQ for a library-wide
|
||||
FAQ.</p>
|
||||
|
||||
<p><b>Why are both value returning and modify-in-place functions provided?</b></p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<p><b>Why are exact-length 8, 16, 32, and 64-bit integers supported rather than the built-in
|
||||
char, short, int, long, long long, etc?</b></p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<p><b>Why not use the Linux names (htobe16, htole16, be16toh, le16toh, etc.) ?</b></p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<h2><a name="Acknowledgements">Acknowledgements</a></h2><p>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 <b><code>boost/endian/detail/intrinsic.hpp</code></b>.
|
||||
Pierre Talbot provided the <code>int8_t endian_reverse()</code> and templated
|
||||
<code>endian_reverse_inplace()</code> implementations.</p>
|
||||
<hr>
|
||||
<p>Last revised:
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->14 October, 2015<!--webbot bot="Timestamp" endspan i-checksum="38874" --></p>
|
||||
<p>© Copyright Beman Dawes, 2011, 2013</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. See <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/ LICENSE_1_0.txt</a></p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,97 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<title>Floating Point Concerns</title>
|
||||
<link href="styles.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Floating Point Concerns</h1>
|
||||
|
||||
<p>Consider this simple implementation of <code>endian_reverse</code>:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>template <class T>
|
||||
inline T endian_reverse(T x) BOOST_NOEXCEPT
|
||||
{
|
||||
std::reverse(reinterpret_cast<unsigned char*>(&x),
|
||||
reinterpret_cast<unsigned char*>(&x) + sizeof(T));
|
||||
return x;
|
||||
}</pre>
|
||||
</blockquote>
|
||||
<p><b>Under what conditions with this code fail?</b></p>
|
||||
<p dir="ltr">It will fail if an object of type <code>T</code> has one or more
|
||||
bit patterns that cause a failure. Failures usually occur when an invalid
|
||||
or otherwise special bit pattern is loaded into or saved from a hardware
|
||||
register.</p>
|
||||
<p dir="ltr">The problem could in theory occur with both integers and floating
|
||||
point numbers, but the <a href="http://en.wikipedia.org/wiki/Two's_complement">
|
||||
two's complement integers</a> ubiquitous in modern computer architectures do not
|
||||
have any invalid or otherwise special bit patterns that cause failure when
|
||||
byte-wise reversed.</p>
|
||||
<p dir="ltr">But floating point numbers are a different story. Even if we limit
|
||||
discussion to IEEE 754 (aka ISO/IEC/IEEE 60559) binary representations of 4 and
|
||||
8 byte sizes, several problems are easy to demonstrate:</p>
|
||||
<ul>
|
||||
<li dir="ltr">
|
||||
<p dir="ltr">...</li>
|
||||
</ul>
|
||||
<h2 dir="ltr">Safe interfaces and possible reference implementations</h2>
|
||||
<h3 dir="ltr">In-place interface</h3>
|
||||
<blockquote>
|
||||
<pre dir="ltr">template <class T>
|
||||
inline void endian_reverse_inplace(T& x)
|
||||
{
|
||||
std::reverse(reinterpret_cast<unsigned char*>(&x),
|
||||
reinterpret_cast<unsigned char*>(&x) + sizeof(T));
|
||||
}</pre>
|
||||
</blockquote>
|
||||
<p dir="ltr">This is the same as the current (i.e integer) customization point
|
||||
interface, so there is no need for any change.</p>
|
||||
<p dir="ltr"><b>Warning:</b> Even thought <code>x</code> may have had a valid
|
||||
value on the originating platform, after calling this function the value of
|
||||
<code>x</code> may differ or be invalid on this platform.</p>
|
||||
<h3 dir="ltr">Copy interface</h3>
|
||||
<blockquote>
|
||||
<pre dir="ltr">template <class T>
|
||||
inline void endian_reverse_copy(const T& from, T& to)
|
||||
{
|
||||
std::reverse_copy(reinterpret_cast<const unsigned char*>(&from),
|
||||
reinterpret_cast<const unsigned char*>(&from) + sizeof(T),
|
||||
reinterpret_cast<unsigned char*>(&to));
|
||||
}</pre>
|
||||
</blockquote>
|
||||
<p><b>Warning:</b> Even thought <code>from</code> may have been a valid value on
|
||||
the originating platform, after calling this function the value of <code>to</code>
|
||||
may differ or be invalid on this platform.</p>
|
||||
<h3>Return-by-value interface</h3>
|
||||
<blockquote>
|
||||
<pre>template <class T>
|
||||
inline T endian_reverse_to_native(<span style="background-color: #FFFF00">const</span><span style="background-color: #FFFF00"> T&</span> x) BOOST_NOEXCEPT
|
||||
{
|
||||
T tmp;
|
||||
std::reverse_copy(reinterpret_cast<const unsigned char*>(&x),
|
||||
reinterpret_cast<const unsigned char*>(&x) + sizeof(T),
|
||||
reinterpret_cast<unsigned char*>(&tmp));
|
||||
return tmp;
|
||||
}</pre>
|
||||
</blockquote>
|
||||
<p><b>Warning:</b> Even thought <code>x</code> may have had a valid value on the
|
||||
originating platform, the value of returned by this function may differ or be
|
||||
invalid on this platform.</p>
|
||||
<h2>Acknowledgements</h2>
|
||||
<hr>
|
||||
<p>Last revised: <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->27 March, 2015<!--webbot bot="Timestamp" endspan i-checksum="28924" --></p>
|
||||
<p><EFBFBD> Copyright Beman Dawes, 2015</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. See <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/ LICENSE_1_0.txt</a></p>
|
||||
|
||||
<p> </p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
606
doc/index.html
606
doc/index.html
@ -1,606 +0,0 @@
|
||||
<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns="http://www.w3.org/TR/REC-html40">
|
||||
|
||||
<head>
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
|
||||
<title>Endian Library</title>
|
||||
<link href="styles.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="100%">
|
||||
<tr>
|
||||
<td width="339">
|
||||
<a href="../../../index.html">
|
||||
<img src="../../../boost.png" alt="Boost logo" align="middle" border="0" width="277" height="86"></a></td>
|
||||
<td align="middle" width="1253">
|
||||
<b>
|
||||
<font size="6">Endian Library</font></b></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse"
|
||||
bordercolor="#111111" bgcolor="#D7EEFF" width="100%">
|
||||
<tr>
|
||||
<td><b>
|
||||
<a href="index.html">Endian Home</a>
|
||||
<a href="conversion.html">Conversion Functions</a>
|
||||
<a href="arithmetic.html">Arithmetic Types</a>
|
||||
<a href="buffers.html">Buffer Types</a>
|
||||
<a href="choosing_approach.html">Choosing Approach</a></b></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p></p>
|
||||
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" align="right">
|
||||
<tr>
|
||||
<td width="100%" bgcolor="#D7EEFF" align="center">
|
||||
<i><b>Contents</b></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100%" bgcolor="#E8F5FF">
|
||||
<a href="#Abstract">Abstract</a><br>
|
||||
<a href="#Introduction-to-endianness">Introduction to endianness</a><br>
|
||||
<a href="#Introduction">Introduction to the Boost.Endian library</a><br>
|
||||
<a href="#Choosing">Choosing between conversion functions,</a><br>
|
||||
<a href="#Choosing">buffer types, and arithmetic types</a><br>
|
||||
<a href="#Intrinsic">Built-in support for Intrinsics</a><br>
|
||||
<a href="#Performance">Performance</a><br>
|
||||
<a href="#Timings">Timings</a><br>
|
||||
<a href="#FAQ">Overall FAQ</a><br>
|
||||
<a href="#Release-history">Release history</a><br>
|
||||
<a href="#Changes-requested-by-formal-review">Changes
|
||||
requested by formal review</a><br>
|
||||
<a href="#Other-changes-since-formal-review">Other changes since
|
||||
formal review</a><br>
|
||||
<a href="#Compatibility">Compatibility with interim releases</a><br>
|
||||
<a href="#C++03-support">C++03 support for C++11 features</a><br>
|
||||
<a href="#Future-directions">Future directions</a><br>
|
||||
<a href="#Acknowledgements">Acknowledgements</a><br>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2><a name="Abstract">Abstract</a></h2>
|
||||
|
||||
<p>Boost.Endian provides facilities to manipulate the
|
||||
<a href="#Introduction-to-endianness">endianness</a> of integers and user-defined types.</p>
|
||||
<ul>
|
||||
<li>Three approaches to endianness are supported. Each has a
|
||||
long history of successful use, and each approach has use cases where it is
|
||||
preferred over the other approaches.<br>
|
||||
</li>
|
||||
<li>Primary uses:<br>
|
||||
<ul>
|
||||
<li>Data portability. The Endian library supports binary data exchange, via either external media or network transmission,
|
||||
regardless of platform endianness.<br>
|
||||
</li>
|
||||
<li>Program portability. POSIX-based and
|
||||
Windows-based operating systems traditionally supply libraries with
|
||||
non-portable functions to perform endian conversion. There are at least four
|
||||
incompatible sets of functions in common use. The Endian library is
|
||||
portable across all C++ platforms.<br>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
<li>Secondary use: Minimizing data size via sizes and/or alignments not supported by the
|
||||
standard C++ integer types.</li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="Introduction-to-endianness">Introduction to endianness</a></h2>
|
||||
|
||||
<p>Consider the following code:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>int16_t i = 0x0102;
|
||||
FILE * file = fopen("test.bin", "wb"); // binary file!
|
||||
fwrite(&i, sizeof(int16_t), 1, file);
|
||||
fclose(file);</pre>
|
||||
</blockquote>
|
||||
<p>On OS X, Linux, or Windows systems with an Intel CPU, a hex dump
|
||||
of the "test.bin" output file produces:</p>
|
||||
<blockquote>
|
||||
<p><code>0201</code></p>
|
||||
</blockquote>
|
||||
<p>On OS X systems with a PowerPC CPU, or Solaris systems with a SPARC CPU, a hex dump of the "test.bin"
|
||||
output file produces:</p>
|
||||
<blockquote>
|
||||
<p><code>0102</code></p>
|
||||
</blockquote>
|
||||
<p>What's happening here is that Intel CPUs order the bytes of an integer with
|
||||
the least-significant byte first, while SPARC CPUs place the most-significant
|
||||
byte first. Some CPUs, such as the PowerPC, allow the operating system to
|
||||
choose which ordering applies.</p>
|
||||
<p><a name="definition"></a>Most-significant-byte-first ordering is traditionally called "big endian"
|
||||
ordering and least-significant-byte-first is traditionally called
|
||||
"little-endian" ordering. The names are derived from
|
||||
<a href="http://en.wikipedia.org/wiki/Jonathan_Swift" title="Jonathan Swift">
|
||||
Jonathan Swift</a>'s satirical novel <i>
|
||||
<a href="http://en.wikipedia.org/wiki/Gulliver's_Travels" title="Gulliver's Travels">
|
||||
Gulliver’s Travels</a></i>, where rival kingdoms opened their soft-boiled eggs
|
||||
at different ends.</p>
|
||||
<p>See Wikipedia's
|
||||
<a href="http://en.wikipedia.org/wiki/Endianness">Endianness</a> article for an
|
||||
extensive discussion of endianness.</p>
|
||||
<p>Programmers can usually ignore endianness, except when reading a core
|
||||
dump on little-endian systems. But programmers have to deal with endianness when exchanging binary integers and binary floating point
|
||||
values between computer systems with differing endianness, whether by physical file transfer or over a network.
|
||||
And programmers may also want to use the library when minimizing either internal or
|
||||
external data sizes is advantageous.</p>
|
||||
<h2><a name="Introduction">Introduction</a> to the Boost.Endian library</h2>
|
||||
|
||||
<p>Boost.Endian provides three different approaches to dealing with
|
||||
|
||||
endianness. All three approaches support integers and user-define types (UDTs).</p>
|
||||
|
||||
<p>Each approach has a long history of successful use, and each approach has use
|
||||
cases where it is preferred to the other approaches.</p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p><b><a href="conversion.html">Endian conversion functions</a> -</b> The
|
||||
application uses the built-in integer types to hold values, and calls the
|
||||
provided conversion functions to convert byte ordering as needed. Both mutating
|
||||
and non-mutating conversions are supplied, and each comes in unconditional and
|
||||
conditional variants.</p>
|
||||
|
||||
<p><b><a href="buffers.html">Endian buffer types</a> -</b> The application uses the provided endian
|
||||
buffer types
|
||||
to hold values, and explicitly converts to and from the built-in integer types. Buffer sizes of 8, 16, 24, 32, 40, 48, 56, and 64 bits (i.e.
|
||||
1, 2, 3, 4, 5, 6, 7, and 8 bytes) are provided. Unaligned integer buffer types
|
||||
are provided for all sizes, and aligned buffer types are provided for 16, 32, and
|
||||
64-bit sizes. The provided specific types are typedefs for a generic class
|
||||
template that may be used directly for less common use cases.</p>
|
||||
|
||||
<p><b><a href="arithmetic.html">Endian arithmetic types</a> -</b> The
|
||||
application uses the provided endian arithmetic types, which supply the same
|
||||
operations as the built-in C++ arithmetic types. All conversions are implicit.
|
||||
Arithmetic sizes of 8, 16, 24, 32, 40, 48, 56, and 64 bits (i.e. 1, 2, 3, 4, 5,
|
||||
6, 7, and 8 bytes) are provided. Unaligned integer types are provided for all
|
||||
sizes and aligned
|
||||
arithmetic types are provided for 16, 32, and 64-bit sizes. The provided
|
||||
specific types are typedefs for a generic class template that may be used
|
||||
directly in generic code of for less common use cases.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<p>Boost Endian is a header-only library. C++11 features
|
||||
affecting interfaces, such as <code>noexcept</code>, are used only if available.
|
||||
See <a href="#C++03-support">C++03 support for C++11 features</a> for details.</p>
|
||||
|
||||
<h2><a name="Choosing">Choosing</a> between conversion functions, buffer types,
|
||||
and arithmetic types</h2>
|
||||
|
||||
<p>This section has been moved to its own <a href="choosing_approach.html">
|
||||
Choosing the Approach</a> page. </p>
|
||||
|
||||
<h2>Built-in support for <a name="Intrinsic">Intrinsic</a>s</h2>
|
||||
<p>Most compilers, including GCC, Clang, and Visual C++, supply built-in support for byte swapping intrinsics.
|
||||
The Endian library uses these intrinsics when available since they may result in smaller and faster generated code, particularly for
|
||||
optimized
|
||||
builds.</p>
|
||||
<p>Defining the macro <code>BOOST_ENDIAN_NO_INTRINSICS</code> will suppress use
|
||||
of the intrinsics. This is useful when a compiler has no intrinsic support or
|
||||
fails to locate the appropriate header, perhaps because it
|
||||
is an older release or has very limited supporting libraries.</p>
|
||||
<p>The macro <code>BOOST_ENDIAN_INTRINSIC_MSG</code> is defined as
|
||||
either <code>"no byte swap intrinsics"</code> or a string describing the
|
||||
particular set of intrinsics being used. This is useful for eliminating missing
|
||||
intrinsics as a source of performance issues.</p>
|
||||
|
||||
<h2><a name="Performance">Performance</a></h2>
|
||||
|
||||
<p>Consider this problem:</p>
|
||||
|
||||
<div align="center">
|
||||
<center>
|
||||
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<p align="center"><i><b><a name="Example-1">Example 1</a></b></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><b><i>Add 100 to a big endian value in a file, then write the
|
||||
result to a file</i> </b> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><i><b>Endian arithmetic type approach</b></i></td>
|
||||
<td><i><b>Endian conversion function approach</b></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<pre>big_int32_at x;
|
||||
|
||||
... read into x from a file ...
|
||||
|
||||
x += 100;
|
||||
|
||||
... write x to a file ...
|
||||
</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>
|
||||
int32_t x;
|
||||
|
||||
... read into x from a file ...
|
||||
|
||||
big_to_native_inplace(x);
|
||||
x += 100;
|
||||
native_to_big_inplace(x);
|
||||
|
||||
... write x to a file ...
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</center>
|
||||
</div>
|
||||
|
||||
<p><b>There will be no performance difference between the two approaches in
|
||||
optimized builds,
|
||||
regardless of the native endianness of the machine.</b> That's because optimizing compilers will generate exactly the same code for each. That conclusion was confirmed by
|
||||
studying the generated assembly code for GCC and Visual C++. Furthermore, time
|
||||
spent doing I/O will determine the speed of this application.</p>
|
||||
|
||||
<p>Now consider a slightly different problem: </p>
|
||||
|
||||
<div align="center">
|
||||
<center>
|
||||
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<p align="center"><b><i><a name="Example-2">Example 2</a></i></b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><i><b>Add a million values to a big endian value in a file, then write the
|
||||
result to a file </b></i> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><i><b>Endian arithmetic type approach</b></i></td>
|
||||
<td><i><b>Endian conversion function approach</b></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<pre>big_int32_at x;
|
||||
|
||||
... read into x from a file ...
|
||||
|
||||
for (int32_t i = 0; i < 1000000; ++i)
|
||||
x += i;
|
||||
|
||||
... write x to a file ...
|
||||
</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>int32_t x;
|
||||
|
||||
... read into x from a file ...
|
||||
|
||||
big_to_native_inplace(x);
|
||||
|
||||
for (int32_t i = 0; i < 1000000; ++i)
|
||||
x += i;
|
||||
|
||||
native_to_big_inplace(x);
|
||||
|
||||
... write x to a file ...
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</center>
|
||||
</div>
|
||||
|
||||
<p>With the Endian arithmetic approach, on little endian platforms an implicit conversion from and then back to
|
||||
big endian is done inside the loop. With the Endian conversion function
|
||||
approach, the user has ensured the conversions are done outside the loop, so the
|
||||
code may run more quickly on little endian platforms.</p>
|
||||
|
||||
<h3><a name="Timings">Timings</a></h3>
|
||||
<p>These tests were run against release builds on a circa 2012 4-core little endian X64 Intel Core i5-3570K
|
||||
CPU @ 3.40GHz under Windows 7.</p>
|
||||
|
||||
<p><b>Caveat emptor: The Windows CPU timer has very high granularity. Repeated
|
||||
runs of the same tests often yield considerably different results.</b></p>
|
||||
|
||||
<p>See <b>test/loop_time_test.cpp</b> for the actual code and <b>benchmark/Jamfile.v2</b> for the build
|
||||
setup.</p>
|
||||
|
||||
|
||||
<div align="center">
|
||||
<center>
|
||||
<table border="1" cellpadding="5" cellspacing="0"style="border-collapse: collapse" bordercolor="#111111">
|
||||
<tr><td colspan="6" align="center"><b>GNU C++ version 4.8.2 on Linux virtual
|
||||
machine</b></td></tr>
|
||||
<tr><td colspan="6" align="center"><b> Iterations: 10'000'000'000, Intrinsics: __builtin_bswap16, etc.</b></td></tr>
|
||||
<tr><td><b>Test Case</b></td>
|
||||
<td align="center"><b>Endian<br>arithmetic<br>type</b></td>
|
||||
<td align="center"><b>Endian<br>conversion<br>function</b></td>
|
||||
</tr>
|
||||
<tr><td>16-bit aligned big endian</td><td align="right">8.46 s</td><td align="right">5.28 s</td></tr>
|
||||
<tr><td>16-bit aligned little endian</td><td align="right">5.28 s</td><td align="right">5.22 s</td></tr>
|
||||
<tr><td>32-bit aligned big endian</td><td align="right">8.40 s</td><td align="right">2.11 s</td></tr>
|
||||
<tr><td>32-bit aligned little endian</td><td align="right">2.11 s</td><td align="right">2.10 s</td></tr>
|
||||
<tr><td>64-bit aligned big endian</td><td align="right">14.02 s</td><td align="right">3.10 s</td></tr>
|
||||
<tr><td>64-bit aligned little endian</td><td align="right">3.00 s</td><td align="right">3.03 s</td></tr>
|
||||
|
||||
</table>
|
||||
</center>
|
||||
</div>
|
||||
<p></p>
|
||||
|
||||
<div align="center"> <center>
|
||||
<table border="1" cellpadding="5" cellspacing="0"style="border-collapse: collapse" bordercolor="#111111">
|
||||
<tr><td colspan="6" align="center"><b>Microsoft Visual C++ version 14.0</b></td></tr>
|
||||
<tr><td colspan="6" align="center"><b> Iterations: 10'000'000'000, Intrinsics: cstdlib _byteswap_ushort, etc.</b></td></tr>
|
||||
<tr><td><b>Test Case</b></td>
|
||||
<td align="center"><b>Endian<br>arithmetic<br>type</b></td>
|
||||
<td align="center"><b>Endian<br>conversion<br>function</b></td>
|
||||
</tr>
|
||||
<tr><td>16-bit aligned big endian</td><td align="right">8.27 s</td><td align="right">5.26 s</td></tr>
|
||||
<tr><td>16-bit aligned little endian</td><td align="right">5.29 s</td><td align="right">5.32 s</td></tr>
|
||||
<tr><td>32-bit aligned big endian</td><td align="right">8.36 s</td><td align="right">5.24 s</td></tr>
|
||||
<tr><td>32-bit aligned little endian</td><td align="right">5.24 s</td><td align="right">5.24 s</td></tr>
|
||||
<tr><td>64-bit aligned big endian</td><td align="right">13.65 s</td><td align="right">3.34 s</td></tr>
|
||||
<tr><td>64-bit aligned little endian</td><td align="right">3.35 s</td><td align="right">2.73 s</td></tr>
|
||||
</table>
|
||||
</center></div>
|
||||
|
||||
|
||||
<h2>Overall <a name="FAQ">FAQ</a></h2>
|
||||
|
||||
<p><b>Is the implementation header only?</b></p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p>Yes.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<p><b>Are C++03 compilers supported?</b></p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p>Yes.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<p><b>Does the implementation use compiler intrinsic built-in byte swapping?</b></p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p>Yes, if available. See <a href="#Intrinsic">Intrinsic built-in support</a>.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<p><b>Why bother with endianness?</b></p>
|
||||
<blockquote>
|
||||
<p>Binary data portability is the primary use case.</p>
|
||||
</blockquote>
|
||||
<p><b>Does endianness have any uses outside of portable binary file or network
|
||||
I/O formats?</b> </p>
|
||||
<blockquote>
|
||||
<p>Using the unaligned integer types with a size tailored to the application's
|
||||
needs is a minor secondary use that saves internal or external memory space. For
|
||||
example, using <code>big_int40_buf_t</code> or <code>big_int40_t</code> in a
|
||||
large array saves a lot of space compared to one of the 64-bit types.</p>
|
||||
</blockquote>
|
||||
<p><b>Why bother with binary I/O? Why not just use C++ Standard Library stream
|
||||
inserters and extractors?</b></p>
|
||||
<blockquote>
|
||||
<p>Data interchange formats often specify binary integer data.</p>
|
||||
<p>Binary integer data is smaller and therefore I/O is faster and file sizes
|
||||
are smaller. Transfer between systems is less expensive.</p>
|
||||
<p >Furthermore, binary integer data is of fixed size, and so fixed-size disk
|
||||
records are possible without padding, easing sorting and allowing random access.</p>
|
||||
<p >Disadvantages, such as the inability to use text utilities on the
|
||||
resulting files, limit usefulness to applications where the binary I/O
|
||||
advantages are paramount.</p>
|
||||
</blockquote>
|
||||
|
||||
<p><b>Which is better, big-endian or little-endian?</b></p>
|
||||
<blockquote>
|
||||
<p>Big-endian tends to be preferred in a networking environment and is a bit
|
||||
more of an industry standard, but little-endian may be preferred for
|
||||
applications that run primarily on x86, x86-64, and other little-endian
|
||||
CPU's. The <a href="http://en.wikipedia.org/wiki/Endian">Wikipedia</a> article
|
||||
gives more pros and cons.</p>
|
||||
</blockquote>
|
||||
|
||||
<p><b>Why are only big and little native endianness supported?</b></p>
|
||||
<blockquote>
|
||||
<p>These are the only endian schemes that have any practical value today. PDP-11
|
||||
and the other middle endian approaches are interesting curiosities
|
||||
but have no relevance for today's C++ developers. The same is true for
|
||||
architectures that allow runtime endianness switching. The
|
||||
<a href="conversion.html#native-order-specification">specification for native
|
||||
ordering</a> has been carefully crafted to allow support for such orderings in
|
||||
the future, should the need arise. Thanks to Howard Hinnant for suggesting this. </p>
|
||||
</blockquote>
|
||||
|
||||
<p><b>Why do both the buffer and arithmetic types exist?</b></p>
|
||||
<blockquote>
|
||||
<p>Conversions in the buffer types are explicit. Conversions in the arithmetic
|
||||
types are implicit. This fundamental difference is a deliberate design feature
|
||||
that would be lost if the inheritance hierarchy were collapsed.</p>
|
||||
<p>The original design provided only arithmetic types. Buffer types were
|
||||
requested during formal review by those wishing total control over when
|
||||
conversion occurs. They also felt that buffer types would be less likely to be
|
||||
misused by maintenance programmers not familiar with the implications of
|
||||
performing a lot of integer operations on the endian arithmetic integer types.</p>
|
||||
</blockquote>
|
||||
<p><b>What is gained by using the buffer types rather than always just using the
|
||||
arithmetic types?</b></p>
|
||||
<blockquote>
|
||||
<p>Assurance that hidden conversions are not performed. This is of overriding
|
||||
importance to users concerned about achieving the ultimate in terms of speed. </p>
|
||||
<p>"Always just using the arithmetic types" is fine for other users. When the
|
||||
ultimate in speed needs to be ensured, the arithmetic types can be used in the
|
||||
same design patterns or idioms that would be used for buffer types, resulting in
|
||||
the same code being generated for either types.</p>
|
||||
</blockquote>
|
||||
|
||||
<p><b>What are the limitations of integer support?</b></p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p>Tests have only been
|
||||
performed on machines that use two's complement arithmetic. The Endian
|
||||
conversion functions only support 16, 32, and 64-bit aligned integers. The
|
||||
endian types only support 8, 16, 24, 32, 40, 48, 56, and 64-bit unaligned integers,
|
||||
and 8, 16, 32, and 64-bit aligned integers.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<p><b>Why is there no floating point support?</b></p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p>An attempt was made to support four-byte <code>float</code>s and eight-byte
|
||||
<code>double</code>s, limited to
|
||||
<a href="http://en.wikipedia.org/wiki/IEEE_floating_point">IEEE 754</a> (also
|
||||
know as ISO/IEC/IEEE 60559) floating point and further limited to systems where
|
||||
floating point endianness does not differ from integer
|
||||
endianness.</p>
|
||||
|
||||
<p>Even with those limitations, support for floating point types was not
|
||||
reliable and was removed. For example, simply reversing the endianness of a
|
||||
floating point number can result in a signaling-NAN. For all practical purposes,
|
||||
binary serialization and endianness for integers are one and the same problem.
|
||||
That is not true for floating point numbers, so binary serialization interfaces
|
||||
and formats for floating point does not fit well in an endian-based library.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<h2><a name="Release-history">Release history</a></h2>
|
||||
<h3><a name="Changes-requested-by-formal-review">Changes requested by formal review</a></h3>
|
||||
<p>The library was reworked from top to bottom to accommodate changes requested
|
||||
during the formal review. See <a href="mini_review_topics.html">Mini-Review</a>
|
||||
page for details.</p>
|
||||
<h3><a name="Other-changes-since-formal-review">Other changes since formal
|
||||
review</a></h3>
|
||||
<ul>
|
||||
<li>Header <code>boost/endian/endian.hpp</code> has been renamed to <code>
|
||||
boost/endian/arithmetic.hpp</code>. Headers
|
||||
<code>boost/endian/conversion.hpp</code> and <code>boost/endian/buffers.hpp</code> have been
|
||||
added.
|
||||
Infrastructure file names were changed accordingly.</li>
|
||||
<li>The endian arithmetic type aliases have been renamed,
|
||||
using a naming pattern that is consistent for both integer and floating point,
|
||||
and a consistent set of aliases supplied for the endian buffer types.</li>
|
||||
<li>The unaligned-type alias names still have the <code>_t</code> suffix, but
|
||||
the aligned-type alias names now have an <code>_at</code> suffix..</li>
|
||||
<li><code>endian_reverse()</code> overloads for <code>int8_t</code> and <code>
|
||||
uint8_t</code> have been added for improved generality. (Pierre Talbot)</li>
|
||||
<li>Overloads of <code>endian_reverse_inplace()</code> have been replaced with a single <code>
|
||||
endian_reverse_inplace()</code> template. (Pierre Talbot)</li>
|
||||
<li>For X86 and X64 architectures, which permit unaligned loads and stores,
|
||||
unaligned little endian buffer and arithmetic types use regular loads and
|
||||
stores when the size is exact. This makes unaligned little endian buffer and
|
||||
arithmetic types significantly more efficient on these architectures. (Jeremy
|
||||
Maitin-Shepard)</li>
|
||||
<li>C++11 features affecting interfaces, such as <code>noexcept</code>, are now used.
|
||||
C++03 compilers are still
|
||||
supported.</li>
|
||||
<li>Acknowledgements have been updated.</li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="Compatibility">Compatibility</a> with interim releases</h2>
|
||||
|
||||
<p>Prior to the official Boost release, class template <code>
|
||||
endian_arithmetic</code> has been used for a decade or more with the same
|
||||
functionality but under the name <code>endian</code>. Other names also changed
|
||||
in the official release. If the macro <code>BOOST_ENDIAN_DEPRECATED_NAMES</code>
|
||||
is defined, those old now deprecated names are still supported. However, the
|
||||
class template <code>endian</code> name is only provided for compilers
|
||||
supporting C++11 template aliases. For C++03 compilers, the name will have to be
|
||||
changed to <code>endian_arithmetic</code>.</p>
|
||||
|
||||
<p>To support backward header compatibility, deprecated header <code>boost/endian/endian.hpp</code>
|
||||
forwards to <code>boost/endian/arithmetic.hpp</code>. It requires <code>
|
||||
BOOST_ENDIAN_DEPRECATED_NAMES</code> be defined. It should only be used while
|
||||
transitioning to the official Boost release of the library as it will be removed
|
||||
in some future release.</p>
|
||||
|
||||
<h2><a name="C++03-support">C++03 support</a> for C++11 features</h2>
|
||||
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
|
||||
<tr>
|
||||
<td><b>C++11 Feature</b></td>
|
||||
<td><b>Action with C++03 Compilers </b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Scoped enums </td>
|
||||
<td>Uses header <code class="computeroutput">
|
||||
<a href="http://www.boost.org/libs/core/doc/html/core/scoped_enum.html">
|
||||
<span class="identifier">boost</span><span class="special">/</span><span class="identifier">core</span><span class="special">/</span><span class="identifier">scoped_enum</span><span class="special">.</span><span class="identifier">hpp</span></a></code><span class="identifier">
|
||||
to emulate C++11 scoped enums.</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>noexcept</code></td>
|
||||
<td><span class="identifier">Uses BOOST_NOEXCEPT macro, which is defined as
|
||||
null for compilers not supporting this C++11 feature.</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>C++11 PODs (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm">N2342</a>)</td>
|
||||
<td><span class="identifier">Takes advantage of C++03 compilers that
|
||||
relax C++03 POD rules, but see Limitations
|
||||
<a href="buffers.html#Limitations">here</a> and
|
||||
<a href="arithmetic.html#Limitations">here</a>. Also see macros for explicit
|
||||
POD control <a href="buffers.html#Compilation">here</a> and
|
||||
<a href="arithmetic.html#Compilation">here</a>.</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2><a name="Future-directions">Future directions</a></h2>
|
||||
|
||||
<p><b>Standardization.</b> The plan is to submit Boost.Endian to the C++
|
||||
standards committee for possible inclusion in a Technical Specification or the
|
||||
C++ standard itself.</p>
|
||||
|
||||
<p><b>Specializations for <code>numeric_limits</code>.</b> Roger Leigh
|
||||
requested that all <code>boost::endian</code> types provide <code>numeric_limits</code>
|
||||
specializations. See <a href="https://github.com/boostorg/endian/issues/4">
|
||||
GitHub issue 4</a>.</p>
|
||||
|
||||
<p><b>Character buffer support.</b> Peter Dimov pointed out during the
|
||||
mini-review that getting and setting basic arithmetic types (or <code><cstdint></code>
|
||||
equivalents) from/to an offset into an array of unsigned char is a common need.
|
||||
See <a href="http://lists.boost.org/Archives/boost/2015/01/219574.php">
|
||||
Boost.Endian mini-review posting</a>.</p>
|
||||
|
||||
<p><b>Out-of-range detection.</b> Peter Dimov pointed suggested during the
|
||||
mini-review that throwing an exception on buffer values being out-of-range might
|
||||
be desirable. See the end of
|
||||
<a href="http://lists.boost.org/Archives/boost/2015/01/219659.php">this posting</a>
|
||||
and subsequent replies.</p>
|
||||
|
||||
<h2><a name="Acknowledgements">Acknowledgements</a></h2>
|
||||
<p>Comments and suggestions were received from Adder, Benaka Moorthi,
|
||||
Christopher Kohlhoff, Cliff Green, Daniel James, Dave Handley, Gennaro Proto, Giovanni Piero
|
||||
Deretta, Gordon Woodhull, dizzy, Hartmut Kaiser, Howard Hinnant, Jason Newton, Jeff Flinn, Jeremy Maitin-Shepard, John Filo, John
|
||||
Maddock, Kim Barrett, Marsh Ray, Martin Bonner, Mathias Gaunard, Matias
|
||||
Capeletto, Neil Mayhew, Nevin Liber,
|
||||
Olaf van der Spek, Paul Bristow, Peter Dimov, Pierre Talbot, Phil Endecott,
|
||||
Philip Bennefall, Pyry Jahkola,
|
||||
Rene Rivera, Robert Stewart, Roger Leigh, Roland Schwarz, Scott McMurray, Sebastian Redl, Tim
|
||||
Blechmann, Tim Moore, tymofey, Tomas Puverle, Vincente Botet, Yuval Ronen and
|
||||
Vitaly Budovsk. Apologies if anyone has been missed.</p>
|
||||
<hr>
|
||||
<p>Last revised:
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05 April, 2016<!--webbot bot="Timestamp" endspan i-checksum="29990" --></p>
|
||||
<p>© Copyright Beman Dawes, 2011, 2013</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. See
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/ LICENSE_1_0.txt</a></p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,150 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>Endian Mini-Review</title>
|
||||
</head>
|
||||
<link href="styles.css" rel="stylesheet">
|
||||
<body>
|
||||
|
||||
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="100%">
|
||||
<tr>
|
||||
<td width="339">
|
||||
<a href="../../../index.html">
|
||||
<img src="../../../boost.png" alt="Boost logo" align="middle" border="0" width="277" height="86"></a></td>
|
||||
<td align="middle" width="1253">
|
||||
<b>
|
||||
<font size="6">Endian </font></b><font size="6"><b>Mini-Review</b></font></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse"
|
||||
bordercolor="#111111" bgcolor="#D7EEFF" width="100%">
|
||||
<tr>
|
||||
<td><b>
|
||||
<a href="index.html">Endian Home</a>
|
||||
<a href="conversion.html">Conversion Functions</a>
|
||||
<a href="arithmetic.html">Arithmetic Types</a>
|
||||
<a href="buffers.html">Buffer Types</a>
|
||||
<a href="choosing_approach.html">Choosing Approach</a></b></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p></p>
|
||||
|
||||
<p>The results of the Boost.Endian formal review included a list of issues to be
|
||||
resolved before a mini-review.</p>
|
||||
|
||||
<p>The issues are shown in <b>bold</b> below, with the resolution indicated.</p>
|
||||
|
||||
<p><b>1. Common use case scenarios should be developed.</b></p>
|
||||
<blockquote>
|
||||
|
||||
<p>Done. The documentation have been refactored. A page is now devoted to
|
||||
<a href="choosing_approach.html">Choosing the Approach</a> to endianness. See
|
||||
<a href="choosing_approach.html#Use-cases">Use cases</a> for use case
|
||||
scenarios.</p>
|
||||
</blockquote>
|
||||
<p><b>2. Example programs should be developed for the common use case scenarios.</b></p>
|
||||
<blockquote>
|
||||
<p>Done. See <a href="choosing_approach.html">Choosing the Approach</a>.
|
||||
Example code has been added throughout.</p>
|
||||
</blockquote>
|
||||
<p><b>3. Documentation should illuminate the differences between endian
|
||||
integer/float type and endian conversion approaches to the common use
|
||||
case scenarios, and provide guidelines for choosing the most appropriate
|
||||
approach in user's applications.</b></p>
|
||||
<blockquote>
|
||||
<p>Done. See <a href="choosing_approach.html">Choosing the Approach</a>.</p>
|
||||
</blockquote>
|
||||
<p><b>4 .Conversion functions supplying results via return should be provided.</b></p>
|
||||
<blockquote>
|
||||
<p>Done. See <a href="conversion.html">ConversionFunctions</a>.</p>
|
||||
</blockquote>
|
||||
<p><b>5. Platform specific performance enhancements such as use of compiler intrinsics or relaxed alignment requirements should be supported.</b></p>
|
||||
<blockquote>
|
||||
<p>Done. Compiler (Clang, GCC, VisualC++, etc.) intrinsics and built-in
|
||||
functions are used in the implementation where appropriate, as requested. See
|
||||
<a href="index.html#Intrinsic">Built-in support for Intrinsics</a>. See
|
||||
<a href="index.html#Timings">Timings for Example 2</a> to gauge the impact of
|
||||
intrinsics.</p>
|
||||
</blockquote>
|
||||
<p><b>6. Endian integer (and floating) types should be implemented via the
|
||||
conversion functions. If that can't be done efficiently, consideration
|
||||
should be given to expanding the conversion function signatures to
|
||||
resolve the inefficiencies.</b></p>
|
||||
<blockquote>
|
||||
<p>Done. For the endian types, the implementation uses the endian conversion
|
||||
functions, and thus the intrinsics, as requested.</p>
|
||||
</blockquote>
|
||||
<p><b>7. Benchmarks that measure performance should be provided. It should be
|
||||
possible to compare platform specific performance enhancements against
|
||||
portable base implementations, and to compare endian integer approaches
|
||||
against endian conversion approaches for the common use case scenarios.</b></p>
|
||||
<blockquote>
|
||||
<p>Done. See <a href="index.html#Timings">Timings for Example 2</a>. The <code>endian/test</code> directory
|
||||
also contains several additional benchmark and speed test programs.</p>
|
||||
</blockquote>
|
||||
<p><b>8. Float (32-bits) and double (64-bits) should be supported. IEEE 754 is
|
||||
the primary use case.</b></p>
|
||||
<blockquote>
|
||||
<p>Done. The <a href="buffers.html">endian buffer types</a>,
|
||||
<a href="arithmetic.html">endian arithmetic types</a> and
|
||||
<a href="conversion.html">endian conversion functions</a> now support 32-bit (<code>float)</code>
|
||||
and 64-bit <code>(double)</code> floating point, as requested.</p>
|
||||
</blockquote>
|
||||
<p><b>9. Support for user defined types (UDTs) is desirable, and should be
|
||||
provided where there would be no conflict with the other concerns.</b></p>
|
||||
<blockquote>
|
||||
<p>Done. See <a href="conversion.html#Customization-points">Customization
|
||||
points for user-defined types (UDTs)</a>.</p>
|
||||
</blockquote>
|
||||
<p><b>10. There is some concern that endian integer/float arithmetic operations
|
||||
might used inadvertently or inappropriately. The impact of adding an endian_buffer
|
||||
class without arithmetic operations should be investigated.</b></p>
|
||||
<blockquote>
|
||||
<p>Done. The endian types have been decomposed into class template <code>
|
||||
<a href="buffers.html">endian_buffer</a></code> and class template <code>
|
||||
<a href="arithmetic.html">endian_arithmetic</a></code>. Class
|
||||
<code>endian_buffer</code> is a public base class for <code>endian_arithmetic</code>,
|
||||
and can also be used by users as a stand-alone class.</p>
|
||||
</blockquote>
|
||||
<p><b>11. Stream insertion and extraction of the endian integer/float types should
|
||||
be documented and included in the test coverage.</b></p>
|
||||
<blockquote>
|
||||
<p>Done. See <a href="buffers.html#Stream-inserter">Stream inserter</a> and
|
||||
<a href="buffers.html#Stream-extractor">Stream extractor</a>.</p>
|
||||
</blockquote>
|
||||
<p><b>12. 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
|
||||
library.</b></p>
|
||||
|
||||
<blockquote>
|
||||
<p>Not done yet. Will be handled as a separate min-review soon after the
|
||||
Endian mini-review.</p>
|
||||
|
||||
</blockquote>
|
||||
<p><b>13. Other requested changes.</b></p>
|
||||
|
||||
<blockquote>
|
||||
<ul>
|
||||
<li>In addition to the named-endianness conversion functions, functions that perform
|
||||
compile-time (via template) and run-time (via function argument) dispatch
|
||||
are now provided.</li>
|
||||
<li><code>order::native</code> is now a synonym for <code>order::big</code>
|
||||
or <code>order::little</code> according to the endianness of the platform. This reduces the number of template specializations required.</li>
|
||||
<li>Headers have been reorganized to make them easier to read,
|
||||
with a synopsis at the front and implementation following.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<hr>
|
||||
<p>Last revised:
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->19 January, 2015<!--webbot bot="Timestamp" endspan i-checksum="38903" --></p>
|
||||
<p>© Copyright Beman Dawes, 2014</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. See
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/ LICENSE_1_0.txt</a></p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,31 +0,0 @@
|
||||
Windows
|
||||
-------
|
||||
|
||||
Prerequisites
|
||||
|
||||
Boost libraries available in boost-root\stage\lib. Example:
|
||||
|
||||
cd boost-root
|
||||
.\bootstrap
|
||||
.\b2 --with-system --with-chrono --with-timer link=shared stage
|
||||
|
||||
The provided Visual Studio solution (endian/test/msvc/endian.sln) has a property page
|
||||
(endian/test/msvc/common.prop) with these Common Properties set (do not include the
|
||||
double quotes):
|
||||
|
||||
VC++ Directores|Executable Directories: prefix default value with "..\..\..\..\..\stage\lib;"
|
||||
(Click "Inherit from parent or project defaults" if not checked)
|
||||
|
||||
C/C++|General|Additional Include Directories: prefix default value with "..\..\..\..\..\stage\lib;"
|
||||
|
||||
Linker|General|Additional Library Directories: prefix default value with "..\..\..\..\..\stage\lib;"
|
||||
|
||||
C/C++|Preprocessor: prefix default value with "BOOST_ALL_DYN_LINK;"
|
||||
|
||||
IMPORTANT: If Preprocessor macros are supplied via a common property page,
|
||||
<inherit from parent or project defaults> must be set for each project!
|
||||
|
||||
------------------------------------------------------------------------------------------
|
||||
Copyright Beman Dawes, 2013
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
See http://www.boost.org/LICENSE_1_0.txt
|
134
doc/p0803r0.html
134
doc/p0803r0.html
@ -1,134 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<style>
|
||||
body
|
||||
{
|
||||
font-family: arial, sans-serif;
|
||||
max-width: 6.75in;
|
||||
margin: 0px auto;
|
||||
font-size: 85%;
|
||||
}
|
||||
ins {background-color: #CCFFCC; text-decoration: none;}
|
||||
del {background-color: #FFCACA; text-decoration: none;}
|
||||
pre {background-color: #D7EEFF; font-size: 95%; font-family: "courier new", courier, serif;}
|
||||
code {font-family: "courier new", courier, serif;}
|
||||
table {font-size: 90%;}
|
||||
</style>
|
||||
<title>Endian RFC</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="left">Doc. no.:</td>
|
||||
<td align="left">P0803R0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Date:</td>
|
||||
<td align="left">
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%Y-%m-%d" startspan -->2017-10-15<!--webbot bot="Timestamp" endspan i-checksum="12057" --></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Reply to:</td>
|
||||
<td align="left">Beman Dawes <bdawes at acm dot org>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Audience:</td>
|
||||
<td align="left">Library Evolution</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
<h1 align="center">Endian Library Request for Comments (R0)</h1>
|
||||
|
||||
|
||||
<h2>Abstract</h2>
|
||||
<p>The Boost Endian library manipulates the
|
||||
<a href="https://en.wikipedia.org/wiki/Endianness">endianness</a> of integers
|
||||
and user-defined types. It provides three approaches to dealing with endianness:
|
||||
conversion functions, buffer classes, and arithmetic classes. Each approach
|
||||
has use cases where it is preferred over the other approaches. The purpose of
|
||||
this RFC is to determine interest in adding all or any of these components to
|
||||
the C++ standard library or a library TS.</p>
|
||||
<h2>Introduction</h2>
|
||||
<p>The Boost Endian documentation (<a href="https://www.boost.org/libs/endian/doc/index.html">www.boost.org/libs/endian/doc</a>)
|
||||
provides an <a href="https://www.boost.org/libs/endian/doc/index.html">overview</a>
|
||||
and detailed technical specifications for the
|
||||
<a href="https://www.boost.org/libs/endian/doc/conversion.html">conversion
|
||||
functions</a>, <a href="https://www.boost.org/libs/endian/doc/arithmetic.html">
|
||||
arithmetic types</a>, and
|
||||
<a href="https://www.boost.org/libs/endian/doc/buffers.html">buffer types</a>.
|
||||
</p>
|
||||
<p>A separate discussion covers
|
||||
<a href="https://www.boost.org/libs/endian/doc/choosing_approach.html">choosing
|
||||
between the three approaches</a> provided by the library.</p>
|
||||
<p>For those not interested in plowing through the entire documentation, the
|
||||
<a href="https://www.boost.org/libs/endian/doc/index.html#FAQ">Overall FAQ</a>,
|
||||
<a href="https://www.boost.org/libs/endian/doc/conversion.html#FAQ">Conversion
|
||||
FAQ</a>, <a href="https://www.boost.org/libs/endian/doc/arithmetic.html#FAQ">
|
||||
Arithmetic FAQ</a>, and
|
||||
<a href="https://www.boost.org/libs/endian/doc/buffers.html#FAQ">Buffers FAQ</a>
|
||||
answer a lot of question likely to arise during standardization.</p>
|
||||
<h2>Motivation for standardization</h2>
|
||||
<ul>
|
||||
<li>Lack of any one de facto standard endianness capability in either C or
|
||||
C++. While most platforms provides some way to handle endianness in C, the
|
||||
mechanism varies from platform to platform.</li>
|
||||
<li>Commonly used endian handling functions are extremely error prone. While
|
||||
the Boost Endian conversion functions have the same problems, the buffer and
|
||||
arithmetic classes do not.</li>
|
||||
<li>Surprisingly difficult to write and test yourself in a portable yet
|
||||
efficient (i.e. using intrinsics) way. </li>
|
||||
<li>Explicit requests for standardization from Boost Endian users.</li>
|
||||
<li>The Boost library is existing practice with years of both implementation
|
||||
and end-user experience.</li>
|
||||
<li>The committee has already failed once to standardize endian conversion
|
||||
functions; perhaps now is time to do it right.</li>
|
||||
</ul>
|
||||
<h2>Impact on the standard library</h2>
|
||||
<p>All three proposed approaches to endianness would be a pure additions to the
|
||||
standard library and would break no existing user code (modulo the usual
|
||||
namespace caveats).</p>
|
||||
<h2>Proposed wording</h2>
|
||||
<p>The Boost Endian reference documentation for
|
||||
<a href="https://www.boost.org/libs/endian/doc/conversion.html#Reference">
|
||||
Conversion</a>,
|
||||
<a href="https://www.boost.org/libs/endian/doc/arithmetic.html#endian">
|
||||
Arithmetic</a>, and
|
||||
<a href="https://www.boost.org/libs/endian/doc/buffers.html#endian">Buffer</a>
|
||||
approaches follows the standard library's <i>Method of description</i>
|
||||
[description], so provides a fairly close approximation of what proposed wording
|
||||
would look like. Actual proposed wording will be provided in a proposal document
|
||||
for any portions of the library of interest to the committee. Names will need
|
||||
the usual bikeshedding.</p>
|
||||
<h2>Questions for the Library Evolution Group</h2>
|
||||
<ul>
|
||||
<li>How would you likely vote on a fully-worded and reviewed proposal to add a
|
||||
standardized version of the Boost Endian conversion functions to the standard
|
||||
library or a library TS?<br>
|
||||
</li>
|
||||
<li>How would you likely vote on a fully-worded and reviewed proposal to add a
|
||||
standardized version of the Boost Endian buffer classes to the standard
|
||||
library or a library TS?<br>
|
||||
</li>
|
||||
<li>How would you likely vote on a fully-worded and reviewed proposal to add a
|
||||
standardized version of the Boost Endian arithmetic classes to the standard
|
||||
library or a library TS?</li>
|
||||
</ul>
|
||||
<h2>Acknowledgements</h2>
|
||||
<p>The original design for the arithmetic classes was developed by Darin Adler
|
||||
based on work by Mark Borgerding. The Boost documentation acknowledges
|
||||
<a href="https://www.boost.org/libs/endian/doc/index.html#Acknowledgements">45+
|
||||
other people</a>.</p>
|
||||
<hr>
|
||||
<p> </p>
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,8 +0,0 @@
|
||||
copy /y c:\boost\develop\libs\endian\doc\* d:\boost\endian-gh-pages
|
||||
pushd d:\boost\endian-gh-pages
|
||||
git commit -a -m "copy from develop"
|
||||
git push
|
||||
popd
|
||||
rem Copyright Beman Dawes, 2014
|
||||
rem Distributed under the Boost Software License, Version 1.0.
|
||||
rem See www.boost.org/LICENSE_1_0.txt
|
140
doc/std-rfc.html
140
doc/std-rfc.html
@ -1,140 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<style>
|
||||
body
|
||||
{
|
||||
font-family: arial, sans-serif;
|
||||
max-width: 6.75in;
|
||||
margin: 0px auto;
|
||||
font-size: 85%;
|
||||
}
|
||||
ins {background-color: #CCFFCC; text-decoration: none;}
|
||||
del {background-color: #FFCACA; text-decoration: none;}
|
||||
pre {background-color: #D7EEFF; font-size: 95%; font-family: "courier new", courier, serif;}
|
||||
code {font-family: "courier new", courier, serif;}
|
||||
table {font-size: 90%;}
|
||||
</style>
|
||||
<title>Endian RFC</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="left">Doc. no.:</td>
|
||||
<td align="left">D0803R1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Date:</td>
|
||||
<td align="left">
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%Y-%m-%d" startspan -->2017-11-10<!--webbot bot="Timestamp" endspan i-checksum="12111" --></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Reply to:</td>
|
||||
<td align="left">Beman Dawes <bdawes at acm dot org>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Audience:</td>
|
||||
<td align="left">Library Evolution</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
<h1 align="center">Endian Library Request for Comments (R1)</h1>
|
||||
|
||||
|
||||
<h2>Abstract</h2>
|
||||
<p>The Boost Endian library manipulates the
|
||||
<a href="https://en.wikipedia.org/wiki/Endianness">endianness</a> of integers
|
||||
and user-defined types. It provides three approaches to dealing with endianness:
|
||||
conversion functions, buffer classes, and arithmetic classes. Each approach
|
||||
has use cases where it is preferred by users over the other approaches, but
|
||||
adding all three approaches to the standard library would likely be too much of
|
||||
a good thing. The purpose of
|
||||
this RFC is to determine interest in adding the Boost conversion functions alone to
|
||||
the C++ standard library or a library TS.</p>
|
||||
<h2>Introduction</h2>
|
||||
<p>The Boost Endian documentation (<a href="https://www.boost.org/libs/endian/doc/index.html">www.boost.org/libs/endian/doc</a>)
|
||||
provides an <a href="https://www.boost.org/libs/endian/doc/index.html">overview</a>
|
||||
and detailed technical specifications for the
|
||||
<a href="https://www.boost.org/libs/endian/doc/conversion.html">conversion
|
||||
functions</a>, <a href="https://www.boost.org/libs/endian/doc/arithmetic.html">
|
||||
arithmetic types</a>, and
|
||||
<a href="https://www.boost.org/libs/endian/doc/buffers.html">buffer types</a>.
|
||||
</p>
|
||||
<p>A separate discussion covers
|
||||
<a href="https://www.boost.org/libs/endian/doc/choosing_approach.html">choosing
|
||||
between the three approaches</a> provided by the library.</p>
|
||||
<p>For those not interested in plowing through the entire documentation, the
|
||||
<a href="https://www.boost.org/libs/endian/doc/index.html#FAQ">Overall FAQ</a>,
|
||||
<a href="https://www.boost.org/libs/endian/doc/conversion.html#FAQ">Conversion
|
||||
FAQ</a>, <a href="https://www.boost.org/libs/endian/doc/arithmetic.html#FAQ">
|
||||
Arithmetic FAQ</a>, and
|
||||
<a href="https://www.boost.org/libs/endian/doc/buffers.html#FAQ">Buffers FAQ</a>
|
||||
answer a lot of question likely to arise during standardization.</p>
|
||||
<h2>Motivation for standardization</h2>
|
||||
Lack of any one de facto standard endianness capability in either C or
|
||||
C++. While most platforms provides some way to handle endianness in C, the
|
||||
mechanism varies from platform to platform.<ul>
|
||||
<li>Commonly used C endian handling functions are extremely error prone. While
|
||||
the Boost Endian conversion functions have some of the same problems, the buffer and
|
||||
arithmetic classes do not.</li>
|
||||
<li>Surprisingly difficult to write and test yourself in a portable yet
|
||||
efficient (i.e. using intrinsics) way. </li>
|
||||
<li>Explicit requests for standardization from Boost Endian users.</li>
|
||||
<li>The Boost library is existing practice with years of both implementation
|
||||
and end-user experience.</li>
|
||||
<li>The committee has already started to standardize endian conversion
|
||||
functions once, but had to pull the proposal at the last minute because of
|
||||
name clashes with widely used macros.</li>
|
||||
</ul>
|
||||
<h2>Motivation for standardizing only the conversion functions</h2>
|
||||
<ul>
|
||||
<li>KISS; Providing three different solutions to the same problem space
|
||||
regularly confuses to Boost users and makes endianness solutions harder to
|
||||
teach.</li>
|
||||
<li>The conversion functions are what end users would need to build their own
|
||||
higher level abstractions.</li>
|
||||
<li>The safe use patterns for the conversion functions are already familiar to
|
||||
users of platform specific C endian conversion functions.</li>
|
||||
<li>The Boost buffer and arithmetic types are specified and implemented in
|
||||
terms of the conversion functions, so are easy to add later if desired.</li>
|
||||
</ul>
|
||||
<h2>Impact on the standard library</h2>
|
||||
<p>Endianness conversion functions would be pure additions to the
|
||||
standard library and would break no existing user code (modulo the usual
|
||||
namespace <code>std</code> caveats).</p>
|
||||
<h2>Proposed wording</h2>
|
||||
<p>The Boost Endian reference documentation for
|
||||
<a href="https://www.boost.org/libs/endian/doc/conversion.html#Reference">
|
||||
Conversion</a> follows the standard library's <i>Method of description</i>
|
||||
[description], so provides a fairly close approximation of what proposed wording
|
||||
would look like. Actual proposed wording will be provided in a proposal document
|
||||
if the library is of interest to the committee. Names will need
|
||||
the usual review.</p>
|
||||
<h2>Revision history</h2>
|
||||
<p>R1: Limits proposal to the conversion functions. KISS.</p>
|
||||
<p>R0: Considers adding all three endianness approaches to the standard library.</p>
|
||||
<h2>Question for the Library Evolution Group</h2>
|
||||
Assuming a fully-worded and reviewed proposal to add a
|
||||
standardized version of the Boost Endian conversion functions to the standard
|
||||
library or a library TS, how would you likely vote for it?<h2>Target?</h2>
|
||||
<p>It is premature to discuss whether to target a TS or the IS. We need to have
|
||||
an acceptable proposal in hand and see where we are in the release cycle before
|
||||
deciding on the target. </p>
|
||||
<h2>Acknowledgements</h2>
|
||||
<p>The original design for the arithmetic classes was developed by Darin Adler
|
||||
based on work by Mark Borgerding. The Boost documentation acknowledges
|
||||
<a href="https://www.boost.org/libs/endian/doc/index.html#Acknowledgements">45+
|
||||
other people</a>.</p>
|
||||
<hr>
|
||||
<p> </p>
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,20 +0,0 @@
|
||||
|
||||
body
|
||||
{
|
||||
font-family: arial, sans-serif;
|
||||
max-width: 6.5in;
|
||||
margin: 0px auto;
|
||||
font-size: 85%;
|
||||
}
|
||||
ins {background-color: #CCFFCC;}
|
||||
del {background-color: #FFCACA;}
|
||||
pre {background-color: #D7EEFF; font-size: 95%; font-family: "courier new", courier, serif;}
|
||||
code {font-size: 110%; font-family: "courier new", courier, serif;}
|
||||
table {font-size: 100%;}
|
||||
|
||||
/*
|
||||
<20> Copyright Beman Dawes, 2014
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
See www.boost.org/LICENSE_1_0.txt
|
||||
*/
|
||||
|
@ -1,106 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>Endian Library Do List</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Endian Library TODO List</h1>
|
||||
|
||||
<h2>To Do</h2>
|
||||
<h2>Format Review Comments</h2>
|
||||
<h3 dir="ltr">Interesting</h3>
|
||||
<ul>
|
||||
<li dir="ltr">
|
||||
<p dir="ltr">John Filo - "Absolutely. I'd like to see support for float and
|
||||
double, but<br>
|
||||
even without those additions, I still vote yes." "For those who deal with
|
||||
non-native endian data, this library is<br>
|
||||
extremely useful. It automatically eliminates a whole class of common<br>
|
||||
programming errors when dealing with such data."<br>
|
||||
</li>
|
||||
<li dir="ltr">
|
||||
<p dir="ltr">Hartmut Kaiser - "Even if this is not a full review, I would like
|
||||
to vote YES to include this <br>
|
||||
library into Boost.
|
||||
<p>Boost.Spirit is using (and shipping) with an older version of this library
|
||||
<br>
|
||||
for several years now and we never had any problems with its usage in <br>
|
||||
Spirit. It is used as the underlying framework for the binary parsers and <br>
|
||||
generators and it is functioning as advertised.</p>
|
||||
<p>As a quick test I replaced the internal (older) version of Boost.Endian in
|
||||
<br>
|
||||
Spirit with the reviewed version. All of Spirits regression tests still <br>
|
||||
pass. "<br>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Executive summary</h3>
|
||||
<ul>
|
||||
<li>Common use case scenarios should be developed.</li>
|
||||
<li>Example programs should be developed for the common use case scenarios.</li>
|
||||
<li>Documentation should illuminate the differences between endian
|
||||
integer/float type and endian conversion approaches to the common use case
|
||||
scenarios, and provide guidelines for choosing the most appropriate approach
|
||||
for user's applications.</li>
|
||||
<li>Conversion functions supplying results via <code>return</code> should be
|
||||
provided.</li>
|
||||
<li>Platform specific performance enhancements such as use of compiler
|
||||
intrinsics or relaxed alignment requirements should be supported.</li>
|
||||
<li>Endian integer (and floating) types should be implemented via the
|
||||
conversion functions. If that can't be done efficiently, consideration should
|
||||
be given to expanding the conversion function signatures to resolve the
|
||||
inefficiencies.</li>
|
||||
<li>Benchmarks that measure performance should be provided. It should be
|
||||
possible to compare platform specific performance enhancements against
|
||||
portable base implementations, and to compare endian integer approaches
|
||||
against endian conversion approaches for the common use case scenarios.</li>
|
||||
<li>Float (32-bits) and double (64-bits) should be supported. IEEE 754 is the
|
||||
primary use case.</li>
|
||||
<li>Support for user defined types (UDTs) is desirable, and should be
|
||||
supported where there would be no conflict with the other concerns.</li>
|
||||
<li>There is some concern that endian integer/float arithmetic operations
|
||||
might used
|
||||
inadvertently or inappropriately. The impact of adding an endian_buffer class without arithmetic
|
||||
operations should be investigated.</li>
|
||||
<li>Stream insertion and extraction of the endian integer/float types should
|
||||
be documented and included in the test coverage.</li>
|
||||
<li>Binary I/O support that was investigated during development of the Endian
|
||||
library should be put up for min-review for inclusion in the Boost I/O
|
||||
library.</li>
|
||||
</ul>
|
||||
<h3>Docs</h3>
|
||||
<ul>
|
||||
<li>one other point ... the help file seems to directly link to the c++
|
||||
headers.<br>
|
||||
this should be changed:<br>
|
||||
<br>
|
||||
* some browsers (at least chromium) will not display the header when clicking<br>
|
||||
the link, but will save them on disk.<br>
|
||||
<br>
|
||||
* providing a direct link to the source code from the docs implies that the<br>
|
||||
user will get some information that are necessary to use the library by<br>
|
||||
reading the sources. imo, this is not the case for using boost.endian.<br>
|
||||
<br>
|
||||
* if a user opens integer.hpp, the first 60 lines just contain copyright, some<br>
|
||||
historical notes, compiler-specific stuff, includes and ifdefs. imo, this is<br>
|
||||
the implementation part, which should not be exposed to a user.<br>
|
||||
<br>
|
||||
so i'd suggest to completely remove the links to the c++ headers.<br>
|
||||
</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last revised:
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->17 January, 2015<!--webbot bot="Timestamp" endspan i-checksum="38899" --></p>
|
||||
<p>© Copyright Beman Dawes, 2012</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. See
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p>
|
||||
<p> </p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
Reference in New Issue
Block a user