mirror of
https://github.com/boostorg/endian.git
synced 2025-08-01 13:34:39 +02:00
Initial gh-pages commit.
This commit is contained in:
344
conversion.html
Normal file
344
conversion.html
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
<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>Boost Endian Conversion Functions</title>
|
||||||
|
<style type="text/css">
|
||||||
|
ins {background-color:#CCFFCC}
|
||||||
|
del {background-color:#FFCACA}
|
||||||
|
body { font-family: sans-serif; width:8.0in; }
|
||||||
|
pre { background-color:#D7EEFF }
|
||||||
|
</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.png (6897 bytes)" align="middle" width="277" height="86" border="0"></a></td>
|
||||||
|
<td align="middle">
|
||||||
|
<font size="7">Endian Conversion<br>
|
||||||
|
Functions</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.htm">Boost Home</a>
|
||||||
|
<a href="index.html">Endian Home</a>
|
||||||
|
<a href="conversion.html">Conversion Functions</a>
|
||||||
|
<a href="types.html">Endian Types</a></b></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<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>
|
||||||
|
<a href="#Functions">Functions</a><br>
|
||||||
|
<a href="#FAQ">FAQ</a><br>
|
||||||
|
<a href="#Acknowledgements">Acknowledgements</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" bgcolor="#D7EEFF" align="center">
|
||||||
|
<b><i>Headers</i></b></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" bgcolor="#E8F5FF">
|
||||||
|
<a href="../../../boost/endian/conversion.hpp"><boost/endian/conversion.hpp></a><br>
|
||||||
|
<a href="../../../boost/endian/types.hpp"><boost/endian/types.hpp></a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="Introduction">Introduction</a></h2>
|
||||||
|
|
||||||
|
<p>Header <a href="../../../boost/endian/conversion.hpp">boost/endian/conversion.hpp</a>
|
||||||
|
provides byte order reversal and conversion functions that convert objects of
|
||||||
|
the multi-byte built-in
|
||||||
|
integer types, and also types <code>float</code> and <code>double,</code>
|
||||||
|
between native, big, or little endian byte
|
||||||
|
ordering. User defined types are also supported.</p>
|
||||||
|
|
||||||
|
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
|
||||||
|
<tr>
|
||||||
|
<td bgcolor="#FFFFCC">Caution: Only big endianness and little endianness is supported;
|
||||||
|
middle endianness is not supported.</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="Reference">Reference</a></h2>
|
||||||
|
|
||||||
|
<p>Functions are implemented <code>inline</code> if appropriate.<code> noexcept</code> is
|
||||||
|
elided for compilers that do not support it.
|
||||||
|
Boost scoped enum emulation is used so that the library still works for compilers that do not support scoped enums. </p>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
<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> {big, little, native};
|
||||||
|
|
||||||
|
// reverse byte order (i.e. endianness)
|
||||||
|
int16_t <a href="#reverse_value">reverse_value</a>(int16_t x) noexcept;
|
||||||
|
int32_t <a href="#reverse_value">reverse_value</a>(int32_t x) noexcept;
|
||||||
|
int64_t <a href="#reverse_value">reverse_value</a>(int64_t x) noexcept;
|
||||||
|
uint16_t <a href="#reverse_value">reverse_value</a>(uint16_t x) noexcept;
|
||||||
|
uint32_t <a href="#reverse_value">reverse_value</a>(uint32_t x) noexcept;
|
||||||
|
uint64_t <a href="#reverse_value">reverse_value</a>(uint64_t x) noexcept;
|
||||||
|
float <a href="#reverse_value">reverse_value</a>(float x) noexcept;
|
||||||
|
double <a href="#reverse_value">reverse_value</a>(double x) noexcept;
|
||||||
|
|
||||||
|
void <a href="#reverse">reverse</a>(int16_t& x) noexcept;
|
||||||
|
void <a href="#reverse">reverse</a>(int32_t& x) noexcept;
|
||||||
|
void <a href="#reverse">reverse</a>(int64_t& x) noexcept;
|
||||||
|
void <a href="#reverse">reverse</a>(uint16_t& x) noexcept;
|
||||||
|
void <a href="#reverse">reverse</a>(uint32_t& x) noexcept;
|
||||||
|
void <a href="#reverse">reverse</a>(uint64_t& x) noexcept;
|
||||||
|
void <a href="#reverse">reverse</a>(float& x) noexcept;
|
||||||
|
void <a href="#reverse">reverse</a>(double& x) noexcept;
|
||||||
|
|
||||||
|
// reverse byte order unless native endianness is big
|
||||||
|
template <class ReversibleValue >
|
||||||
|
ReversibleValue <a href="#big_endian_value">big_endian_value</a>(ReversibleValue x) noexcept;
|
||||||
|
template <class Reversible>
|
||||||
|
void <a href="#big_endian">big_endian</a>(Reversible& x) noexcept;
|
||||||
|
|
||||||
|
// reverse byte order unless native endianness is little
|
||||||
|
template <class ReversibleValue >
|
||||||
|
ReversibleValue <a href="#little_endian_value">little_endian_value</a>(ReversibleValue x) noexcept;
|
||||||
|
template <class Reversible>
|
||||||
|
void <a href="#little_endian">little_endian</a>(Reversible& x) noexcept;
|
||||||
|
|
||||||
|
// synonyms, based on names popularized by BSD (e.g. OS X, Linux) endian.h
|
||||||
|
// "h" for "host" (i.e. native), "be" for "big endian",
|
||||||
|
// "le" for "little endian", "m" for "modify" in place
|
||||||
|
template <class T> T bswap(T x) noexcept {return reverse_value(x);}
|
||||||
|
template <class T> T htobe(T host) noexcept {return big_endian_value(host);}
|
||||||
|
template <class T> T htole(T host) noexcept {return little_endian_value(host);}
|
||||||
|
template <class T> T betoh(T big) noexcept {return big_endian_value(big);}
|
||||||
|
template <class T> T letoh(T little) noexcept {return little_endian_value(little);}
|
||||||
|
|
||||||
|
template <class T> void bswapm(T& x) noexcept {reverse(x);}
|
||||||
|
template <class T> void htobem(T& host) noexcept {big_endian(host);}
|
||||||
|
template <class T> void htole(mT& host noexcept) {little_endian(host);}
|
||||||
|
template <class T> void betohm(T& big) noexcept {big_endian(big);}
|
||||||
|
template <class T> void letohm(T& little) noexcept {little_endian(little);}
|
||||||
|
|
||||||
|
// generic byte order conversion
|
||||||
|
template <order From, order To, class ReversibleValue>
|
||||||
|
ReversibleValue <a href="#convert_value_generic">convert_value</a>(ReversibleValue from) noexcept;
|
||||||
|
template <order From, order To, class Reversible>
|
||||||
|
void <a href="#convert_generic">convert</a>(Reversible& x) noexcept;
|
||||||
|
|
||||||
|
// runtime effective byte order determination
|
||||||
|
order <a href="#effective_order">effective_order</a>(order x) noexcept;
|
||||||
|
|
||||||
|
// runtime byte-order conversion
|
||||||
|
template <class ReversibleValue>
|
||||||
|
ReversibleValue <a href="#convert_value_runtime">convert_value</a>(ReversibleValue from,
|
||||||
|
order from_order, order to_order) noexcept;
|
||||||
|
template <class Reversible>
|
||||||
|
void <a href="#convert_runtime">convert</a>(Reversible& x,
|
||||||
|
order from_order, order to_order) noexcept;
|
||||||
|
|
||||||
|
} // namespace endian
|
||||||
|
} // namespace boost</pre>
|
||||||
|
<h3><a name="Requirements">Requirements</a></h3>
|
||||||
|
<p>The template definitions in this header refer to named
|
||||||
|
requirements whose details are set out in this section. User defined types may
|
||||||
|
be used in the function templates in this header only if they meet the
|
||||||
|
function's template parameter requirements.</p>
|
||||||
|
<h4><a name="ReversibleValue">ReversibleValue</a> requirements</h4>
|
||||||
|
<p><code>ReversibleValue</code> is an object type to be
|
||||||
|
supplied by a C++ program instantiating a template; <code>x</code> is a value of
|
||||||
|
type (possibly <code>const</code>) <code>ReversibleValue</code>.</p>
|
||||||
|
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
|
||||||
|
<tr>
|
||||||
|
<td width="160"><b>Expression</b></td>
|
||||||
|
<td width="150"><b>Return type</b></td>
|
||||||
|
<td width="347"><b>Requirement</b></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top">
|
||||||
|
<p><code>reverse_value(x)</code></td>
|
||||||
|
<td valign="top">
|
||||||
|
<p><a name="ReversibleValue"><code>ReversibleValue</code></a></td>
|
||||||
|
<td>
|
||||||
|
<p>The returned value is the value of <code>x</code> with the
|
||||||
|
order of its constituent bytes reversed.</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<h4><a name="Reversible">Reversible</a> requirements</h4>
|
||||||
|
<p><code>Reversible</code> is an object type to be
|
||||||
|
supplied by a C++ program instantiating a template; <code>x</code> is a
|
||||||
|
modifiable lvalue of type <code>Reversible</code>.</p>
|
||||||
|
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
|
||||||
|
<tr>
|
||||||
|
<td width="160"><b>Expression</b></td>
|
||||||
|
<td width="347"><b>Post-condition</b></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top">
|
||||||
|
<p><code>reverse(x)</code></td>
|
||||||
|
<td>
|
||||||
|
<p>The order of the constituent bytes of <code>x</code> are
|
||||||
|
reversed.</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<h3><a name="Functions">Functions</a></h3>
|
||||||
|
<pre><a name="reverse_value"></a>int16_t reverse_value(int16_t x) noexcept;
|
||||||
|
int32_t reverse_value(int32_t x) noexcept;
|
||||||
|
int64_t reverse_value(int64_t x) noexcept;
|
||||||
|
uint16_t reverse_value(uint16_t x) noexcept;
|
||||||
|
uint32_t reverse_value(uint32_t x) noexcept;
|
||||||
|
uint64_t reverse_value(uint64_t x) noexcept;
|
||||||
|
float reverse_value(float x) noexcept;
|
||||||
|
double reverse_value(double x) noexcept;</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><i>Returns:</i> <i><code>x</code></i>, with the order of its
|
||||||
|
constituent bytes reversed.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre><a name="reverse"></a>void reverse(int16_t& x) noexcept;
|
||||||
|
void reverse(int32_t& x) noexcept;
|
||||||
|
void reverse(int64_t& x) noexcept;
|
||||||
|
void reverse(uint16_t& x) noexcept;
|
||||||
|
void reverse(uint32_t& x) noexcept;
|
||||||
|
void reverse(uint64_t& x) noexcept;
|
||||||
|
void reverse(float& x) noexcept;
|
||||||
|
void reverse(double& x) noexcept;</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><i>Postconditions:</i> The order of the constituent bytes of
|
||||||
|
<code>x</code> are reversed.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre><a name="big_endian_value"></a>template <class ReversibleValue >
|
||||||
|
ReversibleValue big_endian_value(ReversibleValue x) noexcept;
|
||||||
|
<a name="big_endian"></a>template <class Reversible>
|
||||||
|
void big_endian(Reversible& x) noexcept;</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><i>Returns (first form)</i>: <code>x</code> if the native byte order is big
|
||||||
|
endian, otherwise <code>reverse_value(x)</code>.</p>
|
||||||
|
<p><i>Effects (second form):</i> None if the native byte order is big
|
||||||
|
endian, otherwise <code>reverse(x)</code>.</p>
|
||||||
|
<p><i>Example:</i></p>
|
||||||
|
<blockquote>
|
||||||
|
<pre>int32_t x = <b><i>some-value</i></b>;
|
||||||
|
big_endian(x); // reverses the byte order of x, unless
|
||||||
|
// the native byte order is big-endian</pre>
|
||||||
|
</blockquote>
|
||||||
|
</blockquote>
|
||||||
|
<pre><a name="little_endian_value"></a>template <class ReversibleValue >
|
||||||
|
ReversibleValue little_endian_value(ReversibleValue x) noexcept;
|
||||||
|
<a name="little_endian"></a>template <class Reversible>
|
||||||
|
void little_endian(Reversible& x) noexcept;</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><i>Returns (first form)</i>: <code>x</code> if the native byte order is little
|
||||||
|
endian, otherwise <code>reverse_value(x)</code>.</p>
|
||||||
|
<p><i>Effects (second form):</i> None if the native byte order is little
|
||||||
|
endian, otherwise <code>reverse(x)</code>.</p>
|
||||||
|
<p><i>Example:</i></p>
|
||||||
|
<blockquote>
|
||||||
|
<pre>int32_t x = <b><i>some-value</i></b>;
|
||||||
|
int32_t y(little_endian(x));
|
||||||
|
// y has been set to x; the byte order is reversed unless
|
||||||
|
// the native byte order is little-endian.</pre>
|
||||||
|
</blockquote>
|
||||||
|
</blockquote>
|
||||||
|
<pre><a name="convert_value_generic"></a>template <order From, order To, class ReversibleValue>
|
||||||
|
ReversibleValue convert_value(ReversibleValue from) noexcept;
|
||||||
|
<a name="convert_generic"></a>template <order From, order To, class Reversible>
|
||||||
|
void convert(Reversible& x) noexcept;
|
||||||
|
</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p>The <b><i>effective order</i></b> of an order template parameter
|
||||||
|
is the same as the order template parameter if the parameter is not <code>
|
||||||
|
order::native</code>, otherwise it is the constant <code>order::big</code> or
|
||||||
|
<code>order::little</code> that represents the actual native byte order.</p>
|
||||||
|
<p><i>Returns (first form)</i>: <code>from</code> if <code>From</code>
|
||||||
|
and <code>To</code> have the same effective order, otherwise <code>
|
||||||
|
reverse_value(from)</code>.</p>
|
||||||
|
<p><i>Effects (second form):</i> None if <code>From</code> and <code>
|
||||||
|
To</code> have the same effective order, otherwise <code>reverse(x)</code>.</p>
|
||||||
|
<p><i>Example:</i></p>
|
||||||
|
<blockquote>
|
||||||
|
<pre>int32_t x;
|
||||||
|
<i>... read an external big-endian value into x</i>
|
||||||
|
convert<order::big, order::native>(x); // more generic equivalent of big_endian(x);</pre>
|
||||||
|
</blockquote>
|
||||||
|
</blockquote>
|
||||||
|
<pre><a name="effective_order"></a>order effective_order(order x) noexcept;
|
||||||
|
</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><i>Returns:</i> <code>x</code> if <code>x != order::native</code>, otherwise the <code>order</code> constant for the actual native byte order.</p><p><i>Example:</i></p><blockquote><pre>effective_order(order::big); // returns order::big
|
||||||
|
effective_order(order::little); // returns order::little
|
||||||
|
effective_order(order::native); // returns order::big if the native order
|
||||||
|
// is big-endian, otherwise order::little</pre></blockquote></blockquote><pre><a name="convert_value_runtime"></a>template <class ReversibleValue>
|
||||||
|
ReversibleValue convert_value(ReversibleValue from,
|
||||||
|
order from_order, order to_order) noexcept;
|
||||||
|
<a name="convert_runtime"></a>template <class Reversible>
|
||||||
|
void convert(Reversible& x,
|
||||||
|
order from_order, order to_order) noexcept;</pre><blockquote><p><i>Returns (first form)</i>: <code>from</code> if <code>effect_order(from_order) == effective_order(to_order)</code>, otherwise <code>reverse_value(from)</code>.</p>
|
||||||
|
<p><i>Effects (second form):</i> None if <code>effect_order(from_order) == effective_order(to_order)</code>, otherwise <code>reverse(x)</code>.</p>
|
||||||
|
<p><i>Example:</i></p>
|
||||||
|
<blockquote>
|
||||||
|
<pre>int32_t x;
|
||||||
|
<i>... read an external value of an endianness know only at runtime into x</i>
|
||||||
|
convert(x, some_order, order::native); // convert to native byte order if needed</pre>
|
||||||
|
</blockquote>
|
||||||
|
</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 the template versions of <code>reverse()</code> and <code>reverse_value()</code>
|
||||||
|
in a detail namespace?</b></p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
|
||||||
|
<p>They are unsafe for general use. Consider reversing
|
||||||
|
the bytes of a <code>std::pai<b>r</b></code> as a whole - the bytes from <code>first</code>
|
||||||
|
would end up in <code>second</code> and visa versa, and this is totally
|
||||||
|
wrong!</p>
|
||||||
|
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<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 floating point types and 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 <a href="../include/boost/endian/detail/intrinsic.hpp">boost/endian/detail/intrinsic.hpp</a>.</p>
|
||||||
|
<hr>
|
||||||
|
<p>Last revised:
|
||||||
|
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->28 May, 2013<!--webbot bot="Timestamp" endspan i-checksum="13992" --></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>
|
595
index.html
Normal file
595
index.html
Normal file
@@ -0,0 +1,595 @@
|
|||||||
|
<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>Boost Endian Library</title>
|
||||||
|
<style type="text/css">
|
||||||
|
ins {background-color:#CCFFCC}
|
||||||
|
del {background-color:#FFCACA}
|
||||||
|
body { font-family: sans-serif; width:8.0in; }
|
||||||
|
pre { background-color:#D7EEFF }
|
||||||
|
</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.png (6897 bytes)" align="middle" border="0" width="277" height="86"></a></td>
|
||||||
|
<td align="middle">
|
||||||
|
<font size="7">Endian Library</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.htm">Boost Home</a>
|
||||||
|
<a href="index.html">Endian Home</a>
|
||||||
|
<a href="conversion.html">Conversion Functions</a>
|
||||||
|
<a href="types.html">Endian Types</a></b></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<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 approaches</a><br>
|
||||||
|
<a href="#Intrinsic">Intrinsic built-in support</a><br>
|
||||||
|
<a href="#Performance">Performance</a><br>
|
||||||
|
<a href="#Timings">Timings</a><br>
|
||||||
|
<a href="#Conclusions">Conclusions</a><br>
|
||||||
|
<a href="#FAQ">FAQ</a><br>
|
||||||
|
<a href="#Release-history">Release history</a><br>
|
||||||
|
<a href="#Acknowledgements">Acknowledgements</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" bgcolor="#D7EEFF" align="center">
|
||||||
|
<b><i>Headers</i></b></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" bgcolor="#E8F5FF">
|
||||||
|
<a href="../../../boost/endian/conversion.hpp"><boost/endian/conversion.hpp></a><br>
|
||||||
|
<a href="../../../boost/endian/types.hpp"><boost/endian/types.hpp></a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="Abstract">Abstract</a></h2>
|
||||||
|
|
||||||
|
<p>Boost.Endian provides facilities to manipulate the endianness of integers,
|
||||||
|
floating point, and user defined data.</p>
|
||||||
|
<ul>
|
||||||
|
<li>The primary use case is binary I/O for portable data exchange with
|
||||||
|
other systems, via either file or network transmission.<br>
|
||||||
|
</li>
|
||||||
|
<li>A secondary use case is minimizing storage size via sizes and/or
|
||||||
|
alignments not supported by the built-in types.<br>
|
||||||
|
</li>
|
||||||
|
<li>Two distinct approaches to dealing with endianness are provided. Each approach has a
|
||||||
|
long history of successful use, and each approach has use cases where it is
|
||||||
|
superior to the other approach.</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 the 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 the Wikipedia's
|
||||||
|
<a href="http://en.wikipedia.org/wiki/Endianness">Endianness</a> article for an
|
||||||
|
extensive discussion of endianness.</p>
|
||||||
|
<p>Most programmers can ignore endianness, except perhaps for reading a core
|
||||||
|
dump on little-endian systems. Programmers have to deal with endianness in their
|
||||||
|
code when exchanging binary integers and binary floating point
|
||||||
|
values between computer systems with differing endianness, whether by physical file transfer or over a network,
|
||||||
|
. </p>
|
||||||
|
<h2><a name="Introduction">Introduction</a> to the Boost.Endian library</h2>
|
||||||
|
|
||||||
|
<p>The Boost.Endian library provides two different approaches to dealing with
|
||||||
|
integer endianness. Both approaches support integers, floating point types
|
||||||
|
except <code>long double</code>, and user defined types (UDTs).</p>
|
||||||
|
|
||||||
|
<p>Each approach has a long history of successful use, and each approach has use
|
||||||
|
cases where it is superior to the other approach.</p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
|
||||||
|
<p><b><a href="types.html">Endian types</a> -</b> The application uses the provided endian types
|
||||||
|
which mimic the
|
||||||
|
built-in integer types. For example, <code>big_int32_t</code> or <code>little_float64_t</code>.
|
||||||
|
Integer types with lengths of 1 through 8 bytes are supported, rather than just
|
||||||
|
2, 4, and 8 byte integers. The types may be aligned or unaligned.</p>
|
||||||
|
|
||||||
|
<p><b><a href="conversion.html">Endian conversion functions</a> -</b> The
|
||||||
|
application uses the built-in integer and floating point types, 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>
|
||||||
|
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<p>Boost Endian is a header-only library.</p>
|
||||||
|
|
||||||
|
<h2><a name="Choosing">Choosing</a> between endian types and endian
|
||||||
|
conversion functions</h2>
|
||||||
|
|
||||||
|
<p>Which approach is better for dealing with endianness depends on
|
||||||
|
application needs.</p>
|
||||||
|
|
||||||
|
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
|
||||||
|
<tr>
|
||||||
|
<th colspan="2">Needs that favor one approach over the other</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th width="50%"><b><a href="types.html">Endian types</a> are better with
|
||||||
|
these needs</b></th>
|
||||||
|
<th><b><a href="conversion.html">Endian conversion functions</a> are better
|
||||||
|
with these needs</b></th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top">
|
||||||
|
<ul>
|
||||||
|
<li>A need to simplify program logic and eliminate logic
|
||||||
|
errors. Since the endian types mimic the built-in types, there is no need to reason about the current endianness of variables
|
||||||
|
and that can simplify program logic and eliminate logic errors.<br>
|
||||||
|
</li>
|
||||||
|
<li>A need to use unusual integer sizes (i.e. 3, 5,
|
||||||
|
6, or 7 bytes) to reduce internal and external space usage and
|
||||||
|
save I/O time.<br>
|
||||||
|
</li>
|
||||||
|
<li>A need to use unaligned variables. Endian types can eliminate padding bytes in
|
||||||
|
structures, reducing internal and external space usage and saving I/O
|
||||||
|
time. They can deals with structures defined like this:</li>
|
||||||
|
</ul>
|
||||||
|
<blockquote>
|
||||||
|
<p><code>struct S {<br>
|
||||||
|
uint16_t a;<br>
|
||||||
|
uint32_t b;<br>
|
||||||
|
} __attribute__ ((packed));</code></p>
|
||||||
|
</blockquote>
|
||||||
|
</td>
|
||||||
|
<td valign="top">
|
||||||
|
<ul>
|
||||||
|
<li>A need to leverage knowledge of developers who have been using C byte
|
||||||
|
swapping
|
||||||
|
functions for years.<br>
|
||||||
|
</li>
|
||||||
|
<li>A need to save CPU time when a variable is used many times
|
||||||
|
relative to its I/O.<br>
|
||||||
|
</li>
|
||||||
|
<li>A need to pass structures to third-party libraries expecting a
|
||||||
|
specific structure format.<br>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="Intrinsic">Intrinsic</a> built-in support</h2>
|
||||||
|
<p>Recent compilers, including GCC, Clang, and Microsoft, supply intrinsic
|
||||||
|
built-in support for byte swapping. Such support is automatically detected and
|
||||||
|
used since it may in smaller and faster generated code, particularly for release
|
||||||
|
builds.</p>
|
||||||
|
<p dir="ltr">Defining <code>BOOST_ENDIAN_NO_INTRINSICS</code> will suppress use
|
||||||
|
of the intrinsics. Please try defining it if you get compiler errors, such as
|
||||||
|
header byteswap.h not being found.</p>
|
||||||
|
<p dir="ltr">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.</p>
|
||||||
|
|
||||||
|
<h2><a name="Performance">Performance</a></h2>
|
||||||
|
|
||||||
|
<p>Consider this problem:</p>
|
||||||
|
|
||||||
|
<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 type approach</b></i></td>
|
||||||
|
<td><i><b>Endian conversion approach</b></i></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top">
|
||||||
|
<pre>big_int32_t 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_endian(x);
|
||||||
|
x += 100;
|
||||||
|
big_endian(x);
|
||||||
|
|
||||||
|
... write x to a file ...
|
||||||
|
</pre>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p>There will be no performance difference between the two approaches,
|
||||||
|
regardless of the native endianness of the machine. Optimizing compilers will likely
|
||||||
|
generate exactly the same code for both. That conclusion was confirmed by
|
||||||
|
studying the generated assembly code.</p>
|
||||||
|
|
||||||
|
<p>Now consider a slightly different problem: </p>
|
||||||
|
|
||||||
|
<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 type approach</b></i></td>
|
||||||
|
<td><i><b>Endian conversion approach</b></i></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top">
|
||||||
|
<pre>big_int32_t 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_endian(x);
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < 1000000; ++i)
|
||||||
|
x += i;
|
||||||
|
|
||||||
|
big_endian(x);
|
||||||
|
|
||||||
|
... write x to a file ...
|
||||||
|
</pre>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p>With the Endian type approach, an implicit conversion from and then back to
|
||||||
|
big endian is done inside the loop. With the Endian conversion function
|
||||||
|
approach, the conversions are explicit, so only need to be done once, before and
|
||||||
|
after the loop.</p>
|
||||||
|
|
||||||
|
<h3><a name="Timings">Timings</a> for Example 2 (conversion functions hoisted
|
||||||
|
out of loop)</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 <a href="../test/loop_time_test.cpp">loop_time_test.cpp</a> and
|
||||||
|
<a href="../build/Jamfile.v2">Jamfile.v2</a> for the actual code and build
|
||||||
|
setup.
|
||||||
|
(For GCC 4.7, there are no 16-bit intrinsics, so they are emulated by using
|
||||||
|
32-bit intrinsics.)</p>
|
||||||
|
|
||||||
|
<table border="1" cellpadding="5" cellspacing="0"style="border-collapse: collapse" bordercolor="#111111">
|
||||||
|
<tr><td colspan="6" align="center"><b>GNU C++ version 4.7.0</b></td></tr>
|
||||||
|
<tr><td colspan="6" align="center"><b> Iterations: 1000000000, Intrinsics: __builtin_bswap16, etc.</b></td></tr>
|
||||||
|
<tr><td><b>Test Case</b></td>
|
||||||
|
<td align="center"><b>Endian<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">1.37 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
<tr><td>16-bit aligned little endian</td><td align="right">0.83 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
<tr><td>16-bit unaligned big endian</td><td align="right">1.09 s</td><td align="right">0.83 s</td></tr>
|
||||||
|
<tr><td>16-bit unaligned little endian</td><td align="right">1.09 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
<tr><td>32-bit aligned big endian</td><td align="right">0.98 s</td><td align="right">0.27 s</td></tr>
|
||||||
|
<tr><td>32-bit aligned little endian</td><td align="right">0.28 s</td><td align="right">0.27 s</td></tr>
|
||||||
|
<tr><td>32-bit unaligned big endian</td><td align="right">3.82 s</td><td align="right">0.27 s</td></tr>
|
||||||
|
<tr><td>32-bit unaligned little endian</td><td align="right">3.82 s</td><td align="right">0.27 s</td></tr>
|
||||||
|
<tr><td>64-bit aligned big endian</td><td align="right">1.65 s</td><td align="right">0.41 s</td></tr>
|
||||||
|
<tr><td>64-bit aligned little endian</td><td align="right">0.41 s</td><td align="right">0.41 s</td></tr>
|
||||||
|
<tr><td>64-bit unaligned big endian</td><td align="right">17.53 s</td><td align="right">0.41 s</td></tr>
|
||||||
|
<tr><td>64-bit unaligned little endian</td><td align="right">17.52 s</td><td align="right">0.41 s</td></tr>
|
||||||
|
|
||||||
|
<tr><td colspan="6" align="center"><b> Iterations: 1000000000, Intrinsics: no byte swap intrinsics</b></td></tr>
|
||||||
|
<tr><td><b>Test Case</b></td>
|
||||||
|
<td align="center"><b>Endian<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">1.95 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
<tr><td>16-bit aligned little endian</td><td align="right">0.83 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
<tr><td>16-bit unaligned big endian</td><td align="right">1.19 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
<tr><td>16-bit unaligned little endian</td><td align="right">1.20 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
<tr><td>32-bit aligned big endian</td><td align="right">0.97 s</td><td align="right">0.28 s</td></tr>
|
||||||
|
<tr><td>32-bit aligned little endian</td><td align="right">0.27 s</td><td align="right">0.28 s</td></tr>
|
||||||
|
<tr><td>32-bit unaligned big endian</td><td align="right">4.10 s</td><td align="right">0.27 s</td></tr>
|
||||||
|
<tr><td>32-bit unaligned little endian</td><td align="right">4.10 s</td><td align="right">0.27 s</td></tr>
|
||||||
|
<tr><td>64-bit aligned big endian</td><td align="right">1.64 s</td><td align="right">0.42 s</td></tr>
|
||||||
|
<tr><td>64-bit aligned little endian</td><td align="right">0.41 s</td><td align="right">0.41 s</td></tr>
|
||||||
|
<tr><td>64-bit unaligned big endian</td><td align="right">17.52 s</td><td align="right">0.42 s</td></tr>
|
||||||
|
<tr><td>64-bit unaligned little endian</td><td align="right">17.52 s</td><td align="right">0.41 s</td></tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p></p>
|
||||||
|
|
||||||
|
<table border="1" cellpadding="5" cellspacing="0"style="border-collapse: collapse" bordercolor="#111111">
|
||||||
|
<tr><td colspan="6" align="center"><b>Microsoft Visual C++ version 11.0</b></td></tr>
|
||||||
|
<tr><td colspan="6" align="center"><b> Iterations: 1000000000, Intrinsics: cstdlib _byteswap_ushort, etc.</b></td></tr>
|
||||||
|
<tr><td><b>Test Case</b></td>
|
||||||
|
<td align="center"><b>Endian<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">2.18 s</td><td align="right">0.83 s</td></tr>
|
||||||
|
<tr><td>16-bit aligned little endian</td><td align="right">0.81 s</td><td align="right">0.83 s</td></tr>
|
||||||
|
<tr><td>16-bit unaligned big endian</td><td align="right">1.64 s</td><td align="right">0.83 s</td></tr>
|
||||||
|
<tr><td>16-bit unaligned little endian</td><td align="right">1.64 s</td><td align="right">0.83 s</td></tr>
|
||||||
|
<tr><td>32-bit aligned big endian</td><td align="right">0.83 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
<tr><td>32-bit aligned little endian</td><td align="right">0.83 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
<tr><td>32-bit unaligned big endian</td><td align="right">3.01 s</td><td align="right">0.83 s</td></tr>
|
||||||
|
<tr><td>32-bit unaligned little endian</td><td align="right">3.01 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
<tr><td>64-bit aligned big endian</td><td align="right">1.09 s</td><td align="right">1.05 s</td></tr>
|
||||||
|
<tr><td>64-bit aligned little endian</td><td align="right">0.83 s</td><td align="right">1.03 s</td></tr>
|
||||||
|
<tr><td>64-bit unaligned big endian</td><td align="right">12.64 s</td><td align="right">1.01 s</td></tr>
|
||||||
|
<tr><td>64-bit unaligned little endian</td><td align="right">8.41 s</td><td align="right">0.83 s</td></tr>
|
||||||
|
|
||||||
|
<tr><td colspan="6" align="center"><b> Iterations: 1000000000, Intrinsics: no byte swap intrinsics</b></td></tr>
|
||||||
|
<tr><td><b>Test Case</b></td>
|
||||||
|
<td align="center"><b>Endian<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">0.84 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
<tr><td>16-bit aligned little endian</td><td align="right">0.83 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
<tr><td>16-bit unaligned big endian</td><td align="right">1.65 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
<tr><td>16-bit unaligned little endian</td><td align="right">1.65 s</td><td align="right">0.83 s</td></tr>
|
||||||
|
<tr><td>32-bit aligned big endian</td><td align="right">3.46 s</td><td align="right">0.83 s</td></tr>
|
||||||
|
<tr><td>32-bit aligned little endian</td><td align="right">0.81 s</td><td align="right">0.83 s</td></tr>
|
||||||
|
<tr><td>32-bit unaligned big endian</td><td align="right">3.01 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
<tr><td>32-bit unaligned little endian</td><td align="right">3.01 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
<tr><td>64-bit aligned big endian</td><td align="right">10.50 s</td><td align="right">0.83 s</td></tr>
|
||||||
|
<tr><td>64-bit aligned little endian</td><td align="right">0.83 s</td><td align="right">0.97 s</td></tr>
|
||||||
|
<tr><td>64-bit unaligned big endian</td><td align="right">12.62 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
<tr><td>64-bit unaligned little endian</td><td align="right">8.42 s</td><td align="right">0.81 s</td></tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
<h3><a name="Conclusions">Conclusions</a></h3>
|
||||||
|
|
||||||
|
<p>When program logic dictates the same number of conversions for both Endian
|
||||||
|
integer approach and Endian conversion function approach (<a href="#Example-1">example
|
||||||
|
1</a>):</p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
|
||||||
|
<p><b>There will be no performance difference between the two approaches,
|
||||||
|
regardless of the native endianness of the machine.</b> Optimizing compilers will likely
|
||||||
|
generate exactly the same code for both. This conclusion was confirmed by
|
||||||
|
studying the generated assembly code.</p>
|
||||||
|
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<p>When program logic dictates many more conversions for the Endian integer
|
||||||
|
approach than the Endian conversion function approach (<a href="#Example-2">example
|
||||||
|
2</a>):</p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
|
||||||
|
<p><b>There may be a considerable performance difference. </b>If machine endianness differs from the
|
||||||
|
desired endianness, the Endian type approach must do the byte reversal many
|
||||||
|
times while the Endian conversion approach only does the reversal once. But if
|
||||||
|
the endianness is the same, there is no conversion with either approach and no
|
||||||
|
conversion code is generated for typical release builds.</p>
|
||||||
|
|
||||||
|
<p><b>Whether or not compiler byte swap intrinsics are explicitly available has little
|
||||||
|
impact as tested.</b> Byte swap intrinsics are not available on some older
|
||||||
|
compilers and on some machine architectures, such as pre-486 X86 CPUs.</p>
|
||||||
|
|
||||||
|
<p><b>Unaligned types are much slower that aligned types, regardless of
|
||||||
|
endianness considerations.</b> Instead of single instruction register loads and
|
||||||
|
stores, multiple instructions are required.</p>
|
||||||
|
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Overall <a name="FAQ">FAQ</a></h2>
|
||||||
|
|
||||||
|
<p><b>Is the implementation header only?</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 to save internal or external
|
||||||
|
memory space is a minor secondary use case.</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>Binary arithmetic data is smaller and therefore I/O is faster and file sizes
|
||||||
|
are smaller. Transfer between systems is less expensive. Standard interchange
|
||||||
|
formats often specify binary arithmetic data.</p>
|
||||||
|
<p>Furthermore, binary arithmetic data is of fixed size, and so fixed-size disk
|
||||||
|
records are possible without padding, easing sorting and allowing direct access.
|
||||||
|
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 a
|
||||||
|
bit more of an industry standard, but little-endian may be preferred for
|
||||||
|
applications that run primarily Intel/AMD on x86, x64, 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 is only big, little, and 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 historical curiosities
|
||||||
|
but have no relevance to C++ developers.</p>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<p><b>What are the limitations of floating point support?</b></p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
|
||||||
|
<p>The only supported types are four byte <code>float</code> and eight byte
|
||||||
|
<code>double</code>. Even after endianness has been accounted for, floating
|
||||||
|
point values will not be portable between systems that use different floating
|
||||||
|
point formats. Systems where the integer endianness differs from floating point
|
||||||
|
endianness are not supported.</p>
|
||||||
|
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<p><b>What are the limitations of integer support?</b></p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
|
||||||
|
<p>Only 16-bit, 32-bit, and 64-bit integers are supported. Tests have only been
|
||||||
|
performed on machines that use two's complement arithmetic.</p>
|
||||||
|
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<h2><a name="Release-history">Release history</a></h2>
|
||||||
|
<h3>Changes since formal review</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Headers have been renamed to endian/types.hpp and endian/conversion.hpp.
|
||||||
|
Infrastructure file names were changed accordingly.</li>
|
||||||
|
<li>The endian types and endian conversion functions now support 32-bit (<code>float)</code> and
|
||||||
|
64-bit <code>(double)</code> floating point, as requested.</li>
|
||||||
|
<li>Both the endian types and endian conversion functions now support UDTs, as requested.</li>
|
||||||
|
<li>The endian type aliases have been renamed,
|
||||||
|
using a naming pattern that is consistent for both integer and floating point,
|
||||||
|
and that emphasizes that aligned types are usually preferred compared to
|
||||||
|
unaligned types. Unaligned types are deliberately given slightly uglier names.</li>
|
||||||
|
<li>The conversion functions have been much revised,
|
||||||
|
refactored, and otherwise improved based on review comments.<ul>
|
||||||
|
<li>Functions have been renamed to clarify their functionality.</li>
|
||||||
|
<li>Both return-by-value and modify-in-place interfaces are provided, as
|
||||||
|
requested.</li>
|
||||||
|
<li>Synonyms for the BSD byte swapping function names popularized by OS X
|
||||||
|
and Linux are provided, so that that developers already used to these name
|
||||||
|
can continue to use them if they wish.</li>
|
||||||
|
<li>In addition to the named-endianness functions, functions that perform
|
||||||
|
compile-time (via template) and run-time (via function argument) dispatch
|
||||||
|
are now provided, as requested.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Compiler (Clang, GCC, VisualC++, etc.) intrinsics and built-in functions
|
||||||
|
are used in the implementation where appropriate, as requested.</li>
|
||||||
|
<li>For the endian types, the implementation uses the endian conversion functions,
|
||||||
|
and thus the intrinsics,
|
||||||
|
as requested.</li>
|
||||||
|
<li>C++11 features such as <code>noexcept</code> are now used, while still
|
||||||
|
supporting C++03 compilers.</li>
|
||||||
|
<li>Acknowledgements have been updated.</li>
|
||||||
|
<li>Headers have been reorganized to make them easier to read,
|
||||||
|
with a synopsis at the front and implementation following, as requested.</li>
|
||||||
|
<li>Documentation has been revised to address most, but not all, concerns
|
||||||
|
raised during formal review.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a name="Acknowledgements">Acknowledgements</a></h2>
|
||||||
|
<p>Comments and suggestions were
|
||||||
|
received from
|
||||||
|
Adder, Benaka Moorthi,
|
||||||
|
Christopher Kohlhoff,
|
||||||
|
Cliff Green, Daniel James, Gennaro Proto,
|
||||||
|
Giovanni Piero Deretta, Gordon Woodhull, dizzy, Hartmut Kaiser, Jeff Flinn,
|
||||||
|
John Filo, John Maddock,
|
||||||
|
Kim Barrett,
|
||||||
|
Marsh Ray,
|
||||||
|
Martin Bonner, Mathias Gaunard, Matias Capeletto,
|
||||||
|
Neil Mayhew, Paul Bristow, Phil Endecott, Pyry Jahkola, Rene Rivera,
|
||||||
|
Robert Stewart, Roland Schwarz, Scott McMurray,
|
||||||
|
Sebastian Redl,
|
||||||
|
Tim Blechmann, Tim Moore, tymofey, Tomas Puverle, Vincente Botet, Yuval Ronen
|
||||||
|
and Vitaly Budovski,.</p>
|
||||||
|
<hr>
|
||||||
|
<p>Last revised:
|
||||||
|
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->28 May, 2013<!--webbot bot="Timestamp" endspan i-checksum="13992" --></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>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
624
types.html
Normal file
624
types.html
Normal file
@@ -0,0 +1,624 @@
|
|||||||
|
<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>Boost Endian Integers</title>
|
||||||
|
<style type="text/css">
|
||||||
|
ins {background-color:#CCFFCC}
|
||||||
|
del {background-color:#FFCACA}
|
||||||
|
body { font-family: sans-serif; width:8.0in; }
|
||||||
|
pre { background-color:#D7EEFF }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="710">
|
||||||
|
<tr>
|
||||||
|
<td width="277">
|
||||||
|
<a href="../../../index.html">
|
||||||
|
<img src="../../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86" border="0"></a></td>
|
||||||
|
<td width="413" align="middle">
|
||||||
|
<font size="7">Endian Types</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.htm">Boost Home</a>
|
||||||
|
<a href="index.html">Endian Home</a>
|
||||||
|
<a href="conversion.html">Conversion Functions</a>
|
||||||
|
<a href="types.html">Endian Types</a></b></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<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">Typedefs</a><br>
|
||||||
|
<a href="#Comment-on-naming">Comment on naming</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="#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>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" bgcolor="#D7EEFF" align="center">
|
||||||
|
<b><i>Headers</i></b></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="100%" bgcolor="#E8F5FF">
|
||||||
|
<a href="../../../boost/endian/conversion.hpp"><boost/endian/conversion.hpp></a><br>
|
||||||
|
<a href="../../../boost/endian/types.hpp"><boost/endian/types.hpp></a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<h2><a name="Introduction">Introduction</a></h2>
|
||||||
|
<p>Header <a href="file:///D:/endian/boost/endian/types.hpp"><boost/endian/types.hpp></a> provides
|
||||||
|
integer-like byte-holder binary types with explicit 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">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 <code>+</code>, <code>-</code>, <code>~</code>,
|
||||||
|
<code>!</code>, prefix and postfix <code>--</code> and <code>++</code>. Binary
|
||||||
|
arithmetic operators are <code>+</code>, <code>+=</code>, <code>-</code>, <code>
|
||||||
|
-=</code>, <code>*</code>, <code>*=</code>, <code>/</code>, <code>/=</code>,
|
||||||
|
<code>%/ %=</code>, <code>&</code>, <code>&=</code>, <code>|</code>, <code>|=</code>,
|
||||||
|
<code>^</code>, <code>^=</code>, <code><<</code>, <code><<=</code>, <code>>></code>,
|
||||||
|
<code>>>=</code>. Binary relational operators are <code>==</code>, <code>!=</code>,
|
||||||
|
<code><</code>, <code><=</code>, <code>></code>, <code>>=</code>.</p>
|
||||||
|
<p>Automatic conversion is provided to the underlying integer value type.</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/types.hpp>
|
||||||
|
#include <boost/static_assert.hpp>
|
||||||
|
|
||||||
|
using namespace boost::endian;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// This is an extract from a very widely used GIS file format. Who knows
|
||||||
|
// why a designer would mix big and little endians in the same file - 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* [])
|
||||||
|
{
|
||||||
|
BOOST_STATIC_ASSERT(sizeof(header) == 16U); // reality check
|
||||||
|
|
||||||
|
header h;
|
||||||
|
|
||||||
|
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="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</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 do layout 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 will
|
||||||
|
no longer disqualify a type from being a POD. Thus under C++11, <code>endian</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>Integer | floating point</li>
|
||||||
|
<li>1-8 byte (unaligned) | 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 A = align::no>
|
||||||
|
class endian;
|
||||||
|
</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="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>
|
||||||
|
<td width="49%" align="center"><b><i>Alignment</i></b></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="18%"><code>big_int</code><i><b>n</b></i><code>_t</code></td>
|
||||||
|
<td width="10%" align="center"><code>big</code></td>
|
||||||
|
<td width="10%" align="center">signed</td>
|
||||||
|
<td width="15%">16,32,64</td>
|
||||||
|
<td width="49%" align="center"><code>yes</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="18%"><code>big_uint</code><i><b>n</b></i><code>_t</code></td>
|
||||||
|
<td width="10%" align="center"><code>big</code></td>
|
||||||
|
<td width="10%" align="center">unsigned</td>
|
||||||
|
<td width="15%">16,32,64</td>
|
||||||
|
<td width="49%" align="center"><code>yes</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="18%"><code>big_float</code><i><b>n</b></i><code>_t</code></td>
|
||||||
|
<td width="10%" align="center"><code>big</code></td>
|
||||||
|
<td width="10%" align="center">signed</td>
|
||||||
|
<td width="15%">32,64</td>
|
||||||
|
<td width="49%" align="center"><code>yes</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="18%"><code>little_int</code><i><b>n</b></i><code>_t</code></td>
|
||||||
|
<td width="10%" align="center"><code>little</code></td>
|
||||||
|
<td width="10%" align="center">signed</td>
|
||||||
|
<td width="15%">16,32,64</td>
|
||||||
|
<td width="49%" align="center"><code>yes</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="18%"><code>little_uint</code><i><b>n</b></i><code>_t</code></td>
|
||||||
|
<td width="10%" align="center"><code>little</code></td>
|
||||||
|
<td width="10%" align="center">unsigned</td>
|
||||||
|
<td width="15%">16,32,64</td>
|
||||||
|
<td width="49%" align="center"><code>yes</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="18%"><code>little_float</code><i><b>n</b></i><code>_t</code></td>
|
||||||
|
<td width="10%" align="center"><code>little</code></td>
|
||||||
|
<td width="10%" align="center">signed</td>
|
||||||
|
<td width="15%">32,64</td>
|
||||||
|
<td width="49%" align="center"><code>yes</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="18%"><code>big_int</code><b><i>n</i></b><code>un_t</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>
|
||||||
|
<td width="49%" align="center"><code>no</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="18%"><code>big_uint</code><i><b>n</b></i><code>un_</code><code>t</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>
|
||||||
|
<td width="49%" align="center"><code>no</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="18%"><code>big_float</code><i><b>n</b></i><code>un_t</code></td>
|
||||||
|
<td width="10%" align="center"><code>big</code></td>
|
||||||
|
<td width="10%" align="center">signed</td>
|
||||||
|
<td width="15%">32,64</td>
|
||||||
|
<td width="49%" align="center"><code>no</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="18%"><code>little_int</code><i><b>n</b></i><code>un_</code><code>t</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>
|
||||||
|
<td width="49%" align="center"><code>no</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="18%"><code>little_uint</code><i><b>n</b></i><code>un_</code><code>t</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>
|
||||||
|
<td width="49%" align="center"><code>no</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="18%"><code>little_float</code><i><b>n</b></i><code>un_t</code></td>
|
||||||
|
<td width="10%" align="center"><code>little</code></td>
|
||||||
|
<td width="10%" align="center">signed</td>
|
||||||
|
<td width="15%">32,64</td>
|
||||||
|
<td width="49%" align="center"><code>no</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="18%"><code>native_int</code><i><b>n</b></i><code>un_</code><code>t</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>
|
||||||
|
<td width="49%" align="center"><code>no</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="18%"><code>native_uint</code><i><b>n</b></i><code>un_</code><code>t</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>
|
||||||
|
<td width="49%" align="center"><code>no</code></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. Furthermore, aligned types
|
||||||
|
are only available on architectures with 16, 32, and 64-bit integer types.</p>
|
||||||
|
<p><b><i>Note:</i></b> One-byte types
|
||||||
|
have identical
|
||||||
|
functionality. They are provided to improve code readability and searchability.</p>
|
||||||
|
<h2><a name="Class_template_endian">Class template <code>endian</code></a></h2>
|
||||||
|
<p>An endian 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 integers are supplied.</p>
|
||||||
|
<h3><a name="Synopsis">Synopsis</a></h3>
|
||||||
|
<pre>namespace boost
|
||||||
|
{
|
||||||
|
namespace endian
|
||||||
|
{
|
||||||
|
// C++11 features emulated if not available
|
||||||
|
|
||||||
|
enum class <a name="endianness">order</a> {big, little, native};
|
||||||
|
enum class <a name="alignment">align</a> {no, yes};
|
||||||
|
|
||||||
|
template <order Order, typename T, std::size_t n_bits, align A = align::no>
|
||||||
|
class endian
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef T value_type;
|
||||||
|
|
||||||
|
// if BOOST_ENDIAN_FORCE_PODNESS is defined && C++11 POD's are not
|
||||||
|
// available then these two constructors will not be present
|
||||||
|
<a href="#endian">endian</a>() noexcept = default;
|
||||||
|
explicit <a href="#explicit-endian">endian</a>(T v) noexcept;
|
||||||
|
|
||||||
|
endian& <a href="#operator-eq">operator=</a>(T v) noexcept;
|
||||||
|
<a href="#operator-T">operator T</a>() const noexcept;
|
||||||
|
const char* <a href="#data">data</a>() const noexcept;
|
||||||
|
|
||||||
|
// arithmetic operations; additional operators provided by 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef endian<order::big, float, 32, align::yes> big_float32_t;
|
||||||
|
typedef endian<order::big, double, 64, align::yes> big_float64_t;
|
||||||
|
|
||||||
|
// aligned little endian floating point types
|
||||||
|
typedef endian<order::little, float, 32, align::yes> little_float32_t;
|
||||||
|
typedef endian<order::little, double, 64, align::yes> little_float64_t;
|
||||||
|
|
||||||
|
// unaligned big endian floating point types
|
||||||
|
typedef endian<order::big, float, 32, align::no> big_float32un_t;
|
||||||
|
typedef endian<order::big, double, 64, align::no> big_float64un_t;
|
||||||
|
|
||||||
|
// unaligned little endian floating point types
|
||||||
|
typedef endian<order::little, float, 32, align::no> little_float32un_t;
|
||||||
|
typedef endian<order::little, double, 64, align::no> little_float64un_t;
|
||||||
|
|
||||||
|
// aligned big endian signed integer types
|
||||||
|
typedef endian<order::big, int16_t, 16, align::yes> big_int16_t;
|
||||||
|
typedef endian<order::big, int32_t, 32, align::yes> big_int32_t;
|
||||||
|
typedef endian<order::big, int64_t, 64, align::yes> big_int64_t;
|
||||||
|
|
||||||
|
// aligned big endian unsigned integer types
|
||||||
|
typedef endian<order::big, uint16_t, 16, align::yes> big_uint16_t;
|
||||||
|
typedef endian<order::big, uint32_t, 32, align::yes> big_uint32_t;
|
||||||
|
typedef endian<order::big, uint64_t, 64, align::yes> big_uint64_t;
|
||||||
|
|
||||||
|
// aligned little endian signed integer types
|
||||||
|
typedef endian<order::little, int16_t, 16, align::yes> little_int16_t;
|
||||||
|
typedef endian<order::little, int32_t, 32, align::yes> little_int32_t;
|
||||||
|
typedef endian<order::little, int64_t, 64, align::yes> little_int64_t;
|
||||||
|
|
||||||
|
// aligned little endian unsigned integer types
|
||||||
|
typedef endian<order::little, uint16_t, 16, align::yes> little_uint16_t;
|
||||||
|
typedef endian<order::little, uint32_t, 32, align::yes> little_uint32_t;
|
||||||
|
typedef endian<order::little, uint64_t, 64, align::yes> little_uint64_t;
|
||||||
|
|
||||||
|
// aligned native endian typedefs are not provided because
|
||||||
|
// <cstdint> types are superior for this use case
|
||||||
|
|
||||||
|
// unaligned big endian signed integer types
|
||||||
|
typedef endian<order::big, int_least8_t, 8> big_int8un_t;
|
||||||
|
typedef endian<order::big, int_least16_t, 16> big_int16un_t;
|
||||||
|
typedef endian<order::big, int_least32_t, 24> big_int24un_t;
|
||||||
|
typedef endian<order::big, int_least32_t, 32> big_int32un_t;
|
||||||
|
typedef endian<order::big, int_least64_t, 40> big_int40un_t;
|
||||||
|
typedef endian<order::big, int_least64_t, 48> big_int48un_t;
|
||||||
|
typedef endian<order::big, int_least64_t, 56> big_int56un_t;
|
||||||
|
typedef endian<order::big, int_least64_t, 64> big_int64un_t;
|
||||||
|
|
||||||
|
// unaligned big endian unsigned integer types
|
||||||
|
typedef endian<order::big, uint_least8_t, 8> big_uint8un_t;
|
||||||
|
typedef endian<order::big, uint_least16_t, 16> big_uint16un_t;
|
||||||
|
typedef endian<order::big, uint_least32_t, 24> big_uint24un_t;
|
||||||
|
typedef endian<order::big, uint_least32_t, 32> big_uint32un_t;
|
||||||
|
typedef endian<order::big, uint_least64_t, 40> big_uint40un_t;
|
||||||
|
typedef endian<order::big, uint_least64_t, 48> big_uint48un_t;
|
||||||
|
typedef endian<order::big, uint_least64_t, 56> big_uint56un_t;
|
||||||
|
typedef endian<order::big, uint_least64_t, 64> big_uint64un_t;
|
||||||
|
|
||||||
|
// unaligned little endian signed integer types
|
||||||
|
typedef endian<order::little, int_least8_t, 8> little_int8un_t;
|
||||||
|
typedef endian<order::little, int_least16_t, 16> little_int16un_t;
|
||||||
|
typedef endian<order::little, int_least32_t, 24> little_int24un_t;
|
||||||
|
typedef endian<order::little, int_least32_t, 32> little_int32un_t;
|
||||||
|
typedef endian<order::little, int_least64_t, 40> little_int40un_t;
|
||||||
|
typedef endian<order::little, int_least64_t, 48> little_int48un_t;
|
||||||
|
typedef endian<order::little, int_least64_t, 56> little_int56un_t;
|
||||||
|
typedef endian<order::little, int_least64_t, 64> little_int64un_t;
|
||||||
|
|
||||||
|
// unaligned little endian unsigned integer types
|
||||||
|
typedef endian<order::little, uint_least8_t, 8> little_uint8un_t;
|
||||||
|
typedef endian<order::little, uint_least16_t, 16> little_uint16un_t;
|
||||||
|
typedef endian<order::little, uint_least32_t, 24> little_uint24un_t;
|
||||||
|
typedef endian<order::little, uint_least32_t, 32> little_uint32un_t;
|
||||||
|
typedef endian<order::little, uint_least64_t, 40> little_uint40un_t;
|
||||||
|
typedef endian<order::little, uint_least64_t, 48> little_uint48un_t;
|
||||||
|
typedef endian<order::little, uint_least64_t, 56> little_uint56un_t;
|
||||||
|
typedef endian<order::little, uint_least64_t, 64> little_uint64un_t;
|
||||||
|
|
||||||
|
// unaligned native endian signed integer types
|
||||||
|
typedef endian<order::native, int_least8_t, 8> native_int8un_t;
|
||||||
|
typedef endian<order::native, int_least16_t, 16> native_int16un_t;
|
||||||
|
typedef endian<order::native, int_least32_t, 24> native_int24un_t;
|
||||||
|
typedef endian<order::native, int_least32_t, 32> native_int32un_t;
|
||||||
|
typedef endian<order::native, int_least64_t, 40> native_int40un_t;
|
||||||
|
typedef endian<order::native, int_least64_t, 48> native_int48un_t;
|
||||||
|
typedef endian<order::native, int_least64_t, 56> native_int56un_t;
|
||||||
|
typedef endian<order::native, int_least64_t, 64> native_int64un_t;
|
||||||
|
|
||||||
|
// unaligned native endian unsigned integer types
|
||||||
|
typedef endian<order::native, uint_least8_t, 8> native_uint8un_t;
|
||||||
|
typedef endian<order::native, uint_least16_t, 16> native_uint16un_t;
|
||||||
|
typedef endian<order::native, uint_least32_t, 24> native_uint24un_t;
|
||||||
|
typedef endian<order::native, uint_least32_t, 32> native_uint32un_t;
|
||||||
|
typedef endian<order::native, uint_least64_t, 40> native_uint40un_t;
|
||||||
|
typedef endian<order::native, uint_least64_t, 48> native_uint48un_t;
|
||||||
|
typedef endian<order::native, uint_least64_t, 56> native_uint56un_t;
|
||||||
|
typedef endian<order::native, uint_least64_t, 64> native_uint64un_t;
|
||||||
|
|
||||||
|
} // namespace endian
|
||||||
|
} // namespace boost</pre>
|
||||||
|
<h3><a name="Members">Members</a></h3>
|
||||||
|
<p><code><a name="endian">endian</a>() = default; // C++03: endian(){}</code></p>
|
||||||
|
<blockquote>
|
||||||
|
<p><i>Effects:</i> Constructs an object of type <code>endian<E, T, n_bits, A></code>.</p>
|
||||||
|
</blockquote>
|
||||||
|
<p><code><a name="explicit-endian">explicit endian</a>(T v);</code></p>
|
||||||
|
<blockquote>
|
||||||
|
<p><i>Effects:</i> Constructs an object of type <code>endian<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>
|
||||||
|
<p><code>endian& <a name="operator-eq">operator=</a>(T v);</code></p>
|
||||||
|
<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>
|
||||||
|
<p><code><a name="operator-T">operator T</a>() const;</code></p>
|
||||||
|
<blockquote>
|
||||||
|
<p><i>Returns:</i> The current value stored in <code>*this</code>, converted to
|
||||||
|
<code>value_type</code>.</p>
|
||||||
|
</blockquote>
|
||||||
|
<p><code>const char* <a name="data">data</a>() const;</code></p>
|
||||||
|
<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>
|
||||||
|
<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 POD's?</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 endian integer types not being POD's 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>
|
||||||
|
<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 only in very limited
|
||||||
|
circumstances. 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>
|
||||||
|
<li>It is better software engineering if the same implementation works regardless
|
||||||
|
of the CPU endianness. In other words, #ifdefs should be avoided in user code.</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</code> are trivial, and
|
||||||
|
thus POD's.</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</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 , and so can be used in unions.
|
||||||
|
In C++11, <code>class endian</code> objects are POD's even though they have
|
||||||
|
constructors.</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</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. Vicente Botet and other reviewers
|
||||||
|
suggested supporting floating point types.</p>
|
||||||
|
<hr>
|
||||||
|
<p>Last revised:
|
||||||
|
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->28 May, 2013<!--webbot bot="Timestamp" endspan i-checksum="13992" --></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>
|
Reference in New Issue
Block a user