mirror of
https://github.com/boostorg/serialization.git
synced 2026-01-20 17:12:11 +00:00
2349 lines
109 KiB
HTML
Executable File
2349 lines
109 KiB
HTML
Executable File
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
<link rel="stylesheet" href="styles/boost.css" type="text/css">
|
|
<link rel="stylesheet" href="styles/style.css" type="text/css">
|
|
<title>Serialization - Portable Binary Archives Tutorial</title>
|
|
|
|
<script type="text/javascript" src="scripts/jquery-1.4.min.js"></script>
|
|
<script type="text/javascript">
|
|
function toggleDiv(divId) {
|
|
$("#"+divId).toggle();
|
|
}
|
|
window.onload=function()
|
|
{
|
|
document.getElementById('tutorial_pba_0_cpp').style.display='none';
|
|
document.getElementById('tutorial_pba_1_cpp').style.display='none';
|
|
document.getElementById('tutorial_pba_2_cpp').style.display='none';
|
|
document.getElementById('tutorial_pba_3_cpp').style.display='none';
|
|
document.getElementById('tutorial_pba_4_cpp').style.display='none';
|
|
document.getElementById('tutorial_pba_5_cpp').style.display='none';
|
|
document.getElementById('tutorial_pba_6_cpp').style.display='none';
|
|
document.getElementById('tutorial_pba_7_cpp').style.display='none';
|
|
document.getElementById('tutorial_pba_8_cpp').style.display='none';
|
|
document.getElementById('tutorial_pba_9_cpp').style.display='none';
|
|
document.getElementById('tutorial_pba_10_cpp').style.display='none';
|
|
document.getElementById('tutorial_pba_11_cpp').style.display='none';
|
|
}
|
|
</script>
|
|
</head>
|
|
|
|
<!--------------------------------------------------------------------------------->
|
|
|
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
|
<a name="top"></a>
|
|
|
|
<table cellpadding="2" width="100%">
|
|
<tr>
|
|
<td valign="top" width="300">
|
|
<h3><a href="../../../index.htm">
|
|
<img height="86" width="277" alt="Boost" src="./images/boost.png" border="0"></a></h3>
|
|
</td>
|
|
|
|
<td valign="top">
|
|
<h1 align="center">Boost/Serialization ‐ Portable Binary Archives (PBA)</h1>
|
|
<h2 align="center">Tutorial</h2>
|
|
<p>NOTE: Naming differs from the source code! This tutorial reflects our hope to get
|
|
the eos portable archives an official part of the boost serialization library.
|
|
Work is in progress :-)
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<!--------------------------------------------------------------------------------->
|
|
<hr>
|
|
<dl class="index">
|
|
<dt><a href="#Quick_start">Quick start</a><br>
|
|
<ul>
|
|
<li><a href="#Quick_start:store_1">How to store some simple data in a <i>portable binary output archive</i></a></li>
|
|
<li><a href="#Quick_start:load_1">How to load some simple data from a <i>portable binary input archive</i></a></li>
|
|
</ul>
|
|
</dt>
|
|
|
|
<dt><a href="#Format">Format</a>
|
|
</dt>
|
|
|
|
<dt><a href="#Samples">Examples</a><br>
|
|
<ul>
|
|
<li><a href="#Samples:1">Handling special floating point values</a></li>
|
|
<li><a href="#Samples:2">Forbidding the serialization of non finite float values</a></li>
|
|
<li><a href="#Samples:3">Serializing integer numbers</a></li>
|
|
<li><a href="#Samples:4">Using PBA serialization with a memory buffer</a></li>
|
|
<li><a href="#Samples:5">An alternative to PBA using text or XML archives made portable</a></li>
|
|
<li><a href="#Samples:6">Using PBA serialization associated with on-the-fly (de)compressed file streams</a></li>
|
|
<li><a href="#Samples:7">A simple PBA versus text archive benchmark test</a></li>
|
|
</ul>
|
|
</dt>
|
|
</dl>
|
|
|
|
<p>
|
|
</p>
|
|
<hr>
|
|
<!--------------------------------------------------------------------------------->
|
|
<h2><a name="Quick_start"></a>Quick start</h2>
|
|
|
|
Are you impatient to enjoy the Boost Portable Binary Archives (PBA) ?
|
|
If so, this section is for you.
|
|
|
|
<h3><a name="Quick_start:store_1"></a>How to store some simple data in a <i>portable binary output archive</i></h2>
|
|
|
|
<p>
|
|
The <tt class="fs">tutorial_pba_0.cpp</tt> sample
|
|
program uses a <tt class="code">boost::archive::portable_binary_oarchive</tt> object
|
|
attached to a standard output file stream to store a couple of
|
|
variables of primitive types (<tt class="code">bool</tt>,
|
|
<tt class="code">char</tt>, integer
|
|
numbers, floating numbers) and even a <tt class="code">std::string</tt>.
|
|
</p>
|
|
|
|
<div style="background-color: #ccc; padding: 4px 2px; border: 1px" >
|
|
<img src="images/c++-source-code.png" height="20pt" style="float:left" /> The <tt class="fs">tutorial_pba_0.cpp</tt> source code <a href="./code/tutorial_pba_0.cpp" class="button" >Download</a>
|
|
<a href="javascript:toggleDiv('tutorial_pba_0_cpp');" class="button" >Show/hide</a>
|
|
<div id="tutorial_pba_0_cpp" ><PRE>
|
|
<I><FONT COLOR="#B22222">/** tutorial_pba_0.cpp
|
|
*
|
|
* (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
|
|
*
|
|
* Use, modification and distribution is subject to 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)
|
|
*
|
|
*/</FONT></I>
|
|
|
|
<I><FONT COLOR="#B22222">/**
|
|
* The intent of this program is to serve as a tutorial for
|
|
* users of the portable binary archive in the framework of
|
|
* the Boost/Serialization library.
|
|
*
|
|
* This quick start example shows how to store some variables
|
|
* of basic types (bool, integer, floating point numbers, STL string)
|
|
* using the portable binary archive format associated to a
|
|
* standard output file stream.
|
|
*
|
|
*/</FONT></I>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><string></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><fstream></FONT></B>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/cstdint.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/portable_binary_oarchive.hpp></FONT></B>
|
|
|
|
<B><FONT COLOR="#228B22">int</FONT></B> <B><FONT COLOR="#0000FF">main</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
<I><FONT COLOR="#B22222">// The name for the example data file :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">std</FONT></B>::string filename = <B><FONT COLOR="#BC8F8F">"pba_0.data"</FONT></B>;
|
|
|
|
<I><FONT COLOR="#B22222">// Some variables of various primitive types :
|
|
</FONT></I> <B><FONT COLOR="#228B22">bool</FONT></B> b = true;
|
|
<B><FONT COLOR="#228B22">char</FONT></B> c = <B><FONT COLOR="#BC8F8F">'B'</FONT></B>;
|
|
uint32_t answer = 42;
|
|
<B><FONT COLOR="#228B22">float</FONT></B> computing_time = 7.5e6;
|
|
<B><FONT COLOR="#228B22">double</FONT></B> e = 2.71828182845905;
|
|
<B><FONT COLOR="#5F9EA0">std</FONT></B>::string slogan = <B><FONT COLOR="#BC8F8F">"DON'T PANIC"</FONT></B>;
|
|
|
|
<I><FONT COLOR="#B22222">// Open an output file stream in binary mode :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">std</FONT></B>::ofstream fout (filename.c_str (), std::ios_base::binary);
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Create an output portable binary archive attached to the output file :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::portable_binary_oarchive opba (fout);
|
|
|
|
<I><FONT COLOR="#B22222">// Store (serializing) variables :
|
|
</FONT></I> opba & b & c & answer & computing_time & e & slogan;
|
|
}
|
|
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> 0;
|
|
}
|
|
|
|
<I><FONT COLOR="#B22222">// end of tutorial_pba_0.cpp
|
|
</FONT></I>
|
|
</PRE>
|
|
</div><br></div>
|
|
|
|
|
|
<p>
|
|
The compiled executable creates the <tt class="fs">pba_0.data</tt> file which
|
|
contains the following bytes:
|
|
<pre class="byte">127 1 9 1 84 1 66 1 42 4 192 225 228 74 8 116
|
|
87 20 139 10 191 5 64 1 11 68 79 78 39 84 32 80
|
|
65 78 73 67
|
|
</pre>
|
|
This format is explained in details below.
|
|
|
|
|
|
<p>Note:
|
|
<ul>
|
|
<li> the output of the byte content in the <tt class="fs">pba_0.data</tt> file
|
|
can be obtained invoking some command like
|
|
<tt style="font-size: 12px; font-weight: bold; color: #ffffff; background-color: black;" > od -t u1 pba_0.data </tt>
|
|
on a GNU/Linux system.<br>
|
|
<li> one should notice that this program makes use of
|
|
the <i>typedef-ed</i> integer types from
|
|
the <tt class="fs">boost/cstdint.hpp</tt> header (<tt class="code">uint32_t</tt>...). It is a
|
|
strong recommendation to ensure cross-environment portability while
|
|
(de)serializing integer numbers (see also
|
|
the <a href="#Samples">Examples section</a>).
|
|
</ul>
|
|
</p>
|
|
|
|
<!--div style="background-color: #ccc; padding: 4px 2px; border: 1px" -->
|
|
<!--img src="images/c++-source-code.png" height="20pt" style="float:left" /-->
|
|
<div>
|
|
<a href="#top" class="button" >To top</a>
|
|
<!--div id="_cpp" ></div--><br>
|
|
</div>
|
|
|
|
|
|
<h3><a name="Quick_start:load_1"></a>How to load some simple data from a <i>portable binary input archive</i></h2>
|
|
|
|
<p>
|
|
The <tt class="fs">tutorial_pba_1.cpp</tt> sample program uses
|
|
a <tt class="code">boost::archive::portable_binary_iarchive</tt> object
|
|
attached to a standard input file stream in order to load the
|
|
data previously stored by
|
|
the <tt class="fs">tutorial_pba_0.cpp</tt> program in
|
|
the <tt class="fs">pba_0.data</tt> file.
|
|
</p>
|
|
|
|
|
|
<div style="background-color: #ccc; padding: 4px 2px; border: 1px" >
|
|
<img src="images/c++-source-code.png" height="20pt" style="float:left" /> The <tt class="fs">tutorial_pba_1.cpp</tt> source code <a href="./code/tutorial_pba_1.cpp" class="button" >Download</a>
|
|
<a href="javascript:toggleDiv('tutorial_pba_1_cpp');" class="button" >Show/hide</a>
|
|
<div id="tutorial_pba_1_cpp" ><PRE>
|
|
<I><FONT COLOR="#B22222">/** tutorial_pba_1.cpp
|
|
*
|
|
* (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
|
|
*
|
|
* Use, modification and distribution is subject to 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)
|
|
*
|
|
*/</FONT></I>
|
|
|
|
<I><FONT COLOR="#B22222">/**
|
|
* The intent of this program is to serve as a tutorial for
|
|
* users of the portable binary archive in the framework of
|
|
* the Boost/Serialization package.
|
|
*
|
|
* This quick start example shows how to load some variables
|
|
* of basic types (bool, integer, floating point numbers, STL string)
|
|
* using the portable binary archive format associated to a
|
|
* standard input file stream.
|
|
*
|
|
*/</FONT></I>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><iostream></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><string></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><fstream></FONT></B>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/cstdint.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/portable_binary_iarchive.hpp></FONT></B>
|
|
|
|
<B><FONT COLOR="#228B22">int</FONT></B> <B><FONT COLOR="#0000FF">main</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
using namespace std;
|
|
|
|
<I><FONT COLOR="#B22222">// The name for the example data file :
|
|
</FONT></I> string filename = <B><FONT COLOR="#BC8F8F">"pba_0.data"</FONT></B>;
|
|
|
|
<I><FONT COLOR="#B22222">// Some variables of various types :
|
|
</FONT></I> <B><FONT COLOR="#228B22">bool</FONT></B> b;
|
|
<B><FONT COLOR="#228B22">char</FONT></B> c;
|
|
uint32_t answer;
|
|
<B><FONT COLOR="#228B22">float</FONT></B> computing_time;
|
|
<B><FONT COLOR="#228B22">double</FONT></B> e;
|
|
string slogan;
|
|
|
|
<I><FONT COLOR="#B22222">// Open an input file stream in binary mode :
|
|
</FONT></I> ifstream fin (filename.c_str (), ios_base::binary);
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Create an input portable binary archive attached to the input file :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::portable_binary_iarchive ipba (fin);
|
|
|
|
<I><FONT COLOR="#B22222">// Loading (de-serializing) variables using the same
|
|
</FONT></I> <I><FONT COLOR="#B22222">// order than for serialization (see tutorial_pba_0.cpp) :
|
|
</FONT></I> ipba & b & c & answer & computing_time & e & slogan;
|
|
}
|
|
|
|
cout.precision (15);
|
|
cout << <B><FONT COLOR="#BC8F8F">"Variable 'b' is : "</FONT></B> << b << <B><FONT COLOR="#BC8F8F">" "</FONT></B> << <B><FONT COLOR="#BC8F8F">"(bool)"</FONT></B> << endl;
|
|
cout << <B><FONT COLOR="#BC8F8F">"Variable 'c' is : '"</FONT></B> << c << <B><FONT COLOR="#BC8F8F">"' "</FONT></B> << <B><FONT COLOR="#BC8F8F">" "</FONT></B> << <B><FONT COLOR="#BC8F8F">"(char)"</FONT></B> << endl;
|
|
cout << <B><FONT COLOR="#BC8F8F">"Variable 'answer' is : "</FONT></B> << answer << <B><FONT COLOR="#BC8F8F">" "</FONT></B> << <B><FONT COLOR="#BC8F8F">"(unsigned 32-bit integer)"</FONT></B> << endl;
|
|
cout << <B><FONT COLOR="#BC8F8F">"Variable 'computing_time' is : "</FONT></B> << computing_time << <B><FONT COLOR="#BC8F8F">" "</FONT></B> << <B><FONT COLOR="#BC8F8F">"(single precision 32-bit float)"</FONT></B> << endl;
|
|
cout << <B><FONT COLOR="#BC8F8F">"Variable 'e' is : "</FONT></B> << e << <B><FONT COLOR="#BC8F8F">" "</FONT></B> << <B><FONT COLOR="#BC8F8F">"(double precision 64-bit float)"</FONT></B> << endl;
|
|
cout << <B><FONT COLOR="#BC8F8F">"Variable 'slogan' is : \""</FONT></B> << slogan << <B><FONT COLOR="#BC8F8F">"\" "</FONT></B> << <B><FONT COLOR="#BC8F8F">"(std::string)"</FONT></B> << endl;
|
|
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> 0;
|
|
}
|
|
|
|
<I><FONT COLOR="#B22222">// end of tutorial_pba_1.cpp
|
|
</FONT></I>
|
|
</PRE>
|
|
</div><br></div>
|
|
|
|
|
|
<p>
|
|
The executable reads the <tt class="fs">pba_0.data</tt> file and deserializes its
|
|
contents in the same order it has been stored. It then prints the
|
|
restored values of the variables:
|
|
<pre>Variable 'b' is : 1 (bool)
|
|
Variable 'c' is : 'B' (char)
|
|
Variable 'answer' is : 42 (unsigned 32-bit integer)
|
|
Variable 'computing_time' is : 7500000 (single precision 32-bit float)
|
|
Variable 'e' is : 2.71828182845905 (double precision 64-bit float)
|
|
Variable 'slogan' is : "DON'T PANIC" (std::string)
|
|
</pre>
|
|
</p>
|
|
|
|
<!--div style="background-color: #ccc; padding: 4px 2px; border: 1px" -->
|
|
<!--img src="images/c++-source-code.png" height="20pt" style="float:left" /-->
|
|
<div>
|
|
<a href="#top" class="button" >To top</a>
|
|
<!--div id="_cpp" ></div--><br>
|
|
</div>
|
|
|
|
|
|
<!--------------------------------------------------------------------------------->
|
|
<hr>
|
|
<h2><a name="Format"></a>Format</h2>
|
|
|
|
<p>
|
|
This section aims to give some details about the binary format of
|
|
portable binary archives (PBA). We will analyse the byte contents of
|
|
the sample binary archive <tt class="fs">pba_0.data</tt> file
|
|
created by the <tt class="fs">tutorial_pba_0.cpp</tt>
|
|
program (see <a href="#Quick_start:store_1">the previous section</a>).
|
|
</p>
|
|
|
|
<p>
|
|
Like any other archive format within Boost/Serialization, a PBA starts
|
|
with a header (this is the default behaviour but it is possible to
|
|
deactivate the use of this header using a special flag at
|
|
construction, see <a href="#Samples:1">this example</a>). This
|
|
header is made of two informations :
|
|
<ul>
|
|
<li>
|
|
a <em>magic byte</em> with the conventionnal decimal value :
|
|
<pre class="byte">127</pre>
|
|
<li>
|
|
the Boost library version number which is encoded as an integer
|
|
number.
|
|
<p>The PBA encoding of integer numbers uses the following
|
|
scheme:
|
|
<tt><size> <content></tt>,
|
|
where first the <i>size</i> stores the minimal
|
|
number of non zero bytes needed to store the binary
|
|
representation of the integer value; then the bytes corresponding to the <i>content</i> are stored
|
|
starting from the less significant ones (see
|
|
also <a href="#Samples:3">this example</a>). For the library
|
|
version number we have here:
|
|
<pre class="byte">1 9</pre>
|
|
where <tt class="byte">1</tt> is the number of byte needed to store the
|
|
value <tt class="byte">9</tt> which comes with the Serialization library for
|
|
Boost version <tt>1.47.0</tt>. Here, the <tt>9</tt> value being less than <tt>256</tt>,
|
|
one unique byte is enough to store this number.
|
|
</ul>
|
|
</p>
|
|
</p>
|
|
|
|
<p>
|
|
Now we are done with the header, let's have a look on the serialized data !
|
|
</p>
|
|
|
|
<ul>
|
|
<li>
|
|
The first variable is of boolean type with value <tt>true</tt>. Here
|
|
the PBA conventionnaly encodes the <tt>true</tt> value with the
|
|
character <tt class="code_string">'T'</tt> which is stored using the corresponding ASCII
|
|
integer value (<tt class="byte">84</tt>). As <tt>84</tt> is less
|
|
than <tt>256</tt>, this uses only <tt class="byte">1</tt> byte:
|
|
<pre class="byte">1 84</pre>
|
|
</p>
|
|
|
|
<li>The next variable uses <tt class="byte">1</tt> byte to store a 8-bit
|
|
character (<tt>char</tt>) taking value <tt class="code_string">'B'</tt>. Again the PBA
|
|
scheme encodes it using its ASCII integer value
|
|
(<tt class="byte">66</tt>). This gives:
|
|
<pre class="byte">1 66</pre>
|
|
</p>
|
|
|
|
<li>Then we have an unsigned 32-bit integer with
|
|
value <tt class="byte">42</tt> (a fondamental constant from
|
|
the <i>H2G2</i>). As the natural binary 32-bit encoding of this value
|
|
(<256) only needs
|
|
<tt class="byte">1</tt> non-zero byte, the PBA stores :
|
|
<pre class="byte">1 42</pre>
|
|
This scheme results in saving 2 bytes compared to the size of the transient value.
|
|
</p>
|
|
|
|
<li>The next variable is a single precision number with
|
|
value <tt>7.5×10<sup>6</sup></tt>. Following the IEEE 754 standard one thus uses
|
|
32 bits to encode the <font color="red">sign bit</font>,
|
|
the <font color="blue">8-bit exponent</font> and
|
|
the <font color="green">23-bit significant</font> (mantissa).
|
|
As <tt>7.5×10<sup>6</sup></tt> can be rewritten
|
|
in <tt><font color="red">+</font><font color="magenta">1</font>.<font color="green">78813934</font>×2<sup><font color="blue">22</font></sup></tt>, we have the
|
|
following bits contents:<br>
|
|
<br>
|
|
<tt><font color="red">0</font><font color="blue">10010101</font><font color="magenta">1</font><font color="green">11001001110000111000000</font></tt><br><br>
|
|
where the <i>phantom bit</i> (not stored) is conventionaly set
|
|
at <font color="magenta">1</font> and the exponent is stored after
|
|
being shifted conventionaly by <tt>2<sup>7</sup>-1=127</tt>, thus
|
|
<tt>(<font color="blue">10010101</font>)<sub>2</sub>=(149)<sub>10</sub></tt>
|
|
(subscripts indicate the number base) and <tt>149-127=<font color="blue">22</font></tt>.<br>
|
|
|
|
<br>
|
|
Packing these bits using <tt class="byte">4</tt>
|
|
bytes, we get:<br><br>
|
|
<table border="1">
|
|
<tr align="center">
|
|
<td><tt><font color="red">0</font><font color="blue">1001010</font></tt></td>
|
|
<td><tt><font color="blue">1</font><font color="green">1100100</font></tt></td>
|
|
<td><tt><font color="green">11100001</font></tt></td>
|
|
<td><tt><font color="green">11000000</font></tt></td>
|
|
</tr>
|
|
<tr align="center">
|
|
<td><tt class="byte">74</tt></td>
|
|
<td><tt class="byte">228</tt></td>
|
|
<td><tt class="byte">225</tt></td>
|
|
<td><tt class="byte">192</tt></td>
|
|
</tr>
|
|
</table>
|
|
<br>
|
|
|
|
Thus the PBA streams the following 5 bytes (first the <i>size</i> then the <i>content</i>
|
|
from the least significant byte to the most significant byte), giving :
|
|
<pre class="byte">4 192 225 228 74</pre>
|
|
|
|
<li>The next floating number 2.71828182845905 =
|
|
<tt><font color="red">+</font><font color="magenta">1</font>.<font color="green">35914091422952</font>×2<sup>(<font color="blue">1024</font>-1023)</sup></tt>,
|
|
is stored using the double precision IEEE 754 64-bit pattern (using the conventionnal exponent shift <tt>2<sup>10</sup>-1=1023</tt>):
|
|
<br><br>
|
|
<table border="1">
|
|
<tr align="center">
|
|
<td><tt><font color="red">0</font><font color="blue">1000000</font></tt></td>
|
|
<td><tt><font color="blue">0000</font><font color="green">0101</font></tt></td>
|
|
<td><tt><font color="green">11011111</font></tt></td>
|
|
<td><tt><font color="green">00001010</font></tt></td>
|
|
<td><tt><font color="green">10001011</font></tt></td>
|
|
<td><tt><font color="green">00010100</font></tt></td>
|
|
<td><tt><font color="green">01010111</font></tt></td>
|
|
<td><tt><font color="green">01110100</font></tt></td>
|
|
</tr>
|
|
<tr align="center">
|
|
<td><tt class="byte">64</tt></td>
|
|
<td><tt class="byte">5</tt></td>
|
|
<td><tt class="byte">191</tt></td>
|
|
<td><tt class="byte">10</tt></td>
|
|
<td><tt class="byte">139</tt></td>
|
|
<td><tt class="byte">20</tt></td>
|
|
<td><tt class="byte">87</tt></td>
|
|
<td><tt class="byte">116</tt></td>
|
|
</tr>
|
|
</table>
|
|
<br>
|
|
|
|
Thus the PBA uses the following 9 bytes, the first one for the <i>size</i> (<tt class="byte">8</tt>) and the other ones
|
|
for the <i>content</i> (starting with the LSB):
|
|
<pre class="byte">8 116 87 20 139 10 191 5 64</pre>
|
|
|
|
<li>Finally the string <tt class="code_string">"DON'T PANIC"</tt> is stored:
|
|
<ul>
|
|
<li>
|
|
first is given the number of characters using the PBA
|
|
integer encoding scheme; here
|
|
<tt class="byte">1</tt> byte is enough to store the
|
|
value <tt class="byte">11</tt>: <br>
|
|
<pre class="byte">1 11</pre>
|
|
<li> then the array of 11 characters is given using the
|
|
corresponding ASCII codes:
|
|
<br><br>
|
|
<table border="1">
|
|
<tr align="center">
|
|
<td><tt class="code_string">D</td>
|
|
<td><tt class="code_string">O</td>
|
|
<td><tt class="code_string">N</td>
|
|
<td><tt class="code_string">'</td>
|
|
<td><tt class="code_string">T</td>
|
|
<td><tt class="code_string"> </td>
|
|
<td><tt class="code_string">P</td>
|
|
<td><tt class="code_string">A</td>
|
|
<td><tt class="code_string">N</td>
|
|
<td><tt class="code_string">I</td>
|
|
<td><tt class="code_string">C</td>
|
|
</tr>
|
|
<tr align="center">
|
|
<td><tt class="byte">68</td>
|
|
<td><tt class="byte">79</td>
|
|
<td><tt class="byte">78</td>
|
|
<td><tt class="byte">39</td>
|
|
<td><tt class="byte">84</td>
|
|
<td><tt class="byte">32</td>
|
|
<td><tt class="byte">80</td>
|
|
<td><tt class="byte">65</td>
|
|
<td><tt class="byte">78</td>
|
|
<td><tt class="byte">73</td>
|
|
<td><tt class="byte">67</td>
|
|
</tr>
|
|
</table>
|
|
<br>
|
|
<pre class="byte">68 79 78 39 84 32 80 65 78 73 67 </pre>
|
|
</ul>
|
|
|
|
</ul>
|
|
|
|
</p>
|
|
|
|
<p>
|
|
Now the contents of the <tt class="fs">pba_0.data</tt> file can be fully
|
|
understood :
|
|
<pre class="byte">127 1 9 1 84 1 66 1 42 4 192 225 228 74 8 116
|
|
87 20 139 10 191 5 64 1 11 68 79 78 39 84 32 80
|
|
65 78 73 67
|
|
</pre>
|
|
|
|
More details about the format (non finite floating point values,
|
|
negative integer numbers) will be given in
|
|
the <a href="#Samples">sample codes</a> below.
|
|
</p>
|
|
|
|
<!--div style="background-color: #ccc; padding: 4px 2px; border: 1px" -->
|
|
<!--img src="images/c++-source-code.png" height="20pt" style="float:left" /-->
|
|
<div>
|
|
<a href="#top" class="button" >To top</a>
|
|
<!--div id="_cpp" ></div--><br>
|
|
</div>
|
|
|
|
|
|
<!--------------------------------------------------------------------------------->
|
|
<hr>
|
|
<h2><a name="Samples"></a>Examples</h2>
|
|
|
|
|
|
<!------------------------------------------------------------->
|
|
<h3><a name="Samples:1"></a>Handling special floating point values</h3>
|
|
|
|
<p>
|
|
The PBA has been designed in the aims to handle single and double
|
|
precision floating point numbers, including non-finite and special values:
|
|
<ul>
|
|
<li>±infinity
|
|
<li>NaN (<i>not a number</i>)
|
|
<li>denormalized numbers (i.e. floating point numbers with non-guaranteed roundoff precision)
|
|
</ul>
|
|
</p>
|
|
|
|
<p>
|
|
The <tt class="fs">tutorial_pba_2.cpp</tt> sample program
|
|
illustrates the use of such special cases while serializing single precision
|
|
floating point numbers:
|
|
</p>
|
|
|
|
<div style="background-color: #ccc; padding: 4px 2px; border: 1px" >
|
|
<img src="images/c++-source-code.png" height="20pt" style="float:left" /> The <tt class="fs">tutorial_pba_2.cpp</tt> source code <a href="./code/tutorial_pba_2.cpp" class="button" >Download</a>
|
|
<a href="javascript:toggleDiv('tutorial_pba_2_cpp');" class="button" >Show/hide</a>
|
|
<div id="tutorial_pba_2_cpp" ><PRE>
|
|
<I><FONT COLOR="#B22222">/** tutorial_pba_2.cpp
|
|
*
|
|
* (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
|
|
*
|
|
* Use, modification and distribution is subject to 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)
|
|
*
|
|
*/</FONT></I>
|
|
|
|
<I><FONT COLOR="#B22222">/**
|
|
* The intent of this program is to serve as a tutorial for
|
|
* users of the portable binary archive in the framework of
|
|
* the Boost/Serialization library.
|
|
*
|
|
* This sample program shows how to use a portable binary archive
|
|
* to store/load floating point numbers including non-finite and
|
|
* special (denormalized) values.
|
|
*
|
|
*/</FONT></I>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><string></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><fstream></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><limits></FONT></B>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/portable_binary_oarchive.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/portable_binary_iarchive.hpp></FONT></B>
|
|
|
|
<B><FONT COLOR="#228B22">int</FONT></B> <B><FONT COLOR="#0000FF">main</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
using namespace std;
|
|
|
|
<I><FONT COLOR="#B22222">// The name for the example data file :
|
|
</FONT></I> string filename = <B><FONT COLOR="#BC8F8F">"pba_2.data"</FONT></B>;
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// A normal single precision floating point number :
|
|
</FONT></I> <B><FONT COLOR="#228B22">float</FONT></B> pi = 3.14159265;
|
|
|
|
<I><FONT COLOR="#B22222">// Single precision zeroed floating point number :
|
|
</FONT></I> <B><FONT COLOR="#228B22">float</FONT></B> zero = 0.0;
|
|
|
|
<I><FONT COLOR="#B22222">// A denormalized single precision floating point number :
|
|
</FONT></I> <B><FONT COLOR="#228B22">float</FONT></B> tiny = 1.e-40;
|
|
|
|
<I><FONT COLOR="#B22222">// A single precision floating point number with `+Infinity' value :
|
|
</FONT></I> <B><FONT COLOR="#228B22">float</FONT></B> plus_infinity = numeric_limits<<B><FONT COLOR="#228B22">float</FONT></B>>::infinity ();
|
|
|
|
<I><FONT COLOR="#B22222">// A single precision floating point number with `-Infinity' value :
|
|
</FONT></I> <B><FONT COLOR="#228B22">float</FONT></B> minus_infinity = -numeric_limits<<B><FONT COLOR="#228B22">float</FONT></B>>::infinity ();
|
|
|
|
<I><FONT COLOR="#B22222">// A single precision `Not-a-Number' (NaN):
|
|
</FONT></I> <B><FONT COLOR="#228B22">float</FONT></B> nan = numeric_limits<<B><FONT COLOR="#228B22">float</FONT></B>>::quiet_NaN ();
|
|
|
|
<I><FONT COLOR="#B22222">// Open an output file stream in binary mode :
|
|
</FONT></I> ofstream fout (filename.c_str (), ios_base::binary);
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Create an output portable binary archive attached to the output file :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::portable_binary_oarchive opba (fout);
|
|
|
|
<I><FONT COLOR="#B22222">// Store (serialize) variables :
|
|
</FONT></I> opba & pi & zero & tiny & plus_infinity & minus_infinity & nan;
|
|
}
|
|
}
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Single precision floating point numbers to be loaded :
|
|
</FONT></I> <B><FONT COLOR="#228B22">float</FONT></B> x[6];
|
|
|
|
<I><FONT COLOR="#B22222">// Open an input file stream in binary mode :
|
|
</FONT></I> ifstream fin (filename.c_str (), ios_base::binary);
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Create an input portable binary archive attached to the input file :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::portable_binary_iarchive ipba (fin);
|
|
|
|
<I><FONT COLOR="#B22222">// Load (de-serialize) variables using the same
|
|
</FONT></I> <I><FONT COLOR="#B22222">// order than for serialization :
|
|
</FONT></I> <B><FONT COLOR="#A020F0">for</FONT></B> (<B><FONT COLOR="#228B22">int</FONT></B> i = 0; i < 6; ++i)
|
|
{
|
|
ipba & x[i];
|
|
}
|
|
}
|
|
|
|
<I><FONT COLOR="#B22222">// Print :
|
|
</FONT></I> <B><FONT COLOR="#A020F0">for</FONT></B> (<B><FONT COLOR="#228B22">int</FONT></B> i = 0; i < 6; ++i)
|
|
{
|
|
cout.precision (8);
|
|
cout << <B><FONT COLOR="#BC8F8F">"Loaded x["</FONT></B> << i << <B><FONT COLOR="#BC8F8F">"] = "</FONT></B> << x[i];
|
|
<B><FONT COLOR="#A020F0">switch</FONT></B> (fp::fpclassify(x[i]))
|
|
{
|
|
<B><FONT COLOR="#A020F0">case</FONT></B> <B><FONT COLOR="#5F9EA0">FP_NAN</FONT></B>: cout << <B><FONT COLOR="#BC8F8F">" (NaN)"</FONT></B>; <B><FONT COLOR="#A020F0">break</FONT></B>;
|
|
<B><FONT COLOR="#A020F0">case</FONT></B> <B><FONT COLOR="#5F9EA0">FP_INFINITE</FONT></B>: cout << <B><FONT COLOR="#BC8F8F">" (infinite)"</FONT></B>; <B><FONT COLOR="#A020F0">break</FONT></B>;
|
|
<B><FONT COLOR="#A020F0">case</FONT></B> <B><FONT COLOR="#5F9EA0">FP_SUBNORMAL</FONT></B>: cout << <B><FONT COLOR="#BC8F8F">" (denormalized)"</FONT></B>; <B><FONT COLOR="#A020F0">break</FONT></B>;
|
|
<B><FONT COLOR="#A020F0">case</FONT></B> <B><FONT COLOR="#5F9EA0">FP_NORMAL</FONT></B>: cout << <B><FONT COLOR="#BC8F8F">" (normalized)"</FONT></B>; <B><FONT COLOR="#A020F0">break</FONT></B>;
|
|
}
|
|
cout << endl;
|
|
}
|
|
}
|
|
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> 0;
|
|
}
|
|
|
|
<I><FONT COLOR="#B22222">// end of tutorial_pba_2.cpp
|
|
</FONT></I>
|
|
</PRE>
|
|
</div><br></div>
|
|
|
|
|
|
<p>
|
|
The <tt class="fs">pba_2.data</tt> output data file thus contains the following bytes:
|
|
<pre class="byte">127 1 9 4 219 15 73 64 0 3 194 22 1 4 0 0
|
|
128 127 4 0 0 128 255 4 255 255 255 127
|
|
</pre>
|
|
where:
|
|
<ul>
|
|
|
|
<li><tt class="byte">127 1 9</tt> is the standard archive header
|
|
|
|
<li>5 bytes are used to encode the value of π : one byte for the <i>size</i>=<tt class="byte">4</tt> and 4 bytes for the <i>content</i>
|
|
(reversed order):
|
|
<br><br>
|
|
<table border="1">
|
|
<tr align="center">
|
|
<td><tt class="byte">64</tt></td>
|
|
<td><tt class="byte">73</tt></td>
|
|
<td><tt class="byte">15</tt></td>
|
|
<td><tt class="byte">219</tt></td>
|
|
</tr>
|
|
<tr align="center">
|
|
<td><tt><font color="red">0</font><font color="blue">1000000</font></tt></td>
|
|
<td><tt><font color="blue">0</font><font color="green">1001001</font></tt></td>
|
|
<td><tt><font color="green">00001111</font></tt></td>
|
|
<td><tt><font color="green">11011011</font></tt></td>
|
|
</tr>
|
|
</table>
|
|
<br>
|
|
and π = <tt><font color="red">+</font><font color="magenta">1</font>.<font color="green">5707963</font>×2<sup>(<font color="blue">128</font>-127)</sup></tt> = <tt>3.14159265</tt>.
|
|
|
|
<li>the value <i>zero</i> is stored using only
|
|
one <tt class="byte">0</tt> byte (this is called <i>zero optimization</i> and this save bytes for storage).
|
|
|
|
<li>a denormalized value then comes with only <tt class="byte">3</tt> bytes (note that the MSB byte is zero so it is omitted)
|
|
<br><br>
|
|
<table border="1">
|
|
<tr align="center" background="#EEEEEE">
|
|
<td><tt></tt></td>
|
|
<td><tt class="byte">1</tt></td>
|
|
<td><tt class="byte">22</tt></td>
|
|
<td><tt class="byte">194</tt></td>
|
|
</tr>
|
|
<tr align="center">
|
|
<td><tt><font color="red">0</font><font color="blue">0000000</font></tt></td>
|
|
<td><tt><font color="blue">0</font><font color="green">0000001</font></tt></td>
|
|
<td><tt><font color="green">00010110</font></tt></td>
|
|
<td><tt><font color="green">11000010</font></tt></td>
|
|
</tr>
|
|
</table>
|
|
<br>
|
|
Here the value
|
|
is <tt><font color="red">+</font><font color="magenta">0</font>.<font color="green">017014027</font>×2<sup>(<font color="blue">0</font>-127)</sup></tt>
|
|
= <tt>0.9999946×10<sup>-40</sup></tt> which, as expected for
|
|
denormalized numbers, misses the requested
|
|
value <tt>10<sup>-40</sup></tt> by the relative error of
|
|
magnitude <tt>5.4×10<sup>-6</sup></tt>, which is larger than the machine
|
|
roundoff precision (~<tt>10<sup>-7</sup></tt> for the single precision scheme).
|
|
|
|
<li>the +∞ value is stored using one byte for the <i>size</i>
|
|
plus <tt class="byte">4</tt> content bytes, fulfilling the IEEE 754 standard,
|
|
i.e. maximal exponent and zero mantissa :
|
|
<br><br>
|
|
<table border="1">
|
|
<tr align="center" background="#EEEEEE">
|
|
<td><tt class="byte">127</tt></td>
|
|
<td><tt class="byte">128</tt></td>
|
|
<td><tt class="byte">0</tt></td>
|
|
<td><tt class="byte">0</tt></td>
|
|
</tr>
|
|
<tr align="center">
|
|
<td><tt><font color="red">0</font><font color="blue">1111111</font></tt></td>
|
|
<td><tt><font color="blue">1</font><font color="green">0000000</font></tt></td>
|
|
<td><tt><font color="green">00000000</font></tt></td>
|
|
<td><tt><font color="green">00000000</font></tt></td>
|
|
</tr>
|
|
</table>
|
|
<br>
|
|
|
|
<li>the -∞ value is stored using the same scheme as above, but the <font color="red">sign bit</font> :
|
|
<br><br>
|
|
<table border="1">
|
|
<tr align="center" background="#EEEEEE">
|
|
<td><tt class="byte">255</tt></td>
|
|
<td><tt class="byte">128</tt></td>
|
|
<td><tt class="byte">0</tt></td>
|
|
<td><tt class="byte">0</tt></td>
|
|
</tr>
|
|
<tr align="center">
|
|
<td><tt><font color="red">1</font><font color="blue">1111111</font></tt></td>
|
|
<td><tt><font color="blue">1</font><font color="green">0000000</font></tt></td>
|
|
<td><tt><font color="green">00000000</font></tt></td>
|
|
<td><tt><font color="green">00000000</font></tt></td>
|
|
</tr>
|
|
</table>
|
|
<br>
|
|
|
|
<li>the final NaN value is stored also using one <i>size</i> byte plus <tt class="byte">4</tt> <i>content</i> bytes with maximal exponent and non-zero mantissa :
|
|
<br><br>
|
|
<table border="1">
|
|
<tr align="center" background="#EEEEEE">
|
|
<td><tt class="byte">127</tt></td>
|
|
<td><tt class="byte">255</tt></td>
|
|
<td><tt class="byte">255</tt></td>
|
|
<td><tt class="byte">255</tt></td>
|
|
</tr>
|
|
<tr align="center">
|
|
<td><tt><font color="red">0</font><font color="blue">1111111</font></tt></td>
|
|
<td><tt><font color="blue">1</font><font color="green">1111111</font></tt></td>
|
|
<td><tt><font color="green">11111111</font></tt></td>
|
|
<td><tt><font color="green">11111111</font></tt></td>
|
|
</tr>
|
|
</table>
|
|
<br>
|
|
See <a href="http://en.wikipedia.org/wiki/IEEE_754-1985" target="_window">this link</a> for an explanation of the IEEE 754 standard.
|
|
|
|
</ul>
|
|
</p>
|
|
|
|
<!--div style="background-color: #ccc; padding: 4px 2px; border: 1px" -->
|
|
<!--img src="images/c++-source-code.png" height="20pt" style="float:left" /-->
|
|
<div>
|
|
<a href="#top" class="button" >To top</a>
|
|
<!--div id="_cpp" ></div--><br>
|
|
</div>
|
|
|
|
|
|
<!------------------------------------------------------------->
|
|
<h3><a name="Samples:2"></a>Forbidding the serialization of non finite float values</h3>
|
|
|
|
<p>
|
|
One can ask a PBA to reject non-finite values. This is done by
|
|
passing the <tt class="code">boost::archive::no_infnan</tt> flag to the constructor
|
|
of the output archive. Note that in this case, denormalized values are
|
|
still accepted, but infinite and NaNs aren't.
|
|
</p>
|
|
|
|
<p>
|
|
The <tt class="fs">tutorial_pba_3.cpp</tt> sample
|
|
program that illustrates this special case:
|
|
</p>
|
|
|
|
<div style="background-color: #ccc; padding: 4px 2px; border: 1px" >
|
|
<img src="images/c++-source-code.png" height="20pt" style="float:left" /> The <tt class="fs">tutorial_pba_3.cpp</tt> source code <a href="./code/tutorial_pba_3.cpp" class="button" >Download</a>
|
|
<a href="javascript:toggleDiv('tutorial_pba_3_cpp');" class="button" >Show/hide</a>
|
|
<div id="tutorial_pba_3_cpp" ><PRE>
|
|
<I><FONT COLOR="#B22222">/** tutorial_pba_3.cpp
|
|
*
|
|
* (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
|
|
*
|
|
* Use, modification and distribution is subject to 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)
|
|
*
|
|
*/</FONT></I>
|
|
|
|
<I><FONT COLOR="#B22222">/**
|
|
* The intent of this program is to serve as a tutorial for
|
|
* users of the portable binary archive in the framework of
|
|
* the Boost/Serialization library.
|
|
*
|
|
* This sample program shows how to use a portable binary archive
|
|
* and prevent the serialization of non-finite floating numbers.
|
|
*
|
|
*/</FONT></I>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><string></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><fstream></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><limits></FONT></B>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/portable_binary_oarchive.hpp></FONT></B>
|
|
|
|
<B><FONT COLOR="#228B22">int</FONT></B> <B><FONT COLOR="#0000FF">main</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
using namespace std;
|
|
|
|
<I><FONT COLOR="#B22222">// The name for the example data file :
|
|
</FONT></I> string filename = <B><FONT COLOR="#BC8F8F">"pba_3.data"</FONT></B>;
|
|
|
|
<B><FONT COLOR="#A020F0">try</FONT></B>
|
|
{
|
|
<I><FONT COLOR="#B22222">// An array of single precision floating numbers:
|
|
</FONT></I> <B><FONT COLOR="#228B22">float</FONT></B> x[5];
|
|
x[0] = 3.14159; <I><FONT COLOR="#B22222">// Pi
|
|
</FONT></I> x[1] = 6.022e22; <I><FONT COLOR="#B22222">// Avogadro constant
|
|
</FONT></I> x[2] = 1.6e-19; <I><FONT COLOR="#B22222">// Electron charge magnitude
|
|
</FONT></I> x[3] = 1.e-40; <I><FONT COLOR="#B22222">// A tiny (denormalized) value
|
|
</FONT></I> x[4] = numeric_limits<<B><FONT COLOR="#228B22">float</FONT></B>>::infinity (); <I><FONT COLOR="#B22222">// This will fail while serializing...
|
|
</FONT></I>
|
|
<I><FONT COLOR="#B22222">// Open an output file stream in binary mode :
|
|
</FONT></I> ofstream fout (filename.c_str (), ios_base::binary);
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Create an output portable binary archive attached to the output file,
|
|
</FONT></I> <I><FONT COLOR="#B22222">// using the special 'boost::archive::no_infnan' flag :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::portable_binary_oarchive opba (fout, boost::archive::no_infnan);
|
|
|
|
<I><FONT COLOR="#B22222">// Store (serialize) variables :
|
|
</FONT></I> <B><FONT COLOR="#A020F0">for</FONT></B> (<B><FONT COLOR="#228B22">int</FONT></B> i = 0; i < 5; ++i)
|
|
{
|
|
clog << <B><FONT COLOR="#BC8F8F">"Serializing value : "</FONT></B> << x[i] << <B><FONT COLOR="#BC8F8F">" ... "</FONT></B>;
|
|
opba & x[i];
|
|
clog << <B><FONT COLOR="#BC8F8F">"Ok !"</FONT></B> << endl;
|
|
}
|
|
}
|
|
}
|
|
<B><FONT COLOR="#A020F0">catch</FONT></B> (exception & x)
|
|
{
|
|
cerr << <B><FONT COLOR="#BC8F8F">"ERROR: "</FONT></B> << x.what () << endl;
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> 1;
|
|
}
|
|
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> 0;
|
|
}
|
|
|
|
<I><FONT COLOR="#B22222">// end of tutorial_pba_3.cpp
|
|
</FONT></I>
|
|
</PRE>
|
|
</div><br></div>
|
|
|
|
|
|
<p>
|
|
We can check that the PBA now throws an exception as soon as it
|
|
encounters a non finite floating point value during the serialization
|
|
process:
|
|
<pre>
|
|
Serializing value : 3.14159 ... Ok !
|
|
Serializing value : 6.022e+22 ... Ok !
|
|
Serializing value : 1.6e-19 ... Ok !
|
|
Serializing value : 9.99995e-41 ... Ok !
|
|
Serializing value : inf ... ERROR: serialization of illegal floating point value: inf
|
|
|
|
</pre>
|
|
</p>
|
|
|
|
<!--div style="background-color: #ccc; padding: 4px 2px; border: 1px" -->
|
|
<!--img src="images/c++-source-code.png" height="20pt" style="float:left" /-->
|
|
<div>
|
|
<a href="#top" class="button" >To top</a>
|
|
<!--div id="_cpp" ></div--><br>
|
|
</div>
|
|
|
|
|
|
<!------------------------------------------------------------->
|
|
<h3><a name="Samples:3"></a>Serializing integer numbers</h3>
|
|
|
|
<p>
|
|
The PBA obviously handles integer numbers. Unfortunately, C/C++ does
|
|
not garantee the portable size of its primitive integer types (short,
|
|
int, long... and their unsigned versions). It depends on the
|
|
architecture (32-bit/64-bit) and the compiler.
|
|
</p>
|
|
<p>The Boost library
|
|
addresses this issue through a collection of <i>typedefs</i> for
|
|
integer types of common sizes. This technique is supposed to allow
|
|
the manipulation of integer variables in a portable way, typically with
|
|
text or XML archives. So, we are generally
|
|
encouraged to use the <tt class="fs">boost/cstdint.hpp</tt> header file and
|
|
the <i>typedefs</i> defined therein.
|
|
</p>
|
|
<p>Due to its encoding scheme
|
|
of integer numbers, the PBA does not strictly need such technique to ensure
|
|
a correct behaviour while (de)serializing integer numbers.
|
|
This is because the little endian encoding approach allows to only store the non-zero bytes.
|
|
It is thus possible to serialize a value using one integer type (<tt class="code">short int</tt>) and then
|
|
deserialize it using another integer type (<tt class="code">long long</tt>).
|
|
</p>
|
|
<p>
|
|
However, for a strict and safe portable behaviour
|
|
of PBA, we recommend that, in most cases, the user should systematically use such typedefs for all
|
|
serializable integer values. This applies particularly for member attributes
|
|
in <i>structs</i> and <i>classes</i> and should allows the transparent switching
|
|
to another kind of archive (text, XML) thanks to the <tt class="code">serialize</tt> template method.
|
|
</p>
|
|
|
|
<p>
|
|
The <tt class="fs">tutorial_pba_4.cpp</tt> sample
|
|
program illustrates the serialization/deserialization of 8-bit,
|
|
16-bit, 32-bit and 64-bit integer numbers:
|
|
</p>
|
|
|
|
<div style="background-color: #ccc; padding: 4px 2px; border: 1px" >
|
|
<img src="images/c++-source-code.png" height="20pt" style="float:left" /> The <tt class="fs">tutorial_pba_4.cpp</tt> source code <a href="./code/tutorial_pba_4.cpp" class="button" >Download</a>
|
|
<a href="javascript:toggleDiv('tutorial_pba_4_cpp');" class="button" >Show/hide</a>
|
|
<div id="tutorial_pba_4_cpp" ><PRE>
|
|
<I><FONT COLOR="#B22222">/** tutorial_pba_4.cpp
|
|
*
|
|
* (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
|
|
*
|
|
* Use, modification and distribution is subject to 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)
|
|
*
|
|
*/</FONT></I>
|
|
|
|
<I><FONT COLOR="#B22222">/**
|
|
* The intent of this program is to serve as a tutorial for
|
|
* users of the portable binary archive in the framework of
|
|
* the Boost/Serialization library.
|
|
*
|
|
* This sample program shows how to use a portable binary archive
|
|
* to store/load integer numbers of various sizes using the Boost
|
|
* portable integer typedefs.
|
|
*
|
|
*/</FONT></I>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><string></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><fstream></FONT></B>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/cstdint.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/portable_binary_oarchive.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/portable_binary_iarchive.hpp></FONT></B>
|
|
|
|
<B><FONT COLOR="#228B22">int</FONT></B> <B><FONT COLOR="#0000FF">main</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
using namespace std;
|
|
|
|
<I><FONT COLOR="#B22222">// The name for the example data file :
|
|
</FONT></I> string filename = <B><FONT COLOR="#BC8F8F">"pba_4.data"</FONT></B>;
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Some integer numbers :
|
|
</FONT></I> <B><FONT COLOR="#228B22">bool</FONT></B> t = true;
|
|
<B><FONT COLOR="#228B22">char</FONT></B> c = <B><FONT COLOR="#BC8F8F">'c'</FONT></B>;
|
|
<B><FONT COLOR="#228B22">unsigned</FONT></B> <B><FONT COLOR="#228B22">char</FONT></B> u = <B><FONT COLOR="#BC8F8F">'u'</FONT></B>;
|
|
int8_t b = -3; <I><FONT COLOR="#B22222">// char
|
|
</FONT></I> uint8_t B = +6; <I><FONT COLOR="#B22222">// unsigned char
|
|
</FONT></I> int16_t s = -16;
|
|
uint16_t S = +32;
|
|
int32_t l = -128;
|
|
uint32_t L = +127;
|
|
int64_t ll = -1024;
|
|
uint64_t LL = +2048;
|
|
|
|
<I><FONT COLOR="#B22222">// Open an output file stream in binary mode :
|
|
</FONT></I> ofstream fout (filename.c_str (), ios_base::binary);
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Create an output portable binary archive attached to the output file :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::portable_binary_oarchive opba (fout);
|
|
|
|
<I><FONT COLOR="#B22222">// Store (serialize) variables :
|
|
</FONT></I> opba & t & c & u & b & B & s & S & l & L & ll & LL;
|
|
}
|
|
}
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Single precision floating numbers to be loaded :
|
|
</FONT></I> <I><FONT COLOR="#B22222">// Some integer numbers :
|
|
</FONT></I> <B><FONT COLOR="#228B22">bool</FONT></B> t;
|
|
<B><FONT COLOR="#228B22">char</FONT></B> c;
|
|
<B><FONT COLOR="#228B22">unsigned</FONT></B> <B><FONT COLOR="#228B22">char</FONT></B> u;
|
|
int8_t b;
|
|
uint8_t B;
|
|
int16_t s;
|
|
uint16_t S;
|
|
int32_t l;
|
|
uint32_t L;
|
|
int64_t ll;
|
|
uint64_t LL;
|
|
|
|
<I><FONT COLOR="#B22222">// Open an input file stream in binary mode :
|
|
</FONT></I> ifstream fin (filename.c_str (), ios_base::binary);
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Create an input portable binary archive attached to the input file :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::portable_binary_iarchive ipba (fin);
|
|
|
|
<I><FONT COLOR="#B22222">// Load (de-serialize) variables using the same
|
|
</FONT></I> <I><FONT COLOR="#B22222">// order than for serialization :
|
|
</FONT></I> ipba & t & c & u & b & B & s & S & l & L & ll & LL;
|
|
}
|
|
|
|
clog << <B><FONT COLOR="#BC8F8F">"t = "</FONT></B> << t << <B><FONT COLOR="#BC8F8F">" (bool)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">"c = '"</FONT></B> << c << <B><FONT COLOR="#BC8F8F">"' (char)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">"u = '"</FONT></B> << u << <B><FONT COLOR="#BC8F8F">"' (unsigned char)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">"b = "</FONT></B> << (<B><FONT COLOR="#228B22">int</FONT></B>) b << <B><FONT COLOR="#BC8F8F">" (int8_t)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">"B = "</FONT></B> << (<B><FONT COLOR="#228B22">int</FONT></B>) B << <B><FONT COLOR="#BC8F8F">" (uint8_t)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">"s = "</FONT></B> << s << <B><FONT COLOR="#BC8F8F">" (int16_t)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">"S = "</FONT></B> << S << <B><FONT COLOR="#BC8F8F">" (uint16_t)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">"l = "</FONT></B> << l << <B><FONT COLOR="#BC8F8F">" (int32_t)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">"L = "</FONT></B> << L << <B><FONT COLOR="#BC8F8F">" (uint32_t)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">"ll = "</FONT></B> << ll << <B><FONT COLOR="#BC8F8F">" (int64_t)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">"LL = "</FONT></B> << LL << <B><FONT COLOR="#BC8F8F">" (uint64_t)"</FONT></B> << endl;
|
|
}
|
|
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> 0;
|
|
}
|
|
|
|
<I><FONT COLOR="#B22222">// end of tutorial_pba_4.cpp
|
|
</FONT></I>
|
|
</PRE>
|
|
</div><br></div>
|
|
|
|
|
|
<p>
|
|
The resulting PBA file is:
|
|
<pre class="byte">127 1 9 1 84 1 99 1 117 255 253 1 6 255 240 1
|
|
32 255 128 1 127 254 0 252 2 0 8
|
|
</pre>
|
|
|
|
where:
|
|
<ul>
|
|
|
|
<li> <tt class="byte">127 1 9</tt> is the archive header.
|
|
|
|
<li> <tt class="byte">1 84</tt> indicates <tt class="byte">1</tt> byte to
|
|
store the <tt>true</tt> boolean value (ASCII code
|
|
is <tt class="byte">84</tt>).
|
|
|
|
<li> <tt class="byte">1 99</tt> indicates <tt class="byte">1</tt> byte to
|
|
store the ASCII code of character <tt>'c'</tt> (<tt class="byte">99</tt>).
|
|
|
|
<li> <tt class="byte">1 117</tt> indicates <tt class="byte">1</tt> byte to
|
|
store the ASCII code of character <tt>'u'</tt>
|
|
(<tt class="byte">117</tt>).
|
|
|
|
<li> <tt class="byte">255 253</tt> corresponds to the special case for a
|
|
negative integer:
|
|
<tt class="byte">255</tt> is the binary coding for value <tt>-1</tt>
|
|
which means that the integer is negative and needs 1 byte to be
|
|
stored, <tt class="byte">253</tt>, i.e. the 8-bit encoding of the signed
|
|
decimal value <tt>-3</tt>.
|
|
|
|
<li> <tt class="byte">1 6</tt> indicates <tt class="byte">1</tt> byte to store
|
|
value <tt class="byte">6</tt>.
|
|
|
|
<li> <tt class="byte">255 240</tt> corresponds again to a negative
|
|
integer:
|
|
<tt class="byte">255</tt> is the byte coding for value <tt>-1</tt>
|
|
(negative integer encoded using 1 single byte)
|
|
and <tt class="byte">240</tt> is the 8-bit encoding of decimal
|
|
value <tt>-16</tt>.
|
|
|
|
<li> the same scheme is used for all remaining values in the archive :
|
|
the verification is let as an exercise.
|
|
|
|
</ul>
|
|
|
|
</p>
|
|
|
|
<p>Note that this coding scheme optimizes the number of streamed
|
|
bytes. Particularly, it discards the leading <i>zero-ed</i> bytes
|
|
(MSB) of the binary encoding of any integer value in order to save
|
|
storage. Also we recall that the exact <tt>0</tt> value (<i>zero</i>
|
|
or <tt>false</tt> for a <i>boolean</i> data) is always encoded using a
|
|
unique <tt>0</tt> byte (zero optimization). Note this approach is also
|
|
used for floating point numbers.
|
|
</p>
|
|
|
|
<!--div style="background-color: #ccc; padding: 4px 2px; border: 1px" -->
|
|
<!--img src="images/c++-source-code.png" height="20pt" style="float:left" /-->
|
|
<div>
|
|
<a href="#top" class="button" >To top</a>
|
|
<!--div id="_cpp" ></div--><br>
|
|
</div>
|
|
|
|
|
|
<!------------------------------------------------------------->
|
|
<h3><a name="Samples:4"></a>Using PBA serialization with a memory buffer</h3>
|
|
|
|
<p>
|
|
In some case, we don't want to serialize some data in a file
|
|
(<tt class="code">std::ofstream</tt>), but we simply plan to stream it in a memory buffer.
|
|
</p>
|
|
|
|
<p>
|
|
The <tt class="fs">tutorial_pba_5.cpp</tt> sample
|
|
program makes use of a memory buffer implemented with a STL vector of
|
|
characters. The PBA is associated to this buffer thanks to a special
|
|
streaming interface mechanism provided by the Boost/Iostreams
|
|
library. With such technique one can stream serializable data in
|
|
some memory buffer in place of a file :
|
|
</p>
|
|
|
|
<div style="background-color: #ccc; padding: 4px 2px; border: 1px" >
|
|
<img src="images/c++-source-code.png" height="20pt" style="float:left" /> The <tt class="fs">tutorial_pba_5.cpp</tt> source code <a href="./code/tutorial_pba_5.cpp" class="button" >Download</a>
|
|
<a href="javascript:toggleDiv('tutorial_pba_5_cpp');" class="button" >Show/hide</a>
|
|
<div id="tutorial_pba_5_cpp" ><PRE>
|
|
<I><FONT COLOR="#B22222">/** tutorial_pba_5.cpp
|
|
*
|
|
* (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
|
|
*
|
|
* Use, modification and distribution is subject to 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)
|
|
*
|
|
*/</FONT></I>
|
|
|
|
<I><FONT COLOR="#B22222">/**
|
|
* The intent of this program is to serve as a tutorial for
|
|
* users of the portable binary archive in the framework of
|
|
* the Boost/Serialization library.
|
|
*
|
|
* This sample program shows how to use a portable binary archive
|
|
* to store/load data in a memory buffer.
|
|
*
|
|
*/</FONT></I>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><string></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><vector></FONT></B>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/iostreams/stream.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/iostreams/device/back_inserter.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/iostreams/device/array.hpp></FONT></B>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/cstdint.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/portable_binary_oarchive.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/portable_binary_iarchive.hpp></FONT></B>
|
|
|
|
<B><FONT COLOR="#228B22">int</FONT></B> <B><FONT COLOR="#0000FF">main</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
using namespace std;
|
|
|
|
<I><FONT COLOR="#B22222">// The memory buffer is implemented using a STL vector :
|
|
</FONT></I> <B><FONT COLOR="#228B22">typedef</FONT></B> std::vector<<B><FONT COLOR="#228B22">char</FONT></B>> buffer_type;
|
|
buffer_type buffer;
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Some data to be stored :
|
|
</FONT></I> <B><FONT COLOR="#228B22">bool</FONT></B> t = true;
|
|
<B><FONT COLOR="#228B22">char</FONT></B> c = <B><FONT COLOR="#BC8F8F">'c'</FONT></B>;
|
|
int16_t s = +16;
|
|
int32_t l = -128;
|
|
int64_t ll = +10000000000;
|
|
<B><FONT COLOR="#228B22">float</FONT></B> pi = 3.14159;
|
|
<B><FONT COLOR="#228B22">double</FONT></B> nan = numeric_limits<<B><FONT COLOR="#228B22">double</FONT></B>>::quiet_NaN ();
|
|
string hello = <B><FONT COLOR="#BC8F8F">"World !"</FONT></B>;
|
|
|
|
buffer.reserve (1024); <I><FONT COLOR="#B22222">// pre-allocate some memory
|
|
</FONT></I>
|
|
<I><FONT COLOR="#B22222">// The output stream interface to the buffer :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::iostreams::stream<boost::iostreams::back_insert_device<buffer_type> > output_stream (buffer);
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Create an output portable binary archive attached to the output file :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::portable_binary_oarchive opba (output_stream);
|
|
|
|
<I><FONT COLOR="#B22222">// Store (serialize) variables :
|
|
</FONT></I> opba & t & c & s & l & ll & pi & nan & hello;
|
|
}
|
|
|
|
}
|
|
|
|
clog << <B><FONT COLOR="#BC8F8F">"Buffer content is "</FONT></B> << buffer.size () << <B><FONT COLOR="#BC8F8F">" bytes : "</FONT></B> << endl << <B><FONT COLOR="#BC8F8F">" "</FONT></B>;
|
|
<B><FONT COLOR="#A020F0">for</FONT></B> (<B><FONT COLOR="#228B22">int</FONT></B> i = 0; i < buffer.size (); ++i)
|
|
{
|
|
clog << (<B><FONT COLOR="#228B22">int</FONT></B>) ((<B><FONT COLOR="#228B22">unsigned</FONT></B> <B><FONT COLOR="#228B22">char</FONT></B>) buffer[i]) << <B><FONT COLOR="#BC8F8F">' '</FONT></B>;
|
|
<B><FONT COLOR="#A020F0">if</FONT></B> ((i + 1) % 20 == 0) clog << endl << <B><FONT COLOR="#BC8F8F">" "</FONT></B>;
|
|
}
|
|
clog << endl;
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Some data to be loaded :
|
|
</FONT></I> <B><FONT COLOR="#228B22">bool</FONT></B> t;
|
|
<B><FONT COLOR="#228B22">char</FONT></B> c;
|
|
int16_t s;
|
|
int32_t l;
|
|
int64_t ll;
|
|
<B><FONT COLOR="#228B22">float</FONT></B> pi;
|
|
<B><FONT COLOR="#228B22">double</FONT></B> nan;
|
|
string hello;
|
|
|
|
<I><FONT COLOR="#B22222">// The input stream interface to the buffer :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::iostreams::stream<boost::iostreams::array_source> input_stream (&buffer[0],
|
|
buffer.size ());
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Create an input portable binary archive attached to the input file :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::portable_binary_iarchive ipba (input_stream);
|
|
|
|
<I><FONT COLOR="#B22222">// Load (de-serialize) variables :
|
|
</FONT></I> ipba & t & c & s & l & ll & pi & nan & hello;
|
|
}
|
|
|
|
clog << <B><FONT COLOR="#BC8F8F">"Loaded values from the buffer are: "</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" t = "</FONT></B> << t << <B><FONT COLOR="#BC8F8F">" (bool)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" c = '"</FONT></B> << c << <B><FONT COLOR="#BC8F8F">"' (char)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" s = "</FONT></B> << s << <B><FONT COLOR="#BC8F8F">" (int16_t)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" l = "</FONT></B> << l << <B><FONT COLOR="#BC8F8F">" (int32_t)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" ll = "</FONT></B> << ll << <B><FONT COLOR="#BC8F8F">" (int64_t)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" pi = "</FONT></B> << pi << <B><FONT COLOR="#BC8F8F">" (float)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" nan = "</FONT></B> << nan << <B><FONT COLOR="#BC8F8F">" (double)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" hello = \""</FONT></B> << hello << <B><FONT COLOR="#BC8F8F">"\" (std::string)"</FONT></B> << endl;
|
|
}
|
|
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> 0;
|
|
}
|
|
|
|
<I><FONT COLOR="#B22222">// end of tutorial_pba_5.cpp
|
|
</FONT></I>
|
|
</PRE>
|
|
</div><br></div>
|
|
|
|
|
|
<p>
|
|
After the storing of data in the archive, the content of the buffer of
|
|
characters is printed:
|
|
<pre>
|
|
Buffer content is 40 bytes :
|
|
127 1 9 1 84 1 99 1 16 255 128 5 0 228 11 84 2 4 208 15
|
|
73 64 8 255 255 255 255 255 255 255 127 1 7 87 111 114 108 100 32 33
|
|
|
|
Loaded values from the buffer are:
|
|
t = 1 (bool)
|
|
c = 'c' (char)
|
|
s = 16 (int16_t)
|
|
l = -128 (int32_t)
|
|
ll = 10000000000 (int64_t)
|
|
pi = 3.14159 (float)
|
|
nan = nan (double)
|
|
hello = "World !" (std::string)
|
|
|
|
</pre>
|
|
Again the PBA encoding scheme can be easily interpreted. This is let
|
|
as an exercise.
|
|
</p>
|
|
|
|
<h4>Extra:</h4>
|
|
<p>
|
|
You may have a look on the <tt class="fs">tutorial_pba_6.cpp</tt> program that shows a possible — and
|
|
provocative — combined usage of the Boost/Serialization concepts, the
|
|
Boost/Iostreams facilities and the PBA; it enables the copy of an object
|
|
of a non-copyable class.
|
|
</p>
|
|
|
|
<div style="background-color: #ccc; padding: 4px 2px; border: 1px" >
|
|
<img src="images/c++-source-code.png" height="20pt" style="float:left" /> The <tt class="fs">tutorial_pba_6.cpp</tt> source code <a href="./code/tutorial_pba_6.cpp" class="button" >Download</a>
|
|
<a href="javascript:toggleDiv('tutorial_pba_6_cpp');" class="button" >Show/hide</a>
|
|
<div id="tutorial_pba_6_cpp" ><PRE>
|
|
<I><FONT COLOR="#B22222">/** tutorial_pba_6.cpp
|
|
*
|
|
* (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
|
|
*
|
|
* Use, modification and distribution is subject to 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)
|
|
*
|
|
*/</FONT></I>
|
|
|
|
<I><FONT COLOR="#B22222">/**
|
|
* The intent of this program is to serve as a tutorial for
|
|
* users of the portable binary archive in the framework of
|
|
* the Boost/Serialization library.
|
|
*
|
|
* This sample program shows how to use a portable binary archive
|
|
* associated to a memory buffer to copy a non-copyable object.
|
|
*
|
|
*/</FONT></I>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><iostream></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><string></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><sstream></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><vector></FONT></B>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/utility.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/iostreams/stream.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/iostreams/device/back_inserter.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/iostreams/device/array.hpp></FONT></B>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/cstdint.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/portable_binary_oarchive.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/portable_binary_iarchive.hpp></FONT></B>
|
|
|
|
using namespace std;
|
|
|
|
<I><FONT COLOR="#B22222">/* A foo noncopyable class */</FONT></I>
|
|
<B><FONT COLOR="#228B22">struct</FONT></B> foo : boost::noncopyable
|
|
{
|
|
uint32_t status;
|
|
<B><FONT COLOR="#228B22">double</FONT></B> value;
|
|
<B><FONT COLOR="#228B22">double</FONT></B> special;
|
|
|
|
string to_string () <B><FONT COLOR="#228B22">const</FONT></B>
|
|
{
|
|
ostringstream sout;
|
|
sout << <B><FONT COLOR="#BC8F8F">"foo={status="</FONT></B> << status << <B><FONT COLOR="#BC8F8F">"; value="</FONT></B> << value << <B><FONT COLOR="#BC8F8F">"; special="</FONT></B> << special<< <B><FONT COLOR="#BC8F8F">"}"</FONT></B>;
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> sout.str();
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">template</FONT></B><<B><FONT COLOR="#228B22">class</FONT></B> Archive>
|
|
<B><FONT COLOR="#228B22">void</FONT></B> serialize (Archive & ar, <B><FONT COLOR="#228B22">const</FONT></B> <B><FONT COLOR="#228B22">unsigned</FONT></B> <B><FONT COLOR="#228B22">int</FONT></B> version)
|
|
{
|
|
ar & status;
|
|
ar & value;
|
|
ar & special;
|
|
<B><FONT COLOR="#A020F0">return</FONT></B>;
|
|
}
|
|
|
|
};
|
|
|
|
<I><FONT COLOR="#B22222">// A templatized copy function for Boost/Serialization equipped classes.
|
|
</FONT></I><I><FONT COLOR="#B22222">// Here we use PBAs associated to a memory buffer :
|
|
</FONT></I><B><FONT COLOR="#228B22">template</FONT></B> <<B><FONT COLOR="#228B22">class</FONT></B> Serializable>
|
|
<B><FONT COLOR="#228B22">void</FONT></B> <B><FONT COLOR="#0000FF">copy</FONT></B> (<B><FONT COLOR="#228B22">const</FONT></B> Serializable & source, Serializable & target)
|
|
{
|
|
namespace io = boost::iostreams;
|
|
namespace ba = boost::archive;
|
|
<B><FONT COLOR="#A020F0">if</FONT></B> (&source == &target) <B><FONT COLOR="#A020F0">return</FONT></B>; <I><FONT COLOR="#B22222">// self-copy guard
|
|
</FONT></I> <B><FONT COLOR="#228B22">typedef</FONT></B> std::vector<<B><FONT COLOR="#228B22">char</FONT></B>> buffer_type;
|
|
buffer_type buffer;
|
|
buffer.reserve (1024);
|
|
{
|
|
<B><FONT COLOR="#5F9EA0">io</FONT></B>::stream<io::back_insert_device<buffer_type> > output_stream (buffer);
|
|
<B><FONT COLOR="#5F9EA0">ba</FONT></B>::portable_binary_oarchive opba (output_stream);
|
|
opba & source;
|
|
}
|
|
{
|
|
<B><FONT COLOR="#5F9EA0">io</FONT></B>::stream<io::array_source> input_stream (&buffer[0], buffer.size ());
|
|
<B><FONT COLOR="#5F9EA0">ba</FONT></B>::portable_binary_iarchive ipba (input_stream);
|
|
ipba & target;
|
|
}
|
|
<B><FONT COLOR="#A020F0">return</FONT></B>;
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">int</FONT></B> <B><FONT COLOR="#0000FF">main</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
<I><FONT COLOR="#B22222">// Some instance of the 'foo' class :
|
|
</FONT></I> foo dummy;
|
|
dummy.status = 1;
|
|
dummy.value = 3.14159;
|
|
dummy.special = numeric_limits<<B><FONT COLOR="#228B22">double</FONT></B>>::quiet_NaN ();
|
|
clog << <B><FONT COLOR="#BC8F8F">"dummy is : "</FONT></B> << dummy.to_string () << endl;
|
|
|
|
<I><FONT COLOR="#B22222">// Another instance of the 'foo' class :
|
|
</FONT></I> foo clone;
|
|
|
|
<I><FONT COLOR="#B22222">/* The following instruction is forbidden because foo
|
|
inherits 'boost::noncopyable' :
|
|
|
|
clone = dummy; // this ends in a compilation error.
|
|
|
|
*/</FONT></I>
|
|
|
|
<I><FONT COLOR="#B22222">// Anyway, we can use this workaround :
|
|
</FONT></I> copy (dummy, clone);
|
|
clog << <B><FONT COLOR="#BC8F8F">"clone is : "</FONT></B> << clone.to_string () << endl;
|
|
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> 0;
|
|
}
|
|
|
|
<I><FONT COLOR="#B22222">// end of tutorial_pba_6.cpp
|
|
</FONT></I>
|
|
</PRE>
|
|
</div><br></div>
|
|
|
|
|
|
<p> <b>Remark</b> : if a class has been made <i>non-copyable</i> at design,
|
|
it is likely for a good reason; so it is not recommended to workaround
|
|
this trait using such a trick, unless you know what you are doing
|
|
and all the consequences !
|
|
</p>
|
|
|
|
<!--div style="background-color: #ccc; padding: 4px 2px; border: 1px" -->
|
|
<!--img src="images/c++-source-code.png" height="20pt" style="float:left" /-->
|
|
<div>
|
|
<a href="#top" class="button" >To top</a>
|
|
<!--div id="_cpp" ></div--><br>
|
|
</div>
|
|
|
|
|
|
<!------------------------------------------------------------->
|
|
<h3><a name="Samples:5"></a>An alternative to PBA using text or XML archives made portable</h3>
|
|
|
|
<p>
|
|
In some circonstances, it may be useful to use the Boost <i>text</i>
|
|
and <i>XML</i> archives in somewhat portable way. For example, we may
|
|
want to benefit of the XML archive's human-friendly format for
|
|
debugging purpose before to switch to the PBA for production runs.
|
|
However, the <i>text</i> and <i>XML</i> archives provided by the Boost
|
|
serialization library are not strictly portable, particularly because
|
|
they does not support the serialization of non-finite floating point
|
|
numbers. This is because the serialization of floating point numbers
|
|
depends on some formatting features of standard I/O streams. See the
|
|
<tt class="fs">tutorial_pba_7.cpp</tt> sample program below :
|
|
</p>
|
|
|
|
<div style="background-color: #ccc; padding: 4px 2px; border: 1px" >
|
|
<img src="images/c++-source-code.png" height="20pt" style="float:left" /> The <tt class="fs">tutorial_pba_7.cpp</tt> source code <a href="./code/tutorial_pba_7.cpp" class="button" >Download</a>
|
|
<a href="javascript:toggleDiv('tutorial_pba_7_cpp');" class="button" >Show/hide</a>
|
|
<div id="tutorial_pba_7_cpp" ><PRE>
|
|
<I><FONT COLOR="#B22222">/** tutorial_pba_7.cpp
|
|
*
|
|
* (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
|
|
*
|
|
* Use, modification and distribution is subject to 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)
|
|
*
|
|
*/</FONT></I>
|
|
|
|
<I><FONT COLOR="#B22222">/**
|
|
* The intent of this program is to serve as a tutorial for
|
|
* users of the portable binary archive in the framework of
|
|
* the Boost/Serialization library.
|
|
*
|
|
* This example shows how the default behaviour of standard
|
|
* I/O streams does not support the read/write operations of
|
|
* non-finite floating point values in a portable way.
|
|
*
|
|
*/</FONT></I>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><string></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><iostream></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><sstream></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><limits></FONT></B>
|
|
|
|
using namespace std;
|
|
|
|
<B><FONT COLOR="#228B22">int</FONT></B> <B><FONT COLOR="#0000FF">main</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
{
|
|
<B><FONT COLOR="#228B22">float</FONT></B> x = numeric_limits<<B><FONT COLOR="#228B22">float</FONT></B>>::infinity ();
|
|
<B><FONT COLOR="#228B22">double</FONT></B> y = numeric_limits<<B><FONT COLOR="#228B22">double</FONT></B>>::quiet_NaN ();
|
|
cout.precision (8);
|
|
cout << <B><FONT COLOR="#BC8F8F">"x = "</FONT></B> << x << endl;
|
|
cout.precision (16);
|
|
cout << <B><FONT COLOR="#BC8F8F">"y = "</FONT></B> << y << endl;
|
|
}
|
|
|
|
{
|
|
string input (<B><FONT COLOR="#BC8F8F">"inf nan"</FONT></B>);
|
|
istringstream iss (input);
|
|
<B><FONT COLOR="#228B22">float</FONT></B> x;
|
|
<B><FONT COLOR="#228B22">double</FONT></B> y;
|
|
iss >> x >> y;
|
|
<B><FONT COLOR="#A020F0">if</FONT></B> (! iss)
|
|
{
|
|
cerr << <B><FONT COLOR="#BC8F8F">"Cannot read 'x' or 'y' : non finite values are not supported !"</FONT></B> << endl;
|
|
}
|
|
}
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> 0;
|
|
}
|
|
|
|
<I><FONT COLOR="#B22222">// end of tutorial_pba_7.cpp
|
|
</FONT></I>
|
|
</PRE>
|
|
</div><br></div>
|
|
|
|
|
|
<p>
|
|
Depending on the system, one can get some various representation
|
|
respectively for the <i>infinity</i> and <i>NaN</i> values :
|
|
<ul>
|
|
<li>typically on Windows :
|
|
<pre>
|
|
1.#INF
|
|
</pre>
|
|
and
|
|
<pre>
|
|
-1.#IND
|
|
</pre>
|
|
<li>and on Linux :
|
|
<pre>
|
|
inf
|
|
</pre>
|
|
and
|
|
<pre>
|
|
nan
|
|
</pre>
|
|
|
|
</ul>
|
|
Usually one can print such non finite values in an output stream
|
|
(using such a non portable representation), but parsing it from an
|
|
input stream fails !
|
|
</p>
|
|
|
|
<p>
|
|
Hopefully this issue can be solved by configuring the I/O streams with
|
|
some special <i>locale</i> features provided by Boost
|
|
(see <a href="http://www.boost.org/doc/libs/1_47_0/libs/serialization/doc/implementation.html#charencoding">this
|
|
link</a>).
|
|
</p>
|
|
|
|
<p>
|
|
The <tt class="fs">tutorial_pba_8.cpp</tt> program
|
|
shows how this can be achieved through the use of special resources
|
|
from the <tt class="fs">boost/archive/codecvt_null.hpp</tt> and
|
|
<tt class="fs">boost/math/special_functions/nonfinite_num_facets.hpp</tt> headers :
|
|
</p>
|
|
|
|
<div style="background-color: #ccc; padding: 4px 2px; border: 1px" >
|
|
<img src="images/c++-source-code.png" height="20pt" style="float:left" /> The <tt class="fs">tutorial_pba_8.cpp</tt> source code <a href="./code/tutorial_pba_8.cpp" class="button" >Download</a>
|
|
<a href="javascript:toggleDiv('tutorial_pba_8_cpp');" class="button" >Show/hide</a>
|
|
<div id="tutorial_pba_8_cpp" ><PRE>
|
|
<I><FONT COLOR="#B22222">/** tutorial_pba_8.cpp
|
|
*
|
|
* (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
|
|
*
|
|
* Use, modification and distribution is subject to 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)
|
|
*
|
|
*/</FONT></I>
|
|
|
|
<I><FONT COLOR="#B22222">/**
|
|
* The intent of this program is to serve as a tutorial for
|
|
* users of the portable binary archive in the framework of
|
|
* the Boost/Serialization library.
|
|
*
|
|
* This example shows how to store some variables
|
|
* of basic types (bool, integer, floating point numbers, STL string)
|
|
* using the text or XML archive format associated to a
|
|
* standard output file stream supporting portable non-finite
|
|
* floating point values.
|
|
*
|
|
*/</FONT></I>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><string></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><fstream></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><limits></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><locale></FONT></B>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/cstdint.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/xml_oarchive.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/text_oarchive.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/serialization/nvp.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/codecvt_null.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/math/special_functions/nonfinite_num_facets.hpp></FONT></B>
|
|
|
|
using namespace std;
|
|
|
|
<B><FONT COLOR="#228B22">void</FONT></B> <B><FONT COLOR="#0000FF">do_text_out</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
<I><FONT COLOR="#B22222">// The name for the example data text file :
|
|
</FONT></I> string filename = <B><FONT COLOR="#BC8F8F">"pba_8.txt"</FONT></B>;
|
|
|
|
<I><FONT COLOR="#B22222">// Some variables of various primitive types :
|
|
</FONT></I> <B><FONT COLOR="#228B22">bool</FONT></B> b = true;
|
|
<B><FONT COLOR="#228B22">char</FONT></B> c = <B><FONT COLOR="#BC8F8F">'B'</FONT></B>;
|
|
uint32_t answer = 42;
|
|
<B><FONT COLOR="#228B22">float</FONT></B> value = numeric_limits<<B><FONT COLOR="#228B22">float</FONT></B>>::infinity ();
|
|
<B><FONT COLOR="#228B22">double</FONT></B> precision = numeric_limits<<B><FONT COLOR="#228B22">double</FONT></B>>::quiet_NaN ();
|
|
string question = <B><FONT COLOR="#BC8F8F">"What makes you think she's a witch?"</FONT></B>;
|
|
|
|
<I><FONT COLOR="#B22222">// Open an output file stream :
|
|
</FONT></I> ofstream fout (filename.c_str ());
|
|
|
|
<I><FONT COLOR="#B22222">// Prepare the output file stream for inf/NaN support :
|
|
</FONT></I> locale default_locale (locale::classic (),
|
|
<B><FONT COLOR="#A020F0">new</FONT></B> boost::archive::codecvt_null<<B><FONT COLOR="#228B22">char</FONT></B>>);
|
|
locale infnan_locale (default_locale,
|
|
<B><FONT COLOR="#A020F0">new</FONT></B> boost::math::nonfinite_num_put<<B><FONT COLOR="#228B22">char</FONT></B>>);
|
|
fout.imbue (infnan_locale);
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Create an output text archive attached to the output file :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::text_oarchive ota (fout, boost::archive::no_codecvt);
|
|
|
|
<I><FONT COLOR="#B22222">// Store (serializing) variables :
|
|
</FONT></I> ota & b & c & answer & value & precision & question;
|
|
}
|
|
|
|
<B><FONT COLOR="#A020F0">return</FONT></B>;
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">void</FONT></B> <B><FONT COLOR="#0000FF">do_xml_out</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
<I><FONT COLOR="#B22222">// The name for the example data XML file :
|
|
</FONT></I> string filename = <B><FONT COLOR="#BC8F8F">"pba_8.xml"</FONT></B>;
|
|
|
|
<I><FONT COLOR="#B22222">// Some variables of various primitive types :
|
|
</FONT></I> <B><FONT COLOR="#228B22">bool</FONT></B> b = true;
|
|
<B><FONT COLOR="#228B22">char</FONT></B> c = <B><FONT COLOR="#BC8F8F">'B'</FONT></B>;
|
|
uint32_t answer = 42;
|
|
<B><FONT COLOR="#228B22">float</FONT></B> value = numeric_limits<<B><FONT COLOR="#228B22">float</FONT></B>>::infinity ();
|
|
<B><FONT COLOR="#228B22">double</FONT></B> precision = numeric_limits<<B><FONT COLOR="#228B22">double</FONT></B>>::quiet_NaN ();
|
|
string question = <B><FONT COLOR="#BC8F8F">"What makes you think she's a witch?"</FONT></B>;
|
|
|
|
<I><FONT COLOR="#B22222">// Open an output file stream :
|
|
</FONT></I> ofstream fout (filename.c_str ());
|
|
|
|
<I><FONT COLOR="#B22222">// Prepare the output file stream for inf/NaN support :
|
|
</FONT></I> locale default_locale (locale::classic (),
|
|
<B><FONT COLOR="#A020F0">new</FONT></B> boost::archive::codecvt_null<<B><FONT COLOR="#228B22">char</FONT></B>>);
|
|
locale infnan_locale (default_locale,
|
|
<B><FONT COLOR="#A020F0">new</FONT></B> boost::math::nonfinite_num_put<<B><FONT COLOR="#228B22">char</FONT></B>>);
|
|
fout.imbue (infnan_locale);
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Create an output text archive attached to the output file :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::xml_oarchive oxa (fout, boost::archive::no_codecvt);
|
|
|
|
<I><FONT COLOR="#B22222">// Store (serializing) variables :
|
|
</FONT></I> oxa & BOOST_SERIALIZATION_NVP(b)
|
|
& BOOST_SERIALIZATION_NVP(c)
|
|
& BOOST_SERIALIZATION_NVP(answer)
|
|
& BOOST_SERIALIZATION_NVP(value)
|
|
& BOOST_SERIALIZATION_NVP(precision)
|
|
& BOOST_SERIALIZATION_NVP(question);
|
|
}
|
|
|
|
<B><FONT COLOR="#A020F0">return</FONT></B>;
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">int</FONT></B> <B><FONT COLOR="#0000FF">main</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
do_text_out ();
|
|
do_xml_out ();
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> 0;
|
|
}
|
|
|
|
<I><FONT COLOR="#B22222">// end of tutorial_pba_8.cpp
|
|
</FONT></I>
|
|
</PRE>
|
|
</div><br></div>
|
|
|
|
|
|
<p>
|
|
The program creates two output files :
|
|
<ul>
|
|
<li> <tt class="fs">pba_8.txt</tt> stores a text archive with
|
|
non finite floating point values :
|
|
<pre>
|
|
22 serialization::archive 9 1 66 42 inf nan 35 What makes you think she's a witch?
|
|
|
|
</pre>
|
|
<li> <tt class="fs">pba_8.xml</tt> which stored the equivalent content
|
|
using the XML archive format :
|
|
<!--pre-->
|
|
<PRE>
|
|
<B><FONT COLOR="#A020F0"><?xml version=</FONT></B><B><FONT COLOR="#BC8F8F">"1.0"</FONT></B><B><FONT COLOR="#A020F0"> encoding=</FONT></B><B><FONT COLOR="#BC8F8F">"UTF-8"</FONT></B><B><FONT COLOR="#A020F0"> standalone=</FONT></B><B><FONT COLOR="#BC8F8F">"yes"</FONT></B><B><FONT COLOR="#A020F0"> ?></FONT></B>
|
|
<B><FONT COLOR="#A020F0"><!DOCTYPE boost_serialization></FONT></B>
|
|
<B><FONT COLOR="#A020F0"><boost_serialization signature=</FONT></B><B><FONT COLOR="#BC8F8F">"serialization::archive"</FONT></B><B><FONT COLOR="#A020F0"> version=</FONT></B><B><FONT COLOR="#BC8F8F">"9"</FONT></B><B><FONT COLOR="#A020F0">></FONT></B>
|
|
<B><FONT COLOR="#A020F0"><b></FONT></B>1<B><FONT COLOR="#A020F0"></b></FONT></B>
|
|
<B><FONT COLOR="#A020F0"><c></FONT></B>66<B><FONT COLOR="#A020F0"></c></FONT></B>
|
|
<B><FONT COLOR="#A020F0"><answer></FONT></B>42<B><FONT COLOR="#A020F0"></answer></FONT></B>
|
|
<B><FONT COLOR="#A020F0"><value></FONT></B>inf<B><FONT COLOR="#A020F0"></value></FONT></B>
|
|
<B><FONT COLOR="#A020F0"><precision></FONT></B>nan<B><FONT COLOR="#A020F0"></precision></FONT></B>
|
|
<B><FONT COLOR="#A020F0"><question></FONT></B>What makes you think she<B><FONT COLOR="#A020F0">&apos;</FONT></B>s a witch?<B><FONT COLOR="#A020F0"></question></FONT></B>
|
|
<B><FONT COLOR="#A020F0"></boost_serialization></FONT></B>
|
|
|
|
</PRE>
|
|
|
|
<!--/pre-->
|
|
</ul>
|
|
</p>
|
|
|
|
<p>
|
|
The <tt class="fs">tutorial_pba_9.cpp</tt> program
|
|
deserializes the data from the text and XML archive files (respectively
|
|
<tt class="fs">pba_8.txt</tt> and <tt class="fs">pba_8.xml</tt>) and prints the restored variables :
|
|
<pre>
|
|
Loaded values from text archive are:
|
|
b = 1
|
|
c = 'B'
|
|
answer = 42
|
|
value = inf
|
|
precision = nan
|
|
question = "What makes you think she's a witch?"
|
|
Loaded values from XML archive are:
|
|
b = 1
|
|
c = 'B'
|
|
answer = 42
|
|
value = inf
|
|
precision = nan
|
|
question = "What makes you think she's a witch?"
|
|
|
|
</pre>
|
|
</p>
|
|
|
|
<p>
|
|
<div style="background-color: #ccc; padding: 4px 2px; border: 1px" >
|
|
<img src="images/c++-source-code.png" height="20pt" style="float:left" /> The <tt class="fs">tutorial_pba_9.cpp</tt> source code <a href="./code/tutorial_pba_9.cpp" class="button" >Download</a>
|
|
<a href="javascript:toggleDiv('tutorial_pba_9_cpp');" class="button" >Show/hide</a>
|
|
<div id="tutorial_pba_9_cpp" ><PRE>
|
|
<I><FONT COLOR="#B22222">/** tutorial_pba_9.cpp
|
|
*
|
|
* (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
|
|
*
|
|
* Use, modification and distribution is subject to 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)
|
|
*
|
|
*/</FONT></I>
|
|
|
|
<I><FONT COLOR="#B22222">/**
|
|
* The intent of this program is to serve as a tutorial for
|
|
* users of the portable binary archive in the framework of
|
|
* the Boost/Serialization library.
|
|
*
|
|
* This example shows how to load some variables of basic
|
|
* types (bool, char, integer, floating point numbers, STL string)
|
|
* using the text or XML archive format associated to a
|
|
* standard file input stream supporting portable non-finite
|
|
* floating point values.
|
|
*
|
|
*/</FONT></I>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><string></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><fstream></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><limits></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><locale></FONT></B>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/cstdint.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/xml_iarchive.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/text_iarchive.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/serialization/nvp.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/scoped_ptr.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/codecvt_null.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/math/special_functions/nonfinite_num_facets.hpp></FONT></B>
|
|
|
|
using namespace std;
|
|
|
|
<B><FONT COLOR="#228B22">void</FONT></B> <B><FONT COLOR="#0000FF">do_text_in</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
<I><FONT COLOR="#B22222">// The name for the example data text file :
|
|
</FONT></I> string filename = <B><FONT COLOR="#BC8F8F">"pba_8.txt"</FONT></B>;
|
|
<I><FONT COLOR="#B22222">// Some variables of various primitive types :
|
|
</FONT></I> <B><FONT COLOR="#228B22">bool</FONT></B> b;
|
|
<B><FONT COLOR="#228B22">char</FONT></B> c;
|
|
uint32_t answer;
|
|
<B><FONT COLOR="#228B22">float</FONT></B> value;
|
|
<B><FONT COLOR="#228B22">double</FONT></B> precision;
|
|
string question;
|
|
|
|
<I><FONT COLOR="#B22222">// Open an input file stream :
|
|
</FONT></I> ifstream fin (filename.c_str ());
|
|
|
|
<I><FONT COLOR="#B22222">// Prepare the input file stream for inf/NaN support :
|
|
</FONT></I> locale default_locale (locale::classic (),
|
|
<B><FONT COLOR="#A020F0">new</FONT></B> boost::archive::codecvt_null<<B><FONT COLOR="#228B22">char</FONT></B>>);
|
|
locale infnan_locale (default_locale,
|
|
<B><FONT COLOR="#A020F0">new</FONT></B> boost::math::nonfinite_num_get<<B><FONT COLOR="#228B22">char</FONT></B>>);
|
|
fin.imbue (infnan_locale);
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Create an input text archive attached to the input file :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::text_iarchive ita (fin, boost::archive::no_codecvt);
|
|
|
|
<I><FONT COLOR="#B22222">// Store (serializing) variables :
|
|
</FONT></I> ita & b & c & answer & value & precision & question;
|
|
}
|
|
|
|
clog << <B><FONT COLOR="#BC8F8F">"Loaded values from text archive are: "</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" b = "</FONT></B> << b << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" c = '"</FONT></B> << c << <B><FONT COLOR="#BC8F8F">"'"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" answer = "</FONT></B> << answer << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" value = "</FONT></B> << value << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" precision = "</FONT></B> << precision << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" question = \""</FONT></B> << question << <B><FONT COLOR="#BC8F8F">"\""</FONT></B> << endl;
|
|
|
|
<B><FONT COLOR="#A020F0">return</FONT></B>;
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">void</FONT></B> <B><FONT COLOR="#0000FF">do_xml_in</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
<I><FONT COLOR="#B22222">// The name for the example data text file :
|
|
</FONT></I> string filename = <B><FONT COLOR="#BC8F8F">"pba_8.xml"</FONT></B>;
|
|
|
|
<I><FONT COLOR="#B22222">// Some variables of various primitive types :
|
|
</FONT></I> <B><FONT COLOR="#228B22">bool</FONT></B> b;
|
|
<B><FONT COLOR="#228B22">char</FONT></B> c;
|
|
uint32_t answer;
|
|
<B><FONT COLOR="#228B22">float</FONT></B> value;
|
|
<B><FONT COLOR="#228B22">double</FONT></B> precision;
|
|
string question;
|
|
|
|
<I><FONT COLOR="#B22222">// Open an input file stream :
|
|
</FONT></I> ifstream fin (filename.c_str ());
|
|
|
|
<I><FONT COLOR="#B22222">// Prepare the input file stream for inf/NaN support :
|
|
</FONT></I> locale default_locale (locale::classic (),
|
|
<B><FONT COLOR="#A020F0">new</FONT></B> boost::archive::codecvt_null<<B><FONT COLOR="#228B22">char</FONT></B>>);
|
|
locale infnan_locale (default_locale,
|
|
<B><FONT COLOR="#A020F0">new</FONT></B> boost::math::nonfinite_num_get<<B><FONT COLOR="#228B22">char</FONT></B>>);
|
|
fin.imbue (infnan_locale);
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Create an output text archive attached to the output file :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::xml_iarchive ixa (fin, boost::archive::no_codecvt);
|
|
|
|
<I><FONT COLOR="#B22222">// Store (serializing) variables :
|
|
</FONT></I> ixa & BOOST_SERIALIZATION_NVP(b)
|
|
& BOOST_SERIALIZATION_NVP(c)
|
|
& BOOST_SERIALIZATION_NVP(answer)
|
|
& BOOST_SERIALIZATION_NVP(value)
|
|
& BOOST_SERIALIZATION_NVP(precision)
|
|
& BOOST_SERIALIZATION_NVP(question);
|
|
}
|
|
|
|
clog << <B><FONT COLOR="#BC8F8F">"Loaded values from XML archive are: "</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" b = "</FONT></B> << b << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" c = '"</FONT></B> << c << <B><FONT COLOR="#BC8F8F">"'"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" answer = "</FONT></B> << answer << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" value = "</FONT></B> << value << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" precision = "</FONT></B> << precision << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">" question = \""</FONT></B> << question << <B><FONT COLOR="#BC8F8F">"\""</FONT></B> << endl;
|
|
|
|
<B><FONT COLOR="#A020F0">return</FONT></B>;
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">int</FONT></B> <B><FONT COLOR="#0000FF">main</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
do_text_in ();
|
|
do_xml_in ();
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> 0;
|
|
}
|
|
|
|
<I><FONT COLOR="#B22222">// end of tutorial_pba_9.cpp
|
|
</FONT></I>
|
|
</PRE>
|
|
</div><br></div>
|
|
|
|
</p>
|
|
|
|
<!--div style="background-color: #ccc; padding: 4px 2px; border: 1px" -->
|
|
<!--img src="images/c++-source-code.png" height="20pt" style="float:left" /-->
|
|
<div>
|
|
<a href="#top" class="button" >To top</a>
|
|
<!--div id="_cpp" ></div--><br>
|
|
</div>
|
|
|
|
|
|
<!------------------------------------------------------------->
|
|
<h3><a name="Samples:6"></a>Using PBA serialization associated with on-the-fly (de)compressed file streams</h3>
|
|
|
|
<p>
|
|
The <tt class="fs">tutorial_pba_10.cpp</tt> program
|
|
illustrates how to serialize, then deserialize, a class from a PBA associated
|
|
to a GZIP compressed file stream, thanks to a technique
|
|
provided by the Boost/Iostreams library. The class contains a large
|
|
STL vector of double precision floating point numbers with arbitrary values:
|
|
</p>
|
|
|
|
<div style="background-color: #ccc; padding: 4px 2px; border: 1px" >
|
|
<img src="images/c++-source-code.png" height="20pt" style="float:left" /> The <tt class="fs">tutorial_pba_10.cpp</tt> source code <a href="./code/tutorial_pba_10.cpp" class="button" >Download</a>
|
|
<a href="javascript:toggleDiv('tutorial_pba_10_cpp');" class="button" >Show/hide</a>
|
|
<div id="tutorial_pba_10_cpp" ><PRE>
|
|
<I><FONT COLOR="#B22222">/** tutorial_pba_10.cpp
|
|
*
|
|
* (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
|
|
*
|
|
* Use, modification and distribution is subject to 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)
|
|
*
|
|
*/</FONT></I>
|
|
|
|
<I><FONT COLOR="#B22222">/**
|
|
* The intent of this program is to serve as a tutorial for
|
|
* users of the portable binary archive in the framework of
|
|
* the Boost/Serialization library.
|
|
*
|
|
* This example shows how use PBAs combined with on-the-fly
|
|
* compressed I/O streams.
|
|
*
|
|
*/</FONT></I>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><string></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><fstream></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><limits></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><vector></FONT></B>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/cstdint.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/portable_binary_oarchive.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/portable_binary_iarchive.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/iostreams/filtering_stream.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/iostreams/filter/gzip.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/serialization/access.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/serialization/vector.hpp></FONT></B>
|
|
|
|
using namespace std;
|
|
|
|
<B><FONT COLOR="#228B22">class</FONT></B> data_type
|
|
{
|
|
<B><FONT COLOR="#228B22">private</FONT></B>:
|
|
<B><FONT COLOR="#228B22">friend</FONT></B> <B><FONT COLOR="#228B22">class</FONT></B> boost::serialization::access;
|
|
<B><FONT COLOR="#228B22">template</FONT></B><<B><FONT COLOR="#228B22">class</FONT></B> Archive>
|
|
<B><FONT COLOR="#228B22">void</FONT></B> serialize (Archive & ar, <B><FONT COLOR="#228B22">const</FONT></B> <B><FONT COLOR="#228B22">unsigned</FONT></B> <B><FONT COLOR="#228B22">int</FONT></B> version);
|
|
<B><FONT COLOR="#228B22">public</FONT></B>:
|
|
<B><FONT COLOR="#228B22">void</FONT></B> print (ostream & out, <B><FONT COLOR="#228B22">const</FONT></B> string & title) <B><FONT COLOR="#228B22">const</FONT></B>;
|
|
<B><FONT COLOR="#228B22">public</FONT></B>:
|
|
vector<<B><FONT COLOR="#228B22">double</FONT></B>> values;
|
|
data_type ();
|
|
};
|
|
|
|
<B><FONT COLOR="#0000FF">data_type::data_type</FONT></B> () : values ()
|
|
{
|
|
<B><FONT COLOR="#A020F0">return</FONT></B>;
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">void</FONT></B> <B><FONT COLOR="#0000FF">data_type::print</FONT></B> (ostream & out, <B><FONT COLOR="#228B22">const</FONT></B> string & title) <B><FONT COLOR="#228B22">const</FONT></B>
|
|
{
|
|
out << endl;
|
|
out << title << <B><FONT COLOR="#BC8F8F">" :"</FONT></B> << endl;
|
|
<B><FONT COLOR="#A020F0">for</FONT></B> (<B><FONT COLOR="#228B22">int</FONT></B> i = 0; i < <B><FONT COLOR="#A020F0">this</FONT></B>->values.size (); ++i)
|
|
{
|
|
out.precision (16);
|
|
out.width (18);
|
|
out << <B><FONT COLOR="#A020F0">this</FONT></B>->values [i] << <B><FONT COLOR="#BC8F8F">' '</FONT></B> ;
|
|
<B><FONT COLOR="#A020F0">if</FONT></B> ((i%4) == 3) clog << endl;
|
|
}
|
|
out << endl;
|
|
<B><FONT COLOR="#A020F0">return</FONT></B>;
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">template</FONT></B><<B><FONT COLOR="#228B22">class</FONT></B> Archive>
|
|
<B><FONT COLOR="#228B22">void</FONT></B> <B><FONT COLOR="#0000FF">data_type::serialize</FONT></B> (Archive & ar, <B><FONT COLOR="#228B22">const</FONT></B> <B><FONT COLOR="#228B22">unsigned</FONT></B> <B><FONT COLOR="#228B22">int</FONT></B> version)
|
|
{
|
|
ar & values;
|
|
<B><FONT COLOR="#A020F0">return</FONT></B>;
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">void</FONT></B> <B><FONT COLOR="#0000FF">do_gzipped_out</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
<I><FONT COLOR="#B22222">// The name for the output data file :
|
|
</FONT></I> string filename = <B><FONT COLOR="#BC8F8F">"pba_10.data.gz"</FONT></B>;
|
|
|
|
<I><FONT COLOR="#B22222">// A data structure to be stored :
|
|
</FONT></I> data_type my_data;
|
|
|
|
<I><FONT COLOR="#B22222">// Fill the vector with arbitrary (possibly non-finite) values :
|
|
</FONT></I> size_t dim = 1000;
|
|
my_data.values.reserve (dim);
|
|
<B><FONT COLOR="#A020F0">for</FONT></B> (<B><FONT COLOR="#228B22">int</FONT></B> i = 0; i < dim; ++i)
|
|
{
|
|
<B><FONT COLOR="#228B22">double</FONT></B> val = (i + 1) * (1.0 + 3 * numeric_limits<<B><FONT COLOR="#228B22">double</FONT></B>>::epsilon ());
|
|
<B><FONT COLOR="#A020F0">if</FONT></B> (i == 4) val = numeric_limits<<B><FONT COLOR="#228B22">double</FONT></B>>::quiet_NaN ();
|
|
<B><FONT COLOR="#A020F0">if</FONT></B> (i == 23) val = numeric_limits<<B><FONT COLOR="#228B22">double</FONT></B>>::infinity ();
|
|
<B><FONT COLOR="#A020F0">if</FONT></B> (i == 73) val = -numeric_limits<<B><FONT COLOR="#228B22">double</FONT></B>>::infinity ();
|
|
<B><FONT COLOR="#A020F0">if</FONT></B> (i == 90) val = 0.0;
|
|
my_data.values.push_back (val);
|
|
}
|
|
|
|
<I><FONT COLOR="#B22222">// Print:
|
|
</FONT></I> my_data.print (clog, <B><FONT COLOR="#BC8F8F">"Stored data"</FONT></B>);
|
|
|
|
<I><FONT COLOR="#B22222">// Create an output filtering stream :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::iostreams::filtering_ostream zout;
|
|
zout.push (boost::iostreams::gzip_compressor ());
|
|
|
|
<I><FONT COLOR="#B22222">// Open an output file stream in binary mode :
|
|
</FONT></I> ofstream fout (filename.c_str (), ios_base::binary);
|
|
zout.push (fout);
|
|
|
|
<I><FONT COLOR="#B22222">// Save to PBA :
|
|
</FONT></I> {
|
|
<I><FONT COLOR="#B22222">// Create an output portable binary archive attached to the output file :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::portable_binary_oarchive opba (zout);
|
|
|
|
<I><FONT COLOR="#B22222">// Store (serializing) the data :
|
|
</FONT></I> opba & my_data;
|
|
}
|
|
|
|
<I><FONT COLOR="#B22222">// Clean termination of the streams :
|
|
</FONT></I> zout.flush ();
|
|
zout.reset ();
|
|
|
|
<B><FONT COLOR="#A020F0">return</FONT></B>;
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">void</FONT></B> <B><FONT COLOR="#0000FF">do_gzipped_in</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
<I><FONT COLOR="#B22222">// The name for the input data file :
|
|
</FONT></I> string filename = <B><FONT COLOR="#BC8F8F">"pba_10.data.gz"</FONT></B>;
|
|
|
|
<I><FONT COLOR="#B22222">// A data structure to be loaded :
|
|
</FONT></I> data_type my_data;
|
|
|
|
<I><FONT COLOR="#B22222">// Create an input filtering stream :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::iostreams::filtering_istream zin;
|
|
zin.push (boost::iostreams::gzip_decompressor ());
|
|
|
|
<I><FONT COLOR="#B22222">// Open an input file stream in binary mode :
|
|
</FONT></I> ifstream fin (filename.c_str (), ios_base::binary);
|
|
zin.push (fin);
|
|
|
|
<I><FONT COLOR="#B22222">// Load from PBA :
|
|
</FONT></I> {
|
|
<I><FONT COLOR="#B22222">// Create an input portable binary archive attached to the input file :
|
|
</FONT></I> <B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::portable_binary_iarchive ipba (zin);
|
|
|
|
<I><FONT COLOR="#B22222">// Load (deserializing) the data :
|
|
</FONT></I> ipba & my_data;
|
|
}
|
|
|
|
<I><FONT COLOR="#B22222">// Print:
|
|
</FONT></I> my_data.print (clog, <B><FONT COLOR="#BC8F8F">"Loaded data"</FONT></B>);
|
|
|
|
<B><FONT COLOR="#A020F0">return</FONT></B>;
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">int</FONT></B> <B><FONT COLOR="#0000FF">main</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
do_gzipped_out ();
|
|
do_gzipped_in ();
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> 0;
|
|
}
|
|
|
|
<I><FONT COLOR="#B22222">// end of tutorial_pba_10.cpp
|
|
</FONT></I>
|
|
</PRE>
|
|
</div><br></div>
|
|
|
|
|
|
<p>The resulting compressed <tt class="fs">pba_10.data.gz</tt> file contains 1,574 bytes.
|
|
This has to be compared with the size of the plain (uncompressed)
|
|
binary archive which equals 9,001 bytes:
|
|
|
|
<pre class="byte">127 1 9 0 0 2 232 3 0 8 3 0 0 0 0 0
|
|
240 63 8 3 0 0 0 0 0 0 64 8 4 0 0 0
|
|
0 0 8 64 8 3 0 0 0 0 0 16 64 8 255 255
|
|
255 255 255 255 255 127 8 4 0 0 0 0 0 24 64 8
|
|
...
|
|
</pre>
|
|
|
|
which can be interpreted as :
|
|
<ul>
|
|
<li> 3 bytes for the usual archive header : <tt class="byte">127 1
|
|
9</tt>,
|
|
<li> 2 <i>zero-optimized</i> bytes to store the class ID
|
|
and the class version :<tt class="byte">0 0</tt>,
|
|
<li> 3 bytes to store the size of the vector (1000) using the PBA
|
|
representation of integers (<tt class="byte">2 232 3</tt>),
|
|
<li> 1 <i>zero-optimized</i> byte to store the class version of the
|
|
objects stored in the STL vector (here
|
|
the primitive <tt class="code">double</tt> type) : <tt class="byte">0</tt>,
|
|
<li> 999 non-zero double precision floating point values (including non-finite values) each using 9 bytes (1 byte for
|
|
the <i>size</i> and 8 bytes for the <i>content</i>) : <tt class="byte">8 ? ? ? ? ?
|
|
? ? ?</tt>,
|
|
<li> 1 zero floating point value that uses only one <i>zero-optimized</i> byte : <tt class="byte">0</tt>.
|
|
</ul>
|
|
Thus one here achieves a very interesting <i>compression</i> level.
|
|
</p>
|
|
<p>
|
|
It is also possible to use BZIP2 in a similar fashion
|
|
(using ressources from the <tt class="fs">boost/iostreams/filter/bzip2.hpp</tt> header
|
|
in place of <tt class="fs">boost/iostreams/filter/gzip.hpp</tt>).
|
|
</p>
|
|
|
|
<!--div style="background-color: #ccc; padding: 4px 2px; border: 1px" -->
|
|
<!--img src="images/c++-source-code.png" height="20pt" style="float:left" /-->
|
|
<div>
|
|
<a href="#top" class="button" >To top</a>
|
|
<!--div id="_cpp" ></div--><br>
|
|
</div>
|
|
|
|
<!------------------------------------------------------------->
|
|
<h3><a name="Samples:7"></a>A simple PBA versus text archive benchmark test</h3>
|
|
|
|
<p>
|
|
The <tt class="fs">tutorial_pba_11.cpp</tt> program
|
|
runs a benchmark test in the aim to compare the relative fastness of PBA and text archives
|
|
both for read and write operations. It stores then loads a vector of many (10<sup>7</sup>)
|
|
random <tt class="code">double</tt> values and prints the associated (de)serialization time for both kinds of archives:
|
|
</p>
|
|
|
|
<div style="background-color: #ccc; padding: 4px 2px; border: 1px" >
|
|
<img src="images/c++-source-code.png" height="20pt" style="float:left" /> The <tt class="fs">tutorial_pba_11.cpp</tt> source code <a href="./code/tutorial_pba_11.cpp" class="button" >Download</a>
|
|
<a href="javascript:toggleDiv('tutorial_pba_11_cpp');" class="button" >Show/hide</a>
|
|
<div id="tutorial_pba_11_cpp" ><PRE>
|
|
<I><FONT COLOR="#B22222">/** tutorial_pba_11.cpp
|
|
*
|
|
* (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
|
|
*
|
|
* Use, modification and distribution is subject to 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)
|
|
*
|
|
*/</FONT></I>
|
|
|
|
<I><FONT COLOR="#B22222">/**
|
|
* The intent of this program is to serve as a tutorial for
|
|
* users of the portable binary archive in the framework of
|
|
* the Boost/Serialization library.
|
|
*
|
|
* This example program compares the times needed to serialize
|
|
* and deserialize some large amount of data using PBA and
|
|
* text archives.
|
|
*
|
|
*/</FONT></I>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><string></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><fstream></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><vector></FONT></B>
|
|
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/portable_binary_oarchive.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/portable_binary_iarchive.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/text_oarchive.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/archive/text_iarchive.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/serialization/access.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/serialization/vector.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/random/mersenne_twister.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/random/uniform_real_distribution.hpp></FONT></B>
|
|
#<B><FONT COLOR="#5F9EA0">include</FONT></B> <B><FONT COLOR="#BC8F8F"><boost/timer.hpp></FONT></B>
|
|
|
|
using namespace std;
|
|
|
|
<B><FONT COLOR="#228B22">class</FONT></B> data_type
|
|
{
|
|
<B><FONT COLOR="#228B22">private</FONT></B>:
|
|
<B><FONT COLOR="#228B22">friend</FONT></B> <B><FONT COLOR="#228B22">class</FONT></B> boost::serialization::access;
|
|
<B><FONT COLOR="#228B22">template</FONT></B><<B><FONT COLOR="#228B22">class</FONT></B> Archive>
|
|
<B><FONT COLOR="#228B22">void</FONT></B> serialize (Archive & ar, <B><FONT COLOR="#228B22">const</FONT></B> <B><FONT COLOR="#228B22">unsigned</FONT></B> <B><FONT COLOR="#228B22">int</FONT></B> version);
|
|
<B><FONT COLOR="#228B22">public</FONT></B>:
|
|
<B><FONT COLOR="#228B22">void</FONT></B> print (ostream & out, <B><FONT COLOR="#228B22">const</FONT></B> string & title) <B><FONT COLOR="#228B22">const</FONT></B>;
|
|
<B><FONT COLOR="#228B22">public</FONT></B>:
|
|
vector<<B><FONT COLOR="#228B22">double</FONT></B>> values;
|
|
data_type ();
|
|
};
|
|
|
|
<B><FONT COLOR="#0000FF">data_type::data_type</FONT></B> () : values ()
|
|
{
|
|
<B><FONT COLOR="#A020F0">return</FONT></B>;
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">void</FONT></B> <B><FONT COLOR="#0000FF">data_type::print</FONT></B> (ostream & out, <B><FONT COLOR="#228B22">const</FONT></B> string & title) <B><FONT COLOR="#228B22">const</FONT></B>
|
|
{
|
|
out << endl;
|
|
out << title << <B><FONT COLOR="#BC8F8F">" :"</FONT></B> << endl;
|
|
<B><FONT COLOR="#228B22">bool</FONT></B> skip = false;
|
|
<B><FONT COLOR="#A020F0">for</FONT></B> (<B><FONT COLOR="#228B22">int</FONT></B> i = 0; i < <B><FONT COLOR="#A020F0">this</FONT></B>->values.size (); ++i)
|
|
{
|
|
<B><FONT COLOR="#A020F0">if</FONT></B> ((i >= 12) && (i < (<B><FONT COLOR="#228B22">int</FONT></B>) <B><FONT COLOR="#A020F0">this</FONT></B>->values.size () - 8))
|
|
{
|
|
<B><FONT COLOR="#A020F0">if</FONT></B> (! skip) out << <B><FONT COLOR="#BC8F8F">" ..."</FONT></B> << endl;
|
|
skip = true;
|
|
<B><FONT COLOR="#A020F0">continue</FONT></B>;
|
|
}
|
|
out.precision (16);
|
|
out.width (18);
|
|
out << <B><FONT COLOR="#A020F0">this</FONT></B>->values [i] << <B><FONT COLOR="#BC8F8F">' '</FONT></B> ;
|
|
<B><FONT COLOR="#A020F0">if</FONT></B> ((i%4) == 3) clog << endl;
|
|
}
|
|
out << endl;
|
|
<B><FONT COLOR="#A020F0">return</FONT></B>;
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">template</FONT></B><<B><FONT COLOR="#228B22">class</FONT></B> Archive>
|
|
<B><FONT COLOR="#228B22">void</FONT></B> <B><FONT COLOR="#0000FF">data_type::serialize</FONT></B> (Archive & ar, <B><FONT COLOR="#228B22">const</FONT></B> <B><FONT COLOR="#228B22">unsigned</FONT></B> <B><FONT COLOR="#228B22">int</FONT></B> version)
|
|
{
|
|
ar & values;
|
|
<B><FONT COLOR="#A020F0">return</FONT></B>;
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">double</FONT></B> <B><FONT COLOR="#0000FF">do_pba_out</FONT></B> (<B><FONT COLOR="#228B22">const</FONT></B> data_type & a_data)
|
|
{
|
|
string filename = <B><FONT COLOR="#BC8F8F">"pba_11.data"</FONT></B>;
|
|
ofstream fout (filename.c_str (), ios_base::binary);
|
|
<B><FONT COLOR="#5F9EA0">boost</FONT></B>::timer io_timer;
|
|
{
|
|
<B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::portable_binary_oarchive opba (fout);
|
|
opba & a_data;
|
|
}
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> io_timer.elapsed ();
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">double</FONT></B> <B><FONT COLOR="#0000FF">do_pba_in</FONT></B> (data_type & a_data)
|
|
{
|
|
string filename = <B><FONT COLOR="#BC8F8F">"pba_11.data"</FONT></B>;
|
|
ifstream fin (filename.c_str (), ios_base::binary);
|
|
<B><FONT COLOR="#5F9EA0">boost</FONT></B>::timer io_timer;
|
|
{
|
|
<B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::portable_binary_iarchive ipba (fin);
|
|
ipba & a_data;
|
|
}
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> io_timer.elapsed ();
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">double</FONT></B> <B><FONT COLOR="#0000FF">do_text_out</FONT></B> (<B><FONT COLOR="#228B22">const</FONT></B> data_type & a_data)
|
|
{
|
|
string filename = <B><FONT COLOR="#BC8F8F">"pba_11.txt"</FONT></B>;
|
|
ofstream fout (filename.c_str ());
|
|
<B><FONT COLOR="#5F9EA0">boost</FONT></B>::timer io_timer;
|
|
{
|
|
<B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::text_oarchive ota (fout);
|
|
ota & a_data;
|
|
}
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> io_timer.elapsed ();
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">double</FONT></B> <B><FONT COLOR="#0000FF">do_text_in</FONT></B> (data_type & a_data)
|
|
{
|
|
string filename = <B><FONT COLOR="#BC8F8F">"pba_11.txt"</FONT></B>;
|
|
ifstream fin (filename.c_str ());
|
|
<B><FONT COLOR="#5F9EA0">boost</FONT></B>::timer io_timer;
|
|
{
|
|
<B><FONT COLOR="#5F9EA0">boost</FONT></B>::archive::text_iarchive ita (fin);
|
|
ita & a_data;
|
|
}
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> io_timer.elapsed ();
|
|
}
|
|
|
|
<B><FONT COLOR="#228B22">int</FONT></B> <B><FONT COLOR="#0000FF">main</FONT></B> (<B><FONT COLOR="#228B22">void</FONT></B>)
|
|
{
|
|
<B><FONT COLOR="#228B22">double</FONT></B> elapsed_time_pba_out;
|
|
<B><FONT COLOR="#228B22">double</FONT></B> elapsed_time_text_out;
|
|
<B><FONT COLOR="#228B22">double</FONT></B> elapsed_time_pba_in;
|
|
<B><FONT COLOR="#228B22">double</FONT></B> elapsed_time_text_in;
|
|
data_type my_data; <I><FONT COLOR="#B22222">// A data structure to be stored then loaded.
|
|
</FONT></I>
|
|
{
|
|
<I><FONT COLOR="#B22222">// Fill the vector with random values :
|
|
</FONT></I> size_t dim = 10000000;
|
|
my_data.values.reserve (dim);
|
|
<B><FONT COLOR="#5F9EA0">boost</FONT></B>::random::mt19937 rng;
|
|
<B><FONT COLOR="#5F9EA0">boost</FONT></B>::random::uniform_real_distribution<> flat (0.0, 100.0);
|
|
<B><FONT COLOR="#A020F0">for</FONT></B> (<B><FONT COLOR="#228B22">int</FONT></B> i = 0; i < dim; ++i)
|
|
{
|
|
<B><FONT COLOR="#228B22">double</FONT></B> val = flat (rng);
|
|
my_data.values.push_back (val);
|
|
}
|
|
my_data.print (clog, <B><FONT COLOR="#BC8F8F">"Stored data in PBA and text archive"</FONT></B>);
|
|
}
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Store in PBA :
|
|
</FONT></I> elapsed_time_pba_out = do_pba_out (my_data);
|
|
}
|
|
|
|
{
|
|
<I><FONT COLOR="#B22222">// Store in text archive :
|
|
</FONT></I> elapsed_time_text_out = do_text_out (my_data);
|
|
}
|
|
|
|
{
|
|
my_data.values.clear ();
|
|
<I><FONT COLOR="#B22222">// Load from PBA :
|
|
</FONT></I> elapsed_time_pba_in = do_pba_in (my_data);
|
|
my_data.print (clog, <B><FONT COLOR="#BC8F8F">"Loaded data from PBA"</FONT></B>);
|
|
}
|
|
|
|
{
|
|
my_data.values.clear ();
|
|
<I><FONT COLOR="#B22222">// Load from text archive :
|
|
</FONT></I> elapsed_time_text_in = do_text_in (my_data);
|
|
my_data.print (clog, <B><FONT COLOR="#BC8F8F">"Loaded data from text archive"</FONT></B>);
|
|
}
|
|
|
|
clog << <B><FONT COLOR="#BC8F8F">"PBA store I/O elapsed time : "</FONT></B> << elapsed_time_pba_out << <B><FONT COLOR="#BC8F8F">" (second)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">"Text store I/O elapsed time : "</FONT></B> << elapsed_time_text_out << <B><FONT COLOR="#BC8F8F">" (second)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">"PBA load I/O elapsed time : "</FONT></B> << elapsed_time_pba_in << <B><FONT COLOR="#BC8F8F">" (second)"</FONT></B> << endl;
|
|
clog << <B><FONT COLOR="#BC8F8F">"Text load I/O elapsed time : "</FONT></B> << elapsed_time_text_in << <B><FONT COLOR="#BC8F8F">" (second)"</FONT></B> << endl;
|
|
|
|
<B><FONT COLOR="#A020F0">return</FONT></B> 0;
|
|
}
|
|
|
|
<I><FONT COLOR="#B22222">// end of tutorial_pba_11.cpp
|
|
</FONT></I>
|
|
</PRE>
|
|
</div><br></div>
|
|
|
|
|
|
<p>On a 1.60 GHz processor running gcc 4.5.2 on Linux 2.6.38, the result is the following:
|
|
<pre>PBA store I/O elapsed time : 1.86 (second)
|
|
Text store I/O elapsed time : 22.66 (second)
|
|
PBA load I/O elapsed time : 1.53 (second)
|
|
Text load I/O elapsed time : 19.71 (second)
|
|
</pre>
|
|
It this simple case, the use of portable binary archives is faster by at least a factor 10
|
|
compared to the traditional Boost text archives. This is a
|
|
significant saving in time. These performances are highly desirable in the typical framework
|
|
of scientific/computing activities where large amounts of data are accessed through files.
|
|
The PBA concept is thus a valuable candidate for such applications.
|
|
</p>
|
|
|
|
<p>
|
|
One can also consider the sizes of the resulting archive files:
|
|
<ul>
|
|
<li><tt class="fs">pba_11.data</tt> (PBA) : 90,000,010 bytes
|
|
<li><tt class="fs">pba_11.txt</tt> (text archive) : 189,000,040 bytes
|
|
</ul>
|
|
The PBA allows to save a typical factor 2 in storage space compared to text archive.
|
|
This is another strong argument for using PBA.
|
|
</p>
|
|
|
|
<!--div style="background-color: #ccc; padding: 4px 2px; border: 1px" -->
|
|
<!--img src="images/c++-source-code.png" height="20pt" style="float:left" /-->
|
|
<div>
|
|
<a href="#top" class="button" >To top</a>
|
|
<!--div id="_cpp" ></div--><br>
|
|
</div>
|
|
|
|
|
|
<!--------------------------------------------------------------------------------->
|
|
<hr>
|
|
<p>Revised 2011-11-07
|
|
<p><i>© Copyright <a href="mailto:mauger@lpccaen.in2p3.fr">François Mauger</a>,
|
|
<a href="mailto:Christian.Pfligersdorffer@eos.info">Christian Pfligersdorffer</a> 2011.<br>
|
|
Distributed under the Boost Software License, Version 1.0.<br>
|
|
(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
</i>
|
|
</p>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
<!-- end of tutorial.html -->
|