From 0f36e2670d05f139e4161fc9b5797c83657cd025 Mon Sep 17 00:00:00 2001
From: bemandawes
@@ -59,7 +63,8 @@
Introduction
+ Hello endian world
Limitations
Feature set
Typedefs
@@ -46,9 +47,12 @@
Synopsis
Members
FAQ
+ Binary I/O warnings and cautions
Example
Design
Experience
+ C++0x
+ Compilation
Acknowledgements
<boost/integer/endian.hpp>
+ <boost/integer/endian_binary_stream.hpp>
- <boost/integer/endian_io.hpp>
+ <boost/binary_stream.hpp>
Introduction
@@ -70,7 +75,7 @@ byte order, value type, size, and alignment. Typedefs provide easy-to-use names
for common configurations.
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 portability is the primary motivation, these +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.
@@ -91,9 +96,43 @@ arithmetic operators are+
, +=
, -
,
>>=
. Binary relational operators are ==
, !=
,
<
, <=
, >
, >=
.
Automatic conversion is provided to the underlying integer value type.
-Header <boost/integer/endian_io.hpp>
-provides operators <<
and >>
for
-stream insertion and extraction.
+Header <boost/integer/endian_binary_stream.hpp>
+provides operators <= and =>
for unformatted binary (as opposed to
+formatted character) stream insertion and extraction of endian types.
+Header <boost/binary_stream.hpp>
+provides operators <= and =>
for unformatted binary (as opposed to
+formatted character) stream insertion and extraction of built-in and std::string
+types.
+Hello endian world
+
+ #include <boost/integer/endian.hpp>
+#include <boost/integer/endian_binary_stream.hpp>
+#include <boost/binary_stream.hpp>
+#include <iostream>
+
+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 << "Hello, endian world!\n\n";
+
+ std::cout << v << ' ' << b << ' ' << l << '\n';
+ std::cout <= v <= ' ' <= b <= ' ' <= l <= '\n';
+}
+
+On a little-endian CPU, this program outputs:
+
+ Hello, endian world!
+
+825373492 825373492 825373492
+4321 1234 4321
+
Limitations
Requires <climits>
CHAR_BIT == 8
. If CHAR_BIT
is some other value, compilation will result in an #error
. This
@@ -395,11 +434,9 @@ alignment.
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
inserters and extractors, or to serialization.
-Are endian types POD's? In C++03, no. For C++0x, yes, after applying
-
-=
-default
to the default constructor.
-What are the implications of C++03 endian types not being POD's? They
+
Are endian types POD's? Yes for C++0x. No for C++03, although several
+macros are available to force PODness in all cases.
+What are the implications endian types not being POD's of C++03? They
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
real compiler.
@@ -428,6 +465,27 @@ incrementing a variable in a record. It is very convenient to write:
int temp( record.foo);
++temp;
record.foo = temp;
+Why do binary stream insertion and extraction use operators <= and >=
+rather than <<= and >>=? <<= and >>= associate right-to-left, which is the
+opposite of << and >>, so would be very confusing and error prone. <= and >=
+associate left-to-right.
+Binary I/O warnings and cautions
+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.)
+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.
+Caution:
+When mixing formatted (i.e. operator << or >>) and unformatted (i.e.
+operator <= or >=) stream I/O, be aware that << and >> take precedence over <=
+and >=. Use parentheses to force correct order of evaluation. For example:
+
+ my_stream << foo <= bar; // no parentheses needed
+(my_stream <= foo) << bar; // parentheses required
+
+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.
Example
The endian_example.cpp program writes a
binary file containing four byte big-endian and little-endian integers:
@@ -437,15 +495,14 @@ binary file containing four byte big-endian and little-endian integers:
#include <cstdio>
#include <boost/integer/endian.hpp>
-using boost::integer::big32_t;
-using boost::integer::little32_t;
+using namespace boost::integer;
namespace
{
- // This is a portion of a widely used GIS file format. I have no idea why
- // anyone would mix big and little endians in the same format - but it is
- // a real format and users wishing to write code manipulating files in that
- // format have to deal with it.
+ // 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
+ // 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
{
@@ -460,7 +517,7 @@ namespace
int main()
{
- assert( sizeof( header ) == 16 );
+ assert( sizeof( header ) == 16 ); // requirement for interoperability
header h;
@@ -469,15 +526,15 @@ int main()
h.version = -1;
h.shape_type = 0x04030201;
- // Low-level I/O such as POSIX read/write or <cstdio> fread/fwrite is
- // typically used for binary file operations. Such I/O is often performed in
- // some C++ wrapper class, but to drive home the point that endian integers
- // are usually used in fairly low-level code, <cstdio> fopen/fwrite is used
- // for I/O in this example.
+ // 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;
- if ( !(fi = std::fopen( filename, "wb" )) )
+ if ( !(fi = std::fopen( filename, "wb" )) ) // MUST BE BINARY
{
std::cout << "could not open " << filename << '\n';
return 1;
@@ -490,6 +547,7 @@ int main()
}
std::fclose( fi );
+
std::cout << "created file " << filename << '\n';
return 0;
}
@@ -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
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.
+C++0x
+The availability of the C++0x
+
+Defaulted Functions feature is detected automatically, and will be used if
+present to ensure that objects of class endian
are trivial, and
+thus POD's.
+Compilation
+Boost.Endian is implemented entirely within headers, with no need to link to
+any Boost object libraries.
+Several macros allow user control over features:
+
+ - BOOST_ENDIAN_NO_CTORS causes
class endian
to have no
+ constructors. The intended use is for compiling user code that must be
+ portable between compilers regardless of C++0x
+
+ Defaulted Functions support. Use of constructors will always fail,
+
+ - BOOST_ENDIAN_FORCE_PODNESS causes BOOST_ENDIAN_NO_CTORS to be defined if
+ the compiler does not support C++0x
+
+ Defaulted Functions. This is ensures that , and so can be used in unions.
+ In C++0x,
class endian
objects are POD's even though they have
+ constructors.
+
Acknowledgements
Original design developed by Darin Adler based on classes developed by Mark
Borgerding. Four original class templates combined into a single endian
@@ -553,8 +635,8 @@ Tomas Puverle, and
Yuval Ronen.
Last revised:
-12 March, 2009
-© Copyright Beman Dawes, 2006
+19 March, 2009
+© Copyright Beman Dawes, 2006-2009
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at
www.boost.org/ LICENSE_1_0.txt)
diff --git a/libs/integer/example/endian_example.cpp b/libs/integer/example/endian_example.cpp
index 05a994f..fb53c71 100644
--- a/libs/integer/example/endian_example.cpp
+++ b/libs/integer/example/endian_example.cpp
@@ -2,8 +2,8 @@
// Copyright Beman Dawes, 2006
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
// See library home page at http://www.boost.org/libs/endian
@@ -16,14 +16,13 @@
#include
#include
-using boost::integer::big32_t;
-using boost::integer::little32_t;
+using namespace boost::integer;
namespace
{
// 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
- // 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.
struct header
@@ -39,7 +38,7 @@ namespace
int main()
{
- assert( sizeof( header ) == 16 );
+ assert( sizeof( header ) == 16 ); // requirement for interoperability
header h;
@@ -48,15 +47,15 @@ int main()
h.version = -1;
h.shape_type = 0x04030201;
- // Low-level I/O such as POSIX read/write or fread/fwrite is
- // typically used for binary file operations. Such I/O is often performed in
- // some C++ wrapper class, but to drive home the point that endian integers
- // are usually used in fairly low-level code, fopen/fwrite is used
- // for I/O in this example.
+ // Low-level I/O such as POSIX read/write or 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, fopen/fwrite is used for I/O in this example.
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';
return 1;
diff --git a/libs/integer/example/endian_hello_world.cpp b/libs/integer/example/endian_hello_world.cpp
index a8a1a8d..fc600a8 100644
--- a/libs/integer/example/endian_hello_world.cpp
+++ b/libs/integer/example/endian_hello_world.cpp
@@ -19,8 +19,12 @@ int main()
{
int_least32_t v = 0x31323334L; // = ASCII { '1', '2', '3', '4' }
// value chosen to work on text stream
- std::cout << "Hello, endian world!\n";
- std::cout << v << " " << big32_t(v) << " " << little32_t(v) << '\n';
- std::cout <= v <= ' ' <= big32_t(v) <= ' ' <= little32_t(v) <= '\n';
+ big32_t b(v);
+ little32_t l(v);
+
+ std::cout << "Hello, endian world!\n\n";
+
+ std::cout << v << ' ' << b << ' ' << l << '\n';
+ std::cout <= v <= ' ' <= b <= ' ' <= l <= '\n';
}
diff --git a/libs/integer/test/endian_in_union_test.cpp b/libs/integer/test/endian_in_union_test.cpp
index 6755f5e..37b246d 100644
--- a/libs/integer/test/endian_in_union_test.cpp
+++ b/libs/integer/test/endian_in_union_test.cpp
@@ -9,7 +9,7 @@
//----------------------------------------------------------------------------//
-#define BOOST_ENDIANS_IN_UNIONS
+#define BOOST_ENDIAN_FORCE_PODNESS
#include
#include