Endian: docs and examples improvements

git-svn-id: http://svn.boost.org/svn/boost/sandbox/endian@51855 b8fc166d-592f-0410-95f2-cb63ce0dd405
This commit is contained in:
bemandawes
2009-03-19 14:33:59 +00:00
parent 1218fc6f5c
commit 0f36e2670d
6 changed files with 133 additions and 47 deletions

View File

@@ -39,13 +39,13 @@
# error Platforms with CHAR_BIT != 8 are not supported # error Platforms with CHAR_BIT != 8 are not supported
# endif # endif
# ifndef BOOST_NO_DEFAULTED_FUNCTIONS # ifdef BOOST_NO_DEFAULTED_FUNCTIONS
# define BOOST_ENDIAN_DEFAULT_CONSTRUCT = default; // C++0x
# else
# define BOOST_ENDIAN_DEFAULT_CONSTRUCT {} // C++03 # define BOOST_ENDIAN_DEFAULT_CONSTRUCT {} // C++03
# else
# define BOOST_ENDIAN_DEFAULT_CONSTRUCT = default; // C++0x
# endif # endif
# if defined(BOOST_NO_DEFAULTED_FUNCTIONS) && defined(BOOST_ENDIANS_IN_UNIONS) # if defined(BOOST_NO_DEFAULTED_FUNCTIONS) && defined(BOOST_ENDIAN_FORCE_PODNESS)
# define BOOST_ENDIAN_NO_CTORS # define BOOST_ENDIAN_NO_CTORS
# endif # endif

View File

@@ -15,9 +15,10 @@
#include <ostream> #include <ostream>
#include <istream> #include <istream>
// unformatted binary (as opposed to formatted character-set) input and output // unformatted binary (as opposed to formatted character) stream insertion
// and extraction.
// Caution: Use only on streams opened with filemode std::ios_base::binary. Thus // Warning: Use only on streams opened with filemode std::ios_base::binary. Thus
// unformatted binary I/O should not be with the standard streams (cout, cin, etc.) // unformatted binary I/O should not be with the standard streams (cout, cin, etc.)
// since they are opened in text mode. Use on text streams may produce incorrect // since they are opened in text mode. Use on text streams may produce incorrect
// results, such as insertion of unwanted characters or premature end-of-file. // results, such as insertion of unwanted characters or premature end-of-file.

View File

@@ -37,6 +37,7 @@
<tr> <tr>
<td width="100%" bgcolor="#E8F5FF"> <td width="100%" bgcolor="#E8F5FF">
<a href="#Introduction">Introduction</a><br> <a href="#Introduction">Introduction</a><br>
<a href="#Hello-endian-world">Hello endian world</a><br>
<a href="#Limitations">Limitations</a><br> <a href="#Limitations">Limitations</a><br>
<a href="#Feature-set">Feature set</a><br> <a href="#Feature-set">Feature set</a><br>
<a href="#Types">Typedefs</a><br> <a href="#Types">Typedefs</a><br>
@@ -46,9 +47,12 @@
<a href="#Synopsis">Synopsis</a><br> <a href="#Synopsis">Synopsis</a><br>
&nbsp;&nbsp;&nbsp; <a href="#Members">Members</a><br> &nbsp;&nbsp;&nbsp; <a href="#Members">Members</a><br>
<a href="#FAQ">FAQ</a><br> <a href="#FAQ">FAQ</a><br>
<a href="#Binary-I-O-cautions">Binary I/O warnings and cautions</a><br>
<a href="#Example">Example</a><br> <a href="#Example">Example</a><br>
<a href="#Design">Design</a><br> <a href="#Design">Design</a><br>
<a href="#Experience">Experience</a><br> <a href="#Experience">Experience</a><br>
<a href="#C++0x">C++0x</a><br>
<a href="#Compilation">Compilation</a><br>
<a href="#Acknowledgements">Acknowledgements</a> <a href="#Acknowledgements">Acknowledgements</a>
</td> </td>
</tr> </tr>
@@ -59,7 +63,8 @@
<tr> <tr>
<td width="100%" bgcolor="#E8F5FF"> <td width="100%" bgcolor="#E8F5FF">
<a href="../../../boost/integer/endian.hpp">&lt;boost/integer/endian.hpp&gt;</a><br> <a href="../../../boost/integer/endian.hpp">&lt;boost/integer/endian.hpp&gt;</a><br>
<a href="../../../boost/integer/endian_io.hpp">&lt;boost/integer/endian_io.hpp&gt;</a></td> <a href="../../../boost/integer/endian_binary_stream.hpp">&lt;boost/integer/endian_binary_stream.hpp&gt;</a><br>
<a href="../../../boost/binary_stream.hpp">&lt;boost/binary_stream.hpp&gt;</a></td>
</tr> </tr>
</table> </table>
<h2><a name="Introduction">Introduction</a></h2> <h2><a name="Introduction">Introduction</a></h2>
@@ -70,7 +75,7 @@ byte order, value type, size, and alignment. Typedefs provide easy-to-use names
for common configurations.</p> for common configurations.</p>
<p>These types provide portable byte-holders for integer data, independent of <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 particular computer architectures. Use cases almost always involve I/O, either via files or
network connections. Although portability is the primary motivation, these network connections. Although data portability is the primary motivation, these
integer byte-holders may integer byte-holders may
also be used to reduce memory use, file size, or network activity since they also be used to reduce memory use, file size, or network activity since they
provide binary integer sizes not otherwise available.</p> provide binary integer sizes not otherwise available.</p>
@@ -91,9 +96,43 @@ arithmetic operators are <code>+</code>, <code>+=</code>, <code>-</code>, <code>
<code>&gt;&gt;=</code>. Binary relational operators are <code>==</code>, <code>!=</code>, <code>&gt;&gt;=</code>. Binary relational operators are <code>==</code>, <code>!=</code>,
<code>&lt;</code>, <code>&lt;=</code>, <code>&gt;</code>, <code>&gt;=</code>.</p> <code>&lt;</code>, <code>&lt;=</code>, <code>&gt;</code>, <code>&gt;=</code>.</p>
<p>Automatic conversion is provided to the underlying integer value type.</p> <p>Automatic conversion is provided to the underlying integer value type.</p>
<p>Header <a href="../../../boost/integer/endian_io.hpp">&lt;boost/integer/endian_io.hpp&gt;</a> <p>Header <a href="../../../boost/integer/endian_binary_stream.hpp">&lt;boost/integer/endian_binary_stream.hpp&gt;</a>
provides operators <code>&lt;&lt;</code> and <code>&gt;&gt;</code> for provides operators &lt;= and <code>=&gt;</code> for unformatted binary (as opposed to
stream insertion and extraction.</p> formatted character) stream insertion and extraction of endian types.</p>
<p>Header <a href="../../../boost/binary_stream.hpp">&lt;boost/binary_stream.hpp&gt;</a>
provides operators &lt;= and <code>=&gt;</code> for unformatted binary (as opposed to
formatted character) stream insertion and extraction of built-in and std::string
types.</p>
<h2><a name="Hello-endian-world">Hello endian world</a></h2>
<blockquote>
<pre>#include &lt;boost/integer/endian.hpp&gt;
#include &lt;boost/integer/endian_binary_stream.hpp&gt;
#include &lt;boost/binary_stream.hpp&gt;
#include &lt;iostream&gt;
using namespace boost;
using namespace boost::integer;
int main()
{
int_least32_t v = 0x31323334L; // = ASCII { '1', '2', '3', '4' }
// value chosen to work on text stream
big32_t b(v);
little32_t l(v);
std::cout &lt;&lt; &quot;Hello, endian world!\n\n&quot;;
std::cout &lt;&lt; v &lt;&lt; ' ' &lt;&lt; b &lt;&lt; ' ' &lt;&lt; l &lt;&lt; '\n';
std::cout &lt;= v &lt;= ' ' &lt;= b &lt;= ' ' &lt;= l &lt;= '\n';
}</pre>
</blockquote>
<p>On a little-endian CPU, this program outputs:</p>
<blockquote>
<pre>Hello, endian world!
825373492 825373492 825373492
4321 1234 4321</pre>
</blockquote>
<h2><a name="Limitations">Limitations</a></h2> <h2><a name="Limitations">Limitations</a></h2>
<p>Requires <code>&lt;climits&gt;</code> <code>CHAR_BIT == 8</code>. If <code>CHAR_BIT</code> <p>Requires <code>&lt;climits&gt;</code> <code>CHAR_BIT == 8</code>. If <code>CHAR_BIT</code>
is some other value, compilation will result in an <code>#error</code>. This is some other value, compilation will result in an <code>#error</code>. This
@@ -395,11 +434,9 @@ alignment.</p>
compared to arithmetic operations on native integer types. However, these types compared to arithmetic operations on native integer types. However, these types
are usually be faster, and sometimes much faster, for I/O compared to stream are usually be faster, and sometimes much faster, for I/O compared to stream
inserters and extractors, or to serialization.</p> inserters and extractors, or to serialization.</p>
<p><b>Are endian types POD's?</b> In C++03, no. For C++0x, yes, after applying <p><b>Are endian types POD's?</b> Yes for C++0x. No for C++03, although several
<code> <a href="#Compilation">macros</a> are available to force PODness in all cases.</p>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">= <p><b>What are the implications endian types not being POD's of C++03?</b> They
default</a></code> to the default constructor.</p>
<p><b>What are the implications of C++03 endian types not being POD's?</b> They
can't be used in unions. In theory, compilers aren't required to align or lay can't be used in unions. In theory, compilers aren't required to align or lay
out storage in portable ways, although this problem has never been observed in a out storage in portable ways, although this problem has never been observed in a
real compiler.</p> real compiler.</p>
@@ -428,6 +465,27 @@ incrementing a variable in a record. It is very convenient to write:</p>
<pre wrap> int temp( record.foo); <pre wrap> int temp( record.foo);
++temp; ++temp;
record.foo = temp;</pre> record.foo = temp;</pre>
<p wrap><b>Why do binary stream insertion and extraction use operators &lt;= and &gt;=
rather than &lt;&lt;= and &gt;&gt;=?</b> &lt;&lt;= and &gt;&gt;= associate right-to-left, which is the
opposite of &lt;&lt; and &gt;&gt;, so would be very confusing and error prone. &lt;= and &gt;=
associate left-to-right. </p>
<h2><a name="Binary-I-O-cautions">Binary I/O warnings and cautions</a></h2>
<p><font color="#FF0000"><b><i><span style="background-color: #FFFFFF">Warning:</span></i></b></font><span style="background-color: #FFFFFF"> </span>&nbsp;Use
only on streams opened with filemode <code>std::ios_base::binary</code>. Thus
unformatted binary I/O should not be with the standard streams (cout, cin, etc.)
since they are opened in text mode. Use on text streams may produce incorrect
results, such as insertion of unwanted characters or premature end-of-file. For
example, on Windows 0x0D would become 0x0D, 0x0A.</p>
<p><i><b><font color="#FF0000">Caution:</font><font color="#FFFF00"> </font></b>
</i>When mixing formatted (i.e. operator &lt;&lt; or &gt;&gt;) and unformatted (i.e.
operator &lt;= or &gt;=) stream I/O, be aware that &lt;&lt; and &gt;&gt; take precedence over &lt;=
and &gt;=. Use parentheses to force correct order of evaluation. For example:</p>
<blockquote>
<pre>my_stream &lt;&lt; foo &lt;= bar; // no parentheses needed
(my_stream &lt;= foo) &lt;&lt; bar; // parentheses required </pre>
</blockquote>
<p>As a practical matter, it may be easier and safer to never mix the character
and binary insertion or extraction operators in the same statement.</p>
<h2><a name="Example">Example</a></h2> <h2><a name="Example">Example</a></h2>
<p>The <a href="../example/endian_example.cpp">endian_example.cpp</a> program writes a <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> binary file containing four byte big-endian and little-endian integers:</p>
@@ -437,15 +495,14 @@ binary file containing four byte big-endian and little-endian integers:</p>
#include &lt;cstdio&gt; #include &lt;cstdio&gt;
#include &lt;boost/integer/endian.hpp&gt; #include &lt;boost/integer/endian.hpp&gt;
using boost::integer::big32_t; using namespace boost::integer;
using boost::integer::little32_t;
namespace namespace
{ {
// This is a portion of a widely used GIS file format. I have no idea why // This is an extract from a very widely used GIS file format. I have no idea
// anyone would mix big and little endians in the same format - but it is // why a designer would mix big and little endians in the same file - but
// a real format and users wishing to write code manipulating files in that // this is a real-world format and users wishing to write low level code
// format have to deal with it. // manipulating these files have to deal with the mixed endianness.
struct header struct header
{ {
@@ -460,7 +517,7 @@ namespace
int main() int main()
{ {
assert( sizeof( header ) == 16 ); assert( sizeof( header ) == 16 ); // requirement for interoperability
header h; header h;
@@ -469,15 +526,15 @@ int main()
h.version = -1; h.version = -1;
h.shape_type = 0x04030201; h.shape_type = 0x04030201;
// Low-level I/O such as POSIX read/write or &lt;cstdio&gt; fread/fwrite is // Low-level I/O such as POSIX read/write or &lt;cstdio&gt; fread/fwrite is sometimes
// typically used for binary file operations. Such I/O is often performed in // used for binary file operations when ultimate efficiency is important.
// some C++ wrapper class, but to drive home the point that endian integers // Such I/O is often performed in some C++ wrapper class, but to drive home the
// are usually used in fairly low-level code, &lt;cstdio&gt; fopen/fwrite is used // point that endian integers are often used in fairly low-level code that
// for I/O in this example. // does bulk I/O operations, &lt;cstdio&gt; fopen/fwrite is used for I/O in this example.
std::FILE * fi; std::FILE * fi;
if ( !(fi = std::fopen( filename, &quot;wb&quot; )) ) if ( !(fi = std::fopen( filename, &quot;wb&quot; )) ) // MUST BE BINARY
{ {
std::cout &lt;&lt; &quot;could not open &quot; &lt;&lt; filename &lt;&lt; '\n'; std::cout &lt;&lt; &quot;could not open &quot; &lt;&lt; filename &lt;&lt; '\n';
return 1; return 1;
@@ -490,6 +547,7 @@ int main()
} }
std::fclose( fi ); std::fclose( fi );
std::cout &lt;&lt; &quot;created file &quot; &lt;&lt; filename &lt;&lt; '\n'; std::cout &lt;&lt; &quot;created file &quot; &lt;&lt; filename &lt;&lt; '\n';
return 0; return 0;
}</pre> }</pre>
@@ -527,6 +585,30 @@ several Boost programmers and used very successful in high-value, high-use
applications for many years. These independently developed endian libraries applications for many years. These independently developed endian libraries
often evolved from C libraries that were also widely used. Endian integers have proven widely useful across a wide often evolved from C libraries that were also widely used. Endian integers have proven widely useful across a wide
range of computer architectures and applications.</p> range of computer architectures and applications.</p>
<h2><a name="C++0x">C++0x</a></h2>
<p>The availability of the C++0x
<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++0x
<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>
&nbsp;</li>
<li>BOOST_ENDIAN_FORCE_PODNESS causes BOOST_ENDIAN_NO_CTORS to be defined if
the compiler does not support C++0x
<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++0x, <code>class endian</code> objects are POD's even though they have
constructors.</li>
</ul>
<h2><a name="Acknowledgements">Acknowledgements</a></h2> <h2><a name="Acknowledgements">Acknowledgements</a></h2>
<p>Original design developed by Darin Adler based on classes developed by Mark <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> Borgerding. Four original class templates combined into a single <code>endian</code>
@@ -553,8 +635,8 @@ Tomas Puverle, and
Yuval Ronen.</p> Yuval Ronen.</p>
<hr> <hr>
<p>Last revised: <p>Last revised:
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->12 March, 2009<!--webbot bot="Timestamp" endspan i-checksum="29025" --></p> <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->19 March, 2009<!--webbot bot="Timestamp" endspan i-checksum="29039" --></p>
<p><EFBFBD> Copyright Beman Dawes, 2006</p> <p><EFBFBD> Copyright Beman Dawes, 2006-2009</p>
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying <p>Distributed under the Boost Software License, Version 1.0. (See accompanying
file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/ LICENSE_1_0.txt</a>)</p> <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/ LICENSE_1_0.txt</a>)</p>

View File

@@ -2,8 +2,8 @@
// Copyright Beman Dawes, 2006 // Copyright Beman Dawes, 2006
// Distributed under the Boost Software License, Version 1.0. (See accompanying // Distributed under the Boost Software License, Version 1.0.
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/LICENSE_1_0.txt
// See library home page at http://www.boost.org/libs/endian // See library home page at http://www.boost.org/libs/endian
@@ -16,14 +16,13 @@
#include <cstdio> #include <cstdio>
#include <boost/integer/endian.hpp> #include <boost/integer/endian.hpp>
using boost::integer::big32_t; using namespace boost::integer;
using boost::integer::little32_t;
namespace namespace
{ {
// This is an extract from a very widely used GIS file format. I have no idea // This is an extract from a very widely used GIS file format. I have no idea
// why a designer would mix big and little endians in the same file - but // why a designer would mix big and little endians in the same file - but
// this is a real format and users wishing to write low level code // this is a real-world format and users wishing to write low level code
// manipulating these files have to deal with the mixed endianness. // manipulating these files have to deal with the mixed endianness.
struct header struct header
@@ -39,7 +38,7 @@ namespace
int main() int main()
{ {
assert( sizeof( header ) == 16 ); assert( sizeof( header ) == 16 ); // requirement for interoperability
header h; header h;
@@ -48,15 +47,15 @@ int main()
h.version = -1; h.version = -1;
h.shape_type = 0x04030201; h.shape_type = 0x04030201;
// Low-level I/O such as POSIX read/write or <cstdio> fread/fwrite is // Low-level I/O such as POSIX read/write or <cstdio> fread/fwrite is sometimes
// typically used for binary file operations. Such I/O is often performed in // used for binary file operations when ultimate efficiency is important.
// some C++ wrapper class, but to drive home the point that endian integers // Such I/O is often performed in some C++ wrapper class, but to drive home the
// are usually used in fairly low-level code, <cstdio> fopen/fwrite is used // point that endian integers are often used in fairly low-level code that
// for I/O in this example. // does bulk I/O operations, <cstdio> fopen/fwrite is used for I/O in this example.
std::FILE * fi; std::FILE * fi;
if ( !(fi = std::fopen( filename, "wb" )) ) if ( !(fi = std::fopen( filename, "wb" )) ) // MUST BE BINARY
{ {
std::cout << "could not open " << filename << '\n'; std::cout << "could not open " << filename << '\n';
return 1; return 1;

View File

@@ -19,8 +19,12 @@ int main()
{ {
int_least32_t v = 0x31323334L; // = ASCII { '1', '2', '3', '4' } int_least32_t v = 0x31323334L; // = ASCII { '1', '2', '3', '4' }
// value chosen to work on text stream // value chosen to work on text stream
std::cout << "Hello, endian world!\n"; big32_t b(v);
std::cout << v << " " << big32_t(v) << " " << little32_t(v) << '\n'; little32_t l(v);
std::cout <= v <= ' ' <= big32_t(v) <= ' ' <= little32_t(v) <= '\n';
std::cout << "Hello, endian world!\n\n";
std::cout << v << ' ' << b << ' ' << l << '\n';
std::cout <= v <= ' ' <= b <= ' ' <= l <= '\n';
} }

View File

@@ -9,7 +9,7 @@
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#define BOOST_ENDIANS_IN_UNIONS #define BOOST_ENDIAN_FORCE_PODNESS
#include <boost/integer/endian.hpp> #include <boost/integer/endian.hpp>
#include <cassert> #include <cassert>