From 14f3f5ea77d45c39a67641b9e706b9cf11598d98 Mon Sep 17 00:00:00 2001 From: Robert Ramey Date: Mon, 15 Feb 2016 10:51:46 -0800 Subject: [PATCH] added files particular to portable_archive --- doc/tutorial/change_log.txt | 38 + doc/tutorial/code/tutorial_pba_0.cpp | 56 + doc/tutorial/code/tutorial_pba_1.cpp | 68 + doc/tutorial/code/tutorial_pba_10.cpp | 162 ++ doc/tutorial/code/tutorial_pba_10b.cpp | 198 ++ doc/tutorial/code/tutorial_pba_11.cpp | 187 ++ doc/tutorial/code/tutorial_pba_2.cpp | 105 + doc/tutorial/code/tutorial_pba_3.cpp | 70 + doc/tutorial/code/tutorial_pba_4.cpp | 105 + doc/tutorial/code/tutorial_pba_5.cpp | 111 + doc/tutorial/code/tutorial_pba_6.cpp | 112 + doc/tutorial/code/tutorial_pba_7.cpp | 54 + doc/tutorial/code/tutorial_pba_8.cpp | 118 + doc/tutorial/code/tutorial_pba_9.cpp | 134 + doc/tutorial/images/boost.png | Bin 0 -> 6308 bytes doc/tutorial/images/c++-source-code.png | Bin 0 -> 1296 bytes doc/tutorial/release_notes.txt | 36 + doc/tutorial/scripts/jquery-1.4.min.js | 151 ++ doc/tutorial/styles/boost.css | 39 + doc/tutorial/styles/style.css | 92 + doc/tutorial/tutorial.html | 2348 +++++++++++++++++ include/boost/archive/portable_archive.hpp | 35 + .../archive/portable_archive_exception.hpp | 93 + include/boost/archive/portable_iarchive.hpp | 487 ++++ include/boost/archive/portable_oarchive.hpp | 470 ++++ test/polymorphic_portable_archive.hpp | 35 + test/portable_archive.hpp | 25 + 27 files changed, 5329 insertions(+) create mode 100755 doc/tutorial/change_log.txt create mode 100755 doc/tutorial/code/tutorial_pba_0.cpp create mode 100755 doc/tutorial/code/tutorial_pba_1.cpp create mode 100755 doc/tutorial/code/tutorial_pba_10.cpp create mode 100755 doc/tutorial/code/tutorial_pba_10b.cpp create mode 100755 doc/tutorial/code/tutorial_pba_11.cpp create mode 100755 doc/tutorial/code/tutorial_pba_2.cpp create mode 100755 doc/tutorial/code/tutorial_pba_3.cpp create mode 100755 doc/tutorial/code/tutorial_pba_4.cpp create mode 100755 doc/tutorial/code/tutorial_pba_5.cpp create mode 100755 doc/tutorial/code/tutorial_pba_6.cpp create mode 100755 doc/tutorial/code/tutorial_pba_7.cpp create mode 100755 doc/tutorial/code/tutorial_pba_8.cpp create mode 100755 doc/tutorial/code/tutorial_pba_9.cpp create mode 100755 doc/tutorial/images/boost.png create mode 100755 doc/tutorial/images/c++-source-code.png create mode 100755 doc/tutorial/release_notes.txt create mode 100755 doc/tutorial/scripts/jquery-1.4.min.js create mode 100755 doc/tutorial/styles/boost.css create mode 100755 doc/tutorial/styles/style.css create mode 100755 doc/tutorial/tutorial.html create mode 100755 include/boost/archive/portable_archive.hpp create mode 100755 include/boost/archive/portable_archive_exception.hpp create mode 100755 include/boost/archive/portable_iarchive.hpp create mode 100755 include/boost/archive/portable_oarchive.hpp create mode 100755 test/polymorphic_portable_archive.hpp create mode 100644 test/portable_archive.hpp diff --git a/doc/tutorial/change_log.txt b/doc/tutorial/change_log.txt new file mode 100755 index 00000000..e8eba0c1 --- /dev/null +++ b/doc/tutorial/change_log.txt @@ -0,0 +1,38 @@ +IMPORTANT: + +This is the last release from me as EOS employee. I plan to contribute all of this +work to the official boost libraries distribution and will continue to support users. +Francois Mauger joined me recently and already added a valuable tutorial for you! + +Changelog: + +07.11.2015 5.1 Small fix to get it running up to 1.59. + +26.06.2012 5.0 Ported to boost versions up to 1.49. + Added support for wstring, added tutorial by Francois Mauger. + +01.04.2011 4.2 Ported to boost versions up to 1.46.1. + Allow serialization of inf and nan values. + +17.12.2009 4.1 Ported to boost versions up to 1.41. + + 4.0 Changes in inheritance make arrays work. + +13.02.2009 3.1 Shared pointer serialization capabilities added + Ported to recent boost versions (up to 1.38) + +25.09.2008 3.0 Refactored, fixed and ported to recent boost versions + Archives are now named eos::portable_[io]archive + +17.09.2008 2.1 Improved floating point handling and error detection. + Extracted the exception class into an extra file. + +28.04.2008 2.0 Major Bugfix resolving negative number collision! + +28.11.2007 1.1 Small Bugfix in portable_binary_archive_exception class: + throwing specifiers did not match base class declaration + +12.11.2007 1.0 Initial Release to boost-users! + +Christian Pfligersdorffer +christian.pfligersdorffer@gmx.at \ No newline at end of file diff --git a/doc/tutorial/code/tutorial_pba_0.cpp b/doc/tutorial/code/tutorial_pba_0.cpp new file mode 100755 index 00000000..aaec78c7 --- /dev/null +++ b/doc/tutorial/code/tutorial_pba_0.cpp @@ -0,0 +1,56 @@ +/** 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) + * + */ + +/** + * 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. + * + */ + +#include +#include + +#include +#include + +int main (void) +{ + // The name for the example data file : + std::string filename = "pba_0.data"; + + // Some variables of various primitive types : + bool b = true; + char c = 'B'; + uint32_t answer = 42; + float computing_time = 7.5e6; + double e = 2.71828182845905; + std::string slogan = "DON'T PANIC"; + + // Open an output file stream in binary mode : + std::ofstream fout (filename.c_str (), std::ios_base::binary); + + { + // Create an output portable binary archive attached to the output file : + boost::archive::portable_binary_oarchive opba (fout); + + // Store (serializing) variables : + opba & b & c & answer & computing_time & e & slogan; + } + + return 0; +} + +// end of tutorial_pba_0.cpp diff --git a/doc/tutorial/code/tutorial_pba_1.cpp b/doc/tutorial/code/tutorial_pba_1.cpp new file mode 100755 index 00000000..1b5fb8fc --- /dev/null +++ b/doc/tutorial/code/tutorial_pba_1.cpp @@ -0,0 +1,68 @@ +/** 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) + * + */ + +/** + * 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. + * + */ + +#include +#include +#include + +#include +#include + +int main (void) +{ + using namespace std; + + // The name for the example data file : + string filename = "pba_0.data"; + + // Some variables of various types : + bool b; + char c; + uint32_t answer; + float computing_time; + double e; + string slogan; + + // Open an input file stream in binary mode : + ifstream fin (filename.c_str (), ios_base::binary); + + { + // Create an input portable binary archive attached to the input file : + boost::archive::portable_binary_iarchive ipba (fin); + + // Loading (de-serializing) variables using the same + // order than for serialization (see tutorial_pba_0.cpp) : + ipba & b & c & answer & computing_time & e & slogan; + } + + cout.precision (15); + cout << "Variable 'b' is : " << b << " " << "(bool)" << endl; + cout << "Variable 'c' is : '" << c << "' " << " " << "(char)" << endl; + cout << "Variable 'answer' is : " << answer << " " << "(unsigned 32-bit integer)" << endl; + cout << "Variable 'computing_time' is : " << computing_time << " " << "(single precision 32-bit float)" << endl; + cout << "Variable 'e' is : " << e << " " << "(double precision 64-bit float)" << endl; + cout << "Variable 'slogan' is : \"" << slogan << "\" " << "(std::string)" << endl; + + return 0; +} + +// end of tutorial_pba_1.cpp diff --git a/doc/tutorial/code/tutorial_pba_10.cpp b/doc/tutorial/code/tutorial_pba_10.cpp new file mode 100755 index 00000000..a2d44391 --- /dev/null +++ b/doc/tutorial/code/tutorial_pba_10.cpp @@ -0,0 +1,162 @@ +/** 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) + * + */ + +/** + * 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. + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +class data_type +{ +private: + friend class boost::serialization::access; + template + void serialize (Archive & ar, const unsigned int version); +public: + void print (ostream & out, const string & title) const; +public: + vector values; + data_type (); +}; + +data_type::data_type () : values () +{ + return; +} + +void data_type::print (ostream & out, const string & title) const +{ + out << endl; + out << title << " :" << endl; + for (int i = 0; i < this->values.size (); ++i) + { + out.precision (16); + out.width (18); + out << this->values [i] << ' ' ; + if ((i%4) == 3) clog << endl; + } + out << endl; + return; +} + +template +void data_type::serialize (Archive & ar, const unsigned int version) +{ + ar & values; + return; +} + +void do_gzipped_out (void) +{ + // The name for the output data file : + string filename = "pba_10.data.gz"; + + // A data structure to be stored : + data_type my_data; + + // Fill the vector with arbitrary (possibly non-finite) values : + size_t dim = 1000; + my_data.values.reserve (dim); + for (int i = 0; i < dim; ++i) + { + double val = (i + 1) * (1.0 + 3 * numeric_limits::epsilon ()); + if (i == 4) val = numeric_limits::quiet_NaN (); + if (i == 23) val = numeric_limits::infinity (); + if (i == 73) val = -numeric_limits::infinity (); + if (i == 90) val = 0.0; + my_data.values.push_back (val); + } + + // Print: + my_data.print (clog, "Stored data"); + + // Create an output filtering stream : + boost::iostreams::filtering_ostream zout; + zout.push (boost::iostreams::gzip_compressor ()); + + // Open an output file stream in binary mode : + ofstream fout (filename.c_str (), ios_base::binary); + zout.push (fout); + + // Save to PBA : + { + // Create an output portable binary archive attached to the output file : + boost::archive::portable_binary_oarchive opba (zout); + + // Store (serializing) the data : + opba & my_data; + } + + // Clean termination of the streams : + zout.flush (); + zout.reset (); + + return; +} + +void do_gzipped_in (void) +{ + // The name for the input data file : + string filename = "pba_10.data.gz"; + + // A data structure to be loaded : + data_type my_data; + + // Create an input filtering stream : + boost::iostreams::filtering_istream zin; + zin.push (boost::iostreams::gzip_decompressor ()); + + // Open an input file stream in binary mode : + ifstream fin (filename.c_str (), ios_base::binary); + zin.push (fin); + + // Load from PBA : + { + // Create an input portable binary archive attached to the input file : + boost::archive::portable_binary_iarchive ipba (zin); + + // Load (deserializing) the data : + ipba & my_data; + } + + // Print: + my_data.print (clog, "Loaded data"); + + return; +} + +int main (void) +{ + do_gzipped_out (); + do_gzipped_in (); + return 0; +} + +// end of tutorial_pba_10.cpp diff --git a/doc/tutorial/code/tutorial_pba_10b.cpp b/doc/tutorial/code/tutorial_pba_10b.cpp new file mode 100755 index 00000000..f1695f4d --- /dev/null +++ b/doc/tutorial/code/tutorial_pba_10b.cpp @@ -0,0 +1,198 @@ +/** tutorial_pba_10b.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) + * + */ + +/** + * 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. + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +class data_type +{ +private: + friend class boost::serialization::access; + template + void serialize (Archive & ar, const unsigned int version); +public: + void print (ostream & out, const string & title) const; +public: + vector values; + data_type (); +}; + +//BOOST_CLASS_VERSION(data_type, 7) + +data_type::data_type () : values () +{ + return; +} + +void data_type::print (ostream & out, const string & title) const +{ + out << endl; + out << title << " :" << endl; + for (int i = 0; i < this->values.size (); ++i) + { + out.precision (16); + out.width (18); + out << this->values [i] << ' ' ; + if ((i%4) == 3) clog << endl; + } + out << endl; + return; +} + +template +void data_type::serialize (Archive & ar, const unsigned int version) +{ + ar & BOOST_SERIALIZATION_NVP (values); + return; +} + +class data_type2 +{ +private: + friend class boost::serialization::access; + template + void serialize (Archive & ar, const unsigned int version); +public: + double value; + data_type2 (); +}; + +BOOST_CLASS_VERSION(data_type2, 99) + +data_type2::data_type2 () : value (666.666) +{ + return; +} + +template +void data_type2::serialize (Archive & ar, const unsigned int version) +{ + ar & BOOST_SERIALIZATION_NVP (value); + return; +} + +class data_type3 +{ +private: + friend class boost::serialization::access; + template + void serialize (Archive & ar, const unsigned int version); +public: + vector values; + data_type3 (); +}; + +BOOST_CLASS_VERSION(data_type3, 33) + +data_type3::data_type3 () +{ + { + data_type2 d; + d.value = 6.66; + values.push_back (d); + } + { + data_type2 d; + d.value = 66.66; + values.push_back (d); + } + { + data_type2 d; + d.value = 666.66; + values.push_back (d); + } + return; +} + +template +void data_type3::serialize (Archive & ar, const unsigned int version) +{ + ar & BOOST_SERIALIZATION_NVP (values); + return; +} + +/********************/ + +void do_xml_out (void) +{ + // The name for the output data file : + string filename = "pba_10.xml"; + + // A data structure to be stored : + data_type my_data; + + // Fill the vector with arbitrary (possibly non-finite) values : + size_t dim = 6; + my_data.values.reserve (dim); + for (int i = 0; i < dim; ++i) + { + double val = (i + 1) * (1.0 + 3 * numeric_limits::epsilon ()); + if (i == 4) val = numeric_limits::quiet_NaN (); + if (i == 7) val = numeric_limits::infinity (); + if (i == 9) val = -numeric_limits::infinity (); + if (i == 13) val = 0.0; + my_data.values.push_back (val); + } + + // Print: + my_data.print (clog, "Stored data"); + + data_type2 my_data2; + data_type3 my_data3; + + // Open an output file stream in binary mode : + ofstream fout (filename.c_str ()); + + // Save to PBA : + { + // Create an output XML archive attached to the output file : + boost::archive::xml_oarchive oxa (fout); + + // Store (serializing) the data : + oxa & BOOST_SERIALIZATION_NVP(my_data); + oxa & BOOST_SERIALIZATION_NVP(my_data2); + oxa & BOOST_SERIALIZATION_NVP(my_data3); + } + + return; +} + +int main (void) +{ + do_xml_out (); + return 0; +} + +// end of tutorial_pba_10b.cpp diff --git a/doc/tutorial/code/tutorial_pba_11.cpp b/doc/tutorial/code/tutorial_pba_11.cpp new file mode 100755 index 00000000..3e606480 --- /dev/null +++ b/doc/tutorial/code/tutorial_pba_11.cpp @@ -0,0 +1,187 @@ +/** 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) + * + */ + +/** + * 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. + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +class data_type +{ +private: + friend class boost::serialization::access; + template + void serialize (Archive & ar, const unsigned int version); +public: + void print (ostream & out, const string & title) const; +public: + vector values; + data_type (); +}; + +data_type::data_type () : values () +{ + return; +} + +void data_type::print (ostream & out, const string & title) const +{ + out << endl; + out << title << " :" << endl; + bool skip = false; + for (int i = 0; i < this->values.size (); ++i) + { + if ((i >= 12) && (i < (int) this->values.size () - 8)) + { + if (! skip) out << " ..." << endl; + skip = true; + continue; + } + out.precision (16); + out.width (18); + out << this->values [i] << ' ' ; + if ((i%4) == 3) clog << endl; + } + out << endl; + return; +} + +template +void data_type::serialize (Archive & ar, const unsigned int version) +{ + ar & values; + return; +} + +double do_pba_out (const data_type & a_data) +{ + string filename = "pba_11.data"; + ofstream fout (filename.c_str (), ios_base::binary); + boost::timer io_timer; + { + boost::archive::portable_binary_oarchive opba (fout); + opba & a_data; + } + return io_timer.elapsed (); +} + +double do_pba_in (data_type & a_data) +{ + string filename = "pba_11.data"; + ifstream fin (filename.c_str (), ios_base::binary); + boost::timer io_timer; + { + boost::archive::portable_binary_iarchive ipba (fin); + ipba & a_data; + } + return io_timer.elapsed (); +} + +double do_text_out (const data_type & a_data) +{ + string filename = "pba_11.txt"; + ofstream fout (filename.c_str ()); + boost::timer io_timer; + { + boost::archive::text_oarchive ota (fout); + ota & a_data; + } + return io_timer.elapsed (); +} + +double do_text_in (data_type & a_data) +{ + string filename = "pba_11.txt"; + ifstream fin (filename.c_str ()); + boost::timer io_timer; + { + boost::archive::text_iarchive ita (fin); + ita & a_data; + } + return io_timer.elapsed (); +} + +int main (void) +{ + double elapsed_time_pba_out; + double elapsed_time_text_out; + double elapsed_time_pba_in; + double elapsed_time_text_in; + data_type my_data; // A data structure to be stored then loaded. + + { + // Fill the vector with random values : + size_t dim = 10000000; + my_data.values.reserve (dim); + boost::random::mt19937 rng; + boost::random::uniform_real_distribution<> flat (0.0, 100.0); + for (int i = 0; i < dim; ++i) + { + double val = flat (rng); + my_data.values.push_back (val); + } + my_data.print (clog, "Stored data in PBA and text archive"); + } + + { + // Store in PBA : + elapsed_time_pba_out = do_pba_out (my_data); + } + + { + // Store in text archive : + elapsed_time_text_out = do_text_out (my_data); + } + + { + my_data.values.clear (); + // Load from PBA : + elapsed_time_pba_in = do_pba_in (my_data); + my_data.print (clog, "Loaded data from PBA"); + } + + { + my_data.values.clear (); + // Load from text archive : + elapsed_time_text_in = do_text_in (my_data); + my_data.print (clog, "Loaded data from text archive"); + } + + clog << "PBA store I/O elapsed time : " << elapsed_time_pba_out << " (second)" << endl; + clog << "Text store I/O elapsed time : " << elapsed_time_text_out << " (second)" << endl; + clog << "PBA load I/O elapsed time : " << elapsed_time_pba_in << " (second)" << endl; + clog << "Text load I/O elapsed time : " << elapsed_time_text_in << " (second)" << endl; + + return 0; +} + +// end of tutorial_pba_11.cpp diff --git a/doc/tutorial/code/tutorial_pba_2.cpp b/doc/tutorial/code/tutorial_pba_2.cpp new file mode 100755 index 00000000..7f6c875b --- /dev/null +++ b/doc/tutorial/code/tutorial_pba_2.cpp @@ -0,0 +1,105 @@ +/** 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) + * + */ + +/** + * 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. + * + */ + +#include +#include +#include + +#include +#include + +int main (void) +{ + using namespace std; + + // The name for the example data file : + string filename = "pba_2.data"; + + { + // A normal single precision floating point number : + float pi = 3.14159265; + + // Single precision zeroed floating point number : + float zero = 0.0; + + // A denormalized single precision floating point number : + float tiny = 1.e-40; + + // A single precision floating point number with `+Infinity' value : + float plus_infinity = numeric_limits::infinity (); + + // A single precision floating point number with `-Infinity' value : + float minus_infinity = -numeric_limits::infinity (); + + // A single precision `Not-a-Number' (NaN): + float nan = numeric_limits::quiet_NaN (); + + // Open an output file stream in binary mode : + ofstream fout (filename.c_str (), ios_base::binary); + + { + // Create an output portable binary archive attached to the output file : + boost::archive::portable_binary_oarchive opba (fout); + + // Store (serialize) variables : + opba & pi & zero & tiny & plus_infinity & minus_infinity & nan; + } + } + + { + // Single precision floating point numbers to be loaded : + float x[6]; + + // Open an input file stream in binary mode : + ifstream fin (filename.c_str (), ios_base::binary); + + { + // Create an input portable binary archive attached to the input file : + boost::archive::portable_binary_iarchive ipba (fin); + + // Load (de-serialize) variables using the same + // order than for serialization : + for (int i = 0; i < 6; ++i) + { + ipba & x[i]; + } + } + + // Print : + for (int i = 0; i < 6; ++i) + { + cout.precision (8); + cout << "Loaded x[" << i << "] = " << x[i]; + switch (fp::fpclassify(x[i])) + { + case FP_NAN: cout << " (NaN)"; break; + case FP_INFINITE: cout << " (infinite)"; break; + case FP_SUBNORMAL: cout << " (denormalized)"; break; + case FP_NORMAL: cout << " (normalized)"; break; + } + cout << endl; + } + } + + return 0; +} + +// end of tutorial_pba_2.cpp diff --git a/doc/tutorial/code/tutorial_pba_3.cpp b/doc/tutorial/code/tutorial_pba_3.cpp new file mode 100755 index 00000000..42df3bf9 --- /dev/null +++ b/doc/tutorial/code/tutorial_pba_3.cpp @@ -0,0 +1,70 @@ +/** 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) + * + */ + +/** + * 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. + * + */ + +#include +#include +#include + +#include + +int main (void) +{ + using namespace std; + + // The name for the example data file : + string filename = "pba_3.data"; + + try + { + // An array of single precision floating numbers: + float x[5]; + x[0] = 3.14159; // Pi + x[1] = 6.022e22; // Avogadro constant + x[2] = 1.6e-19; // Electron charge magnitude + x[3] = 1.e-40; // A tiny (denormalized) value + x[4] = numeric_limits::infinity (); // This will fail while serializing... + + // Open an output file stream in binary mode : + ofstream fout (filename.c_str (), ios_base::binary); + + { + // Create an output portable binary archive attached to the output file, + // using the special 'boost::archive::no_infnan' flag : + boost::archive::portable_binary_oarchive opba (fout, boost::archive::no_infnan); + + // Store (serialize) variables : + for (int i = 0; i < 5; ++i) + { + clog << "Serializing value : " << x[i] << " ... "; + opba & x[i]; + clog << "Ok !" << endl; + } + } + } + catch (exception & x) + { + cerr << "ERROR: " << x.what () << endl; + return 1; + } + + return 0; +} + +// end of tutorial_pba_3.cpp diff --git a/doc/tutorial/code/tutorial_pba_4.cpp b/doc/tutorial/code/tutorial_pba_4.cpp new file mode 100755 index 00000000..61d05f6f --- /dev/null +++ b/doc/tutorial/code/tutorial_pba_4.cpp @@ -0,0 +1,105 @@ +/** 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) + * + */ + +/** + * 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. + * + */ + +#include +#include + +#include +#include +#include + +int main (void) +{ + using namespace std; + + // The name for the example data file : + string filename = "pba_4.data"; + + { + // Some integer numbers : + bool t = true; + char c = 'c'; + unsigned char u = 'u'; + int8_t b = -3; // char + uint8_t B = +6; // unsigned char + int16_t s = -16; + uint16_t S = +32; + int32_t l = -128; + uint32_t L = +127; + int64_t ll = -1024; + uint64_t LL = +2048; + + // Open an output file stream in binary mode : + ofstream fout (filename.c_str (), ios_base::binary); + + { + // Create an output portable binary archive attached to the output file : + boost::archive::portable_binary_oarchive opba (fout); + + // Store (serialize) variables : + opba & t & c & u & b & B & s & S & l & L & ll & LL; + } + } + + { + // Single precision floating numbers to be loaded : + // Some integer numbers : + bool t; + char c; + unsigned char 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; + + // Open an input file stream in binary mode : + ifstream fin (filename.c_str (), ios_base::binary); + + { + // Create an input portable binary archive attached to the input file : + boost::archive::portable_binary_iarchive ipba (fin); + + // Load (de-serialize) variables using the same + // order than for serialization : + ipba & t & c & u & b & B & s & S & l & L & ll & LL; + } + + clog << "t = " << t << " (bool)" << endl; + clog << "c = '" << c << "' (char)" << endl; + clog << "u = '" << u << "' (unsigned char)" << endl; + clog << "b = " << (int) b << " (int8_t)" << endl; + clog << "B = " << (int) B << " (uint8_t)" << endl; + clog << "s = " << s << " (int16_t)" << endl; + clog << "S = " << S << " (uint16_t)" << endl; + clog << "l = " << l << " (int32_t)" << endl; + clog << "L = " << L << " (uint32_t)" << endl; + clog << "ll = " << ll << " (int64_t)" << endl; + clog << "LL = " << LL << " (uint64_t)" << endl; + } + + return 0; +} + +// end of tutorial_pba_4.cpp diff --git a/doc/tutorial/code/tutorial_pba_5.cpp b/doc/tutorial/code/tutorial_pba_5.cpp new file mode 100755 index 00000000..18f61392 --- /dev/null +++ b/doc/tutorial/code/tutorial_pba_5.cpp @@ -0,0 +1,111 @@ +/** 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) + * + */ + +/** + * 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. + * + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +int main (void) +{ + using namespace std; + + // The memory buffer is implemented using a STL vector : + typedef std::vector buffer_type; + buffer_type buffer; + + { + // Some data to be stored : + bool t = true; + char c = 'c'; + int16_t s = +16; + int32_t l = -128; + int64_t ll = +10000000000; + float pi = 3.14159; + double nan = numeric_limits::quiet_NaN (); + string hello = "World !"; + + buffer.reserve (1024); // pre-allocate some memory + + // The output stream interface to the buffer : + boost::iostreams::stream > output_stream (buffer); + + { + // Create an output portable binary archive attached to the output file : + boost::archive::portable_binary_oarchive opba (output_stream); + + // Store (serialize) variables : + opba & t & c & s & l & ll & pi & nan & hello; + } + + } + + clog << "Buffer content is " << buffer.size () << " bytes : " << endl << " "; + for (int i = 0; i < buffer.size (); ++i) + { + clog << (int) ((unsigned char) buffer[i]) << ' '; + if ((i + 1) % 20 == 0) clog << endl << " "; + } + clog << endl; + + { + // Some data to be loaded : + bool t; + char c; + int16_t s; + int32_t l; + int64_t ll; + float pi; + double nan; + string hello; + + // The input stream interface to the buffer : + boost::iostreams::stream input_stream (&buffer[0], + buffer.size ()); + + { + // Create an input portable binary archive attached to the input file : + boost::archive::portable_binary_iarchive ipba (input_stream); + + // Load (de-serialize) variables : + ipba & t & c & s & l & ll & pi & nan & hello; + } + + clog << "Loaded values from the buffer are: " << endl; + clog << " t = " << t << " (bool)" << endl; + clog << " c = '" << c << "' (char)" << endl; + clog << " s = " << s << " (int16_t)" << endl; + clog << " l = " << l << " (int32_t)" << endl; + clog << " ll = " << ll << " (int64_t)" << endl; + clog << " pi = " << pi << " (float)" << endl; + clog << " nan = " << nan << " (double)" << endl; + clog << " hello = \"" << hello << "\" (std::string)" << endl; + } + + return 0; +} + +// end of tutorial_pba_5.cpp diff --git a/doc/tutorial/code/tutorial_pba_6.cpp b/doc/tutorial/code/tutorial_pba_6.cpp new file mode 100755 index 00000000..f32659a4 --- /dev/null +++ b/doc/tutorial/code/tutorial_pba_6.cpp @@ -0,0 +1,112 @@ +/** 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) + * + */ + +/** + * 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. + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +using namespace std; + +/* A foo noncopyable class */ +struct foo : boost::noncopyable +{ + uint32_t status; + double value; + double special; + + string to_string () const + { + ostringstream sout; + sout << "foo={status=" << status << "; value=" << value << "; special=" << special<< "}"; + return sout.str(); + } + + template + void serialize (Archive & ar, const unsigned int version) + { + ar & status; + ar & value; + ar & special; + return; + } + +}; + +// A templatized copy function for Boost/Serialization equipped classes. +// Here we use PBAs associated to a memory buffer : +template +void copy (const Serializable & source, Serializable & target) +{ + namespace io = boost::iostreams; + namespace ba = boost::archive; + if (&source == &target) return; // self-copy guard + typedef std::vector buffer_type; + buffer_type buffer; + buffer.reserve (1024); + { + io::stream > output_stream (buffer); + ba::portable_binary_oarchive opba (output_stream); + opba & source; + } + { + io::stream input_stream (&buffer[0], buffer.size ()); + ba::portable_binary_iarchive ipba (input_stream); + ipba & target; + } + return; +} + +int main (void) +{ + // Some instance of the 'foo' class : + foo dummy; + dummy.status = 1; + dummy.value = 3.14159; + dummy.special = numeric_limits::quiet_NaN (); + clog << "dummy is : " << dummy.to_string () << endl; + + // Another instance of the 'foo' class : + foo clone; + + /* The following instruction is forbidden because foo + inherits 'boost::noncopyable' : + + clone = dummy; // this ends in a compilation error. + + */ + + // Anyway, we can use this workaround : + copy (dummy, clone); + clog << "clone is : " << clone.to_string () << endl; + + return 0; +} + +// end of tutorial_pba_6.cpp diff --git a/doc/tutorial/code/tutorial_pba_7.cpp b/doc/tutorial/code/tutorial_pba_7.cpp new file mode 100755 index 00000000..30722b18 --- /dev/null +++ b/doc/tutorial/code/tutorial_pba_7.cpp @@ -0,0 +1,54 @@ +/** 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) + * + */ + +/** + * 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. + * + */ + +#include +#include +#include +#include + +using namespace std; + +int main (void) +{ + { + float x = numeric_limits::infinity (); + double y = numeric_limits::quiet_NaN (); + cout.precision (8); + cout << "x = " << x << endl; + cout.precision (16); + cout << "y = " << y << endl; + } + + { + string input ("inf nan"); + istringstream iss (input); + float x; + double y; + iss >> x >> y; + if (! iss) + { + cerr << "Cannot read 'x' or 'y' : non finite values are not supported !" << endl; + } + } + return 0; +} + +// end of tutorial_pba_7.cpp diff --git a/doc/tutorial/code/tutorial_pba_8.cpp b/doc/tutorial/code/tutorial_pba_8.cpp new file mode 100755 index 00000000..a41e46fb --- /dev/null +++ b/doc/tutorial/code/tutorial_pba_8.cpp @@ -0,0 +1,118 @@ +/** 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) + * + */ + +/** + * 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. + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; + +void do_text_out (void) +{ + // The name for the example data text file : + string filename = "pba_8.txt"; + + // Some variables of various primitive types : + bool b = true; + char c = 'B'; + uint32_t answer = 42; + float value = numeric_limits::infinity (); + double precision = numeric_limits::quiet_NaN (); + string question = "What makes you think she's a witch?"; + + // Open an output file stream : + ofstream fout (filename.c_str ()); + + // Prepare the output file stream for inf/NaN support : + locale default_locale (locale::classic (), + new boost::archive::codecvt_null); + locale infnan_locale (default_locale, + new boost::math::nonfinite_num_put); + fout.imbue (infnan_locale); + + { + // Create an output text archive attached to the output file : + boost::archive::text_oarchive ota (fout, boost::archive::no_codecvt); + + // Store (serializing) variables : + ota & b & c & answer & value & precision & question; + } + + return; +} + +void do_xml_out (void) +{ + // The name for the example data XML file : + string filename = "pba_8.xml"; + + // Some variables of various primitive types : + bool b = true; + char c = 'B'; + uint32_t answer = 42; + float value = numeric_limits::infinity (); + double precision = numeric_limits::quiet_NaN (); + string question = "What makes you think she's a witch?"; + + // Open an output file stream : + ofstream fout (filename.c_str ()); + + // Prepare the output file stream for inf/NaN support : + locale default_locale (locale::classic (), + new boost::archive::codecvt_null); + locale infnan_locale (default_locale, + new boost::math::nonfinite_num_put); + fout.imbue (infnan_locale); + + { + // Create an output text archive attached to the output file : + boost::archive::xml_oarchive oxa (fout, boost::archive::no_codecvt); + + // Store (serializing) variables : + 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); + } + + return; +} + +int main (void) +{ + do_text_out (); + do_xml_out (); + return 0; +} + +// end of tutorial_pba_8.cpp diff --git a/doc/tutorial/code/tutorial_pba_9.cpp b/doc/tutorial/code/tutorial_pba_9.cpp new file mode 100755 index 00000000..ff564be1 --- /dev/null +++ b/doc/tutorial/code/tutorial_pba_9.cpp @@ -0,0 +1,134 @@ +/** 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) + * + */ + +/** + * 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. + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +void do_text_in (void) +{ + // The name for the example data text file : + string filename = "pba_8.txt"; + // Some variables of various primitive types : + bool b; + char c; + uint32_t answer; + float value; + double precision; + string question; + + // Open an input file stream : + ifstream fin (filename.c_str ()); + + // Prepare the input file stream for inf/NaN support : + locale default_locale (locale::classic (), + new boost::archive::codecvt_null); + locale infnan_locale (default_locale, + new boost::math::nonfinite_num_get); + fin.imbue (infnan_locale); + + { + // Create an input text archive attached to the input file : + boost::archive::text_iarchive ita (fin, boost::archive::no_codecvt); + + // Store (serializing) variables : + ita & b & c & answer & value & precision & question; + } + + clog << "Loaded values from text archive are: " << endl; + clog << " b = " << b << endl; + clog << " c = '" << c << "'" << endl; + clog << " answer = " << answer << endl; + clog << " value = " << value << endl; + clog << " precision = " << precision << endl; + clog << " question = \"" << question << "\"" << endl; + + return; +} + +void do_xml_in (void) +{ + // The name for the example data text file : + string filename = "pba_8.xml"; + + // Some variables of various primitive types : + bool b; + char c; + uint32_t answer; + float value; + double precision; + string question; + + // Open an input file stream : + ifstream fin (filename.c_str ()); + + // Prepare the input file stream for inf/NaN support : + locale default_locale (locale::classic (), + new boost::archive::codecvt_null); + locale infnan_locale (default_locale, + new boost::math::nonfinite_num_get); + fin.imbue (infnan_locale); + + { + // Create an output text archive attached to the output file : + boost::archive::xml_iarchive ixa (fin, boost::archive::no_codecvt); + + // Store (serializing) variables : + 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 << "Loaded values from XML archive are: " << endl; + clog << " b = " << b << endl; + clog << " c = '" << c << "'" << endl; + clog << " answer = " << answer << endl; + clog << " value = " << value << endl; + clog << " precision = " << precision << endl; + clog << " question = \"" << question << "\"" << endl; + + return; +} + +int main (void) +{ + do_text_in (); + do_xml_in (); + return 0; +} + +// end of tutorial_pba_9.cpp diff --git a/doc/tutorial/images/boost.png b/doc/tutorial/images/boost.png new file mode 100755 index 0000000000000000000000000000000000000000..b4d51fcd5c9149fd77f5ca6ed2b6b1b70e8fe24f GIT binary patch literal 6308 zcmeAS@N?(olHy`uVBq!ia0y~yU=(FwU~)iH)5g zbF}vT%$qmo{2pS9asE?~yS4 zV~}*@!()Y0Y8HLTe-Cy%RA)$&m?L5Mr-f6RO~ozV_0NRY3o~1Lgxi$dvW4w;NZndD zlR*^3VYi=hVqyLvMt=V-1{{V_+&@0IB#0`@6669QfIo7R{( z3ohQ;EYDP7Gx74VKmF=OCnj|XE)MOKH}{k2T<}9tMWRb$ZQh>=2c7MBTjaeg3`Gp1 zOn)q7?Ek%8_>X~zVbts&3mN$xw|)-2UDdxRz3$(!-R|jkeqPU&t9|EQf4U-d>xFFg z{x{Ws1M+_v3h7m71U^}DEu~!BQ6S*mp|rVu(zeF6FR#qBJpbplS--)u7*~_>#FgoP zC0;&Blc}(I*wXQNtz+fgBa>K#&Pz3gS=T4tG_Ef>tdM*v)Mf9R;~oktCWxAuS7f+M zkY)H5Kj*{7I$4cZ0Rpn~XC94B`jlQOxK3N&`sd?@$!_ceJ*?v{!!S?h|1u2N0KqFL{jZD3|yYm@!7 zD{$ko5T!kC`67XKbkL|AAk>9FP1vNkmjDiX|^R^y;cp z^UAV29q)=Z9@9`fO2<&WREDl_D6c zquluTRZ|NyzoZApW6$HZ`(0auB>B#Jzf759_*7~`{jMwhHPzc6w)9V3{3&onmEH2% zy1=bZw@F0$zb(W{9 z3y<+%SSy^|qZ!UEsHV8u))-3_d=8X|6u5RU;FQR;B`srKi(_hUww{zF=hR3r! zXLBzsJ+<)d^@Z9(9_Fnfdv|Wq@t&1)^nJt=i_#|%nJxW)9rf71f7X9z|KnWAZGFS3 z6Aswit-5^U?sor@cTX63S$-tEJ0!F~YKzzL2CkY3US8MpYB<;)MEE6iKJ-umChec13b_tyxeQ=+0@?B&Bs0~0tT{en%M z!%db795*#F_ZI8rm3nY-i<6%G8IdAE^ zDcP6n-YUQkEQw;TGU7HvCEhOlZXez|o}Ik#ZL?n#f0 zm&@0usQ+!aHM{IEtN)He?(1_cF30}4pyQB{na7p?Yt8cWT4DhvyZ3Gk>NcJ@p<`k8 zb?L*N3y*YaGWf?i-b}h|dV}Y$;ZwfjTPJK+?Nynme|0gZZy~q5i)`feg`e7*FI?+1 z3@AFW_=oZTk8Tl*&Of=by#9l1Jjd5fcb~`G2q;xtI3*F#bbUFm$+xKbV)a$C6pB^^ z1lmV4oNhM{)j56VprliIp4*~^l%?ygdcFK&!0`C8>zBZ7qSF(;8{W9w$+1hRPbq0j z+)56cPdt$hA_o`mkbLbYy3?Fb@PqKL13660Kc?a<=bYSg062edXWB zWk)QFCOK^l>QzbpWBd40zP}UyN9`o5y*vwbUtjd_Dwm#8d^#yhph!H`qy`^UIetc?g_a^_;BpJd%79iM`k@&x+!*DZpNpYH*(v#^RIqB%W%DElQ`FVt9xtp`qG%b zC$}Fd&--&DH83jV)Kse%$@gWZo1E>i$#8qWhU1%|-rcg^X`PE_ty+0>&6INuT-yR% zxPP|Y*w}t-ZO3=V6RVy*aV_z@=v=p|=8kdC)JwZxtCz&GZ9Y^LW^|u{U;} zH9gjEzv*t-9Vo|D|*8v{A{fASF z4@9J_E8;M}@S;Pv?~(;Wf{ALi+8wFP_qSPdPi;PPZT2qF^A}I27XSOPuxC%n@p-B( zt8}g_)E>XC@_5s$Ihsaw+xtIH>NwT4DojsxvZltzn@X#$*eqz$;ZVGtzxlvVrCkAL zC0jgvN+r{B`J+0jc8c<>U@`AYK5={|i<-zw(b;?XCpx|^@%g&??zdAd8Z`mar`!L! zZNKl7bW!WK4_O=6t-C$pQNDb)q{7qLpXc>9NX>H&=WWnz^4h7YXsF`0BZgJh_OeNJ z%)&xn`-aN`M%?~q7tWm>=<~qKRC8tM8$a%L{ey2kI8txkxx3xJ;j7Q%D{3XiFZ{lA z@!CjtaC^NE+kflmOwWbxatr6_&(6MF|6t{woyqeTuLzr<&3y94wX=cek{6aeUJ?*A zA|7V$;*0%XQzrZUg(%toS)1l9e_o_KgKhsEl z%>TgoO~d@AO(F$~s`B5L-VF&l#Q9|Tyjsb)_4*kL6%Aq?l9x1=_fJ3j^FjMRW|bX# zU6Q`WES&Q2hiJpbyKS#ltvcns@e11nSMJJ^B1hxqr*{?>ay(Q_Ii`J_HS?Id?{T} zdujR8{u=dDvyGLc7uJ{ttvLQ5V9SoEsjpLa>P>%Dv{6m`!HQ{LoEx3>RuuJJe^uzo z{$VBSd{ZZrwhL!mZPoQYZBh&R_c2j-wsMC1wHuXxj_54pxvBSE<#2{|uAf=& zLd15vt&n7VlFY&B#>m^cA54%ctolSO;BmGUrUyj5Bh|5j?+)pHw?WDm47pW+O9 zapkFU{jK18t4ejHF7IXSZmrrDuz$w-=P9P)*ZONBbwjSyJihQL^)G|A>LjU0Uffq_ zP3tT!?=ek$DPW;3yhBoPfpqV_$y2N5tS-y=v!LPh+Jb#i)vEJb_8ysf>GQqyWr3G< z<*w!ME8g1r{q(aHPxvJ*`JS!~nLbHq{`A-XO}A#ukbjnCIr)d1)J)4iQ)ixFu9xvX zdbIm!h~4~ndy9g%0`-4k^9VYS(!B`f@odS%TN&ghk&qa}1AIa%-D z$8C%`#j>qQJDtBXs~)#t@!o%HYf)UqGs6jT?Ds6M{Z!I6SYh*cVS(xQgvW+jf6sp3 z%so|0|7hvz$A68DHtp`@W!duRzSKsWSBHw;cBd95xB2s=OnIuGqAJRyPqPNOGM$x>QK{U%tz_lxWgo+MmmXe~{? z<6L};Q#fzI>}!WZYtIYx=emVuWtaUr=Jt1c(B+_*qx+(6Z#*WwGihVyleYH@II39l zJ}fpd_~g2ix4PlMk40;i#J?3PS$kamrfc7Gj+R&Nj#^!K)PC&K&X9*flk{r%&Oecw z$vY#nZ;SG@=TDqu>)3-l<3c~F*7BZTJDcS);{$`1J7N=4Ib!F!Nk6J$F<%w-=ETb* zKNiM^ef`t@yRiBGJlV-tye__U(Eq=+*}b5bt!U-f)v-ozIo<^wx8%2qmlKz;H<``9 z?#>>rkBeCDRDDZI&GXC@{m^vb)UT`G?N;lEg*ZCYBr$8H9;}L#f4(j5@a&6A^WvF4 z-KzNbjJK*TGEmh|QQ>&<&6sJY_`RR0-w|QI;&7gQM?mVFbDfhbtTLL{JbD+t`=L;x z5R-ZP?ckrzeJ5hpeVBAYT>IlE<(%Q0v@s{d_?sS#t{kL+XXYA?fR9UiJUAOA%gODBCxwpUXuhfe;p`E03 zF7@-)mBOc2Y&2ObS(`l1>~XeE`mL@HGKXcqe`|lb|JUUuB2T9)&#W?3Pc@RhUfArJ zyRzeiw0>PSkE+X(D_c~;pY7>but)IN+MnFs2lQCxw%<`b;5pB_y`hp}j@J%xmRmJt zmG7Nz-@T=L*3GgZ!k>Fd{M&8Hm0x%d)HS~rKNOX~^lAQ&kK7BmOU|pG{P}BH;grd* zcRf8^%)U(Af3CLa^D-&!^*_@@mYZ@vnIU*d|Kpy@>rZ$;&R*YjC2Q6s>wclboSK^^ zTwkTNsdABYb!6d+t*s}nGXKhVU8lm@`n>WETQ|pN&8znRch4_*+-mo?`Tc`uZ%$~< zk7Zzswd4Ks@yU0&EdQ%Kdt+lSYqQCHJ;^Mb@O!7c?W;~k2ie3u#h10u|4r_Q$g2Ol zZBb|8JnQWtmS0mZ&U$ub)Q*n)+)&UqVQtiM#gL#cmh&@0ItsTs z1)iH;(qFcZ!+k4*`^u;(Ul%WsH?`<`8nrS;xc92vJR^3&@_Ugd;<&aq`)=*cadVcG zSbO-b{ey(~&x@zOElW;N>i25gBfd~SUEyK7O?S}hSL-%QulI9dUHCM#Sh*$1EyLhw z{+Sn(0yL*P3VVNAs&Z=i4knq*eG|mGGUM#oS}yJC*yE>>s#K&Fbgo0xGeG*)g6aR- zgzYqX*7nQnWy+HF)o+s!N?Rwr^p51>^tWyM_FO3sG1@zKN`2Iehf5g0m>=JD?rY(e zn3bwY6X%xa{CGOCa<^SujI{g2TF&o1udT{g#<26AEBF54z`5tM!koOeyv31oA0<2$ zpI6DlGih7-8g@RmKF(K0?|gUX9x)NPGo!lvzPqxak4N*}r>hsY?VHXq_5Xo~9vk-U z-5e9-s>%1~=l%WG_22f~;S$O%+SuCUmfRM+@S%;t5;hezvt#dN`<<1i2E{$fo+lr+ z;5g^gMbL zx2)>qe`Ql(vEz}_s*s)w=XIIGRvhf&y)RI7!tiwcglRu~o0XPidAYVPa1^Usv&Gu+ z$22i!{>62V*pCz4}_#;jX@bd|JO za2+kbcnxgq{F*xk#37XT8qPBx!(S?FYm8#N8M!PH;<~B z_}HVu&bV24@xKSh7w*}aSu1ohwf6kQ{JTae@i`7N1aFy5bJ%r$*DMj!_%lD0j_Ybk zR!Dq3SlURq6Xm1$<7<^CO0zSow1OaD-NHDJb{Ibplgsxl00r+8kT@_*YnA?-hW?T&hC41^5*9p{QuwU%Wj!(x1(12-A4wS zzC(|b!za#vICVRp^XnEX+xd!u{r@h1|NcOMrS;_7f3GgQzd!F+bLp<~@3j^ldp7<5 zaAo7^$Y~?mc2%Zv>*mS3f^JXSvsldxyo}N%gGWcP}gc$%I_v zI|}R%7S_)W_+iME$M%82zO+w%vZkhY-)~NN;aG*Zd4FDdrv#=Mu8aKf#B1k6xnR5b z=b7HmGhL#3)|lb%YwrDjYVrg(yt0&-*~(de@xNa!!-J2mYkodwsCe-4-_Q5oOF|<% zE+`x~KEBS;^xK=>4;wpP#ZuI{a?4J5hV)2Qt0!ho(xkd_=2*otMnY2&#==q+9 z`$N{{NXhOher>VsLy_Ev1hI2cR_Fgtu6GIe*3kcce{lMv?fo?l6&}Zp87dwa7U&<> z@%eF^U-}bELvEt9`pO0Mju#GUS3NrZ-&51?@R9z<+I!~Be^9Ee9g-YDqJ}hT+{K3mK7V(2mOeeZM zFiYMbpC@MVvi+Frg}{do7urZD9>}%$!ytS(p6f(Qw9a1c?-Bve*4;k#@NMIXrgFR5 zM<$H+X{{~$IpSD*m_GQO=~M0r&MW8WP=4{^-pl+v!6%%G@h1d7-QCn7uw87Cx6~Ky z7prR5|37B)_u*oGA-1#^OHLjvyl=Jeu!H{lJ?#zIjpdHgCb{uV>++@KTEraXjaM7( zeBStb+eFuyk)jS9$GCTJ-duKB-ez9ec zlkl@RE6K&I!>P~SranO>?6_bYpT`MvUh^JSn+tn)KTLY6@qMM!j|&zq-pMZN@iWjrucTLs03Gq8jX0xSk+4b=;_re8-+I5;FDkRnx{&`T~q*+sATf}42 zb4{e~gaB8UjEvj~KQlHtx78B%771J0Wu!z5KNv&>|5)e}DE&*?nQ!rWt~!CQ<&w81 z+kK%?tyDs7T(@uhz*ICMX35d@9K_ej)97$*Hl iJhEc{m;X#W3{O<*lBMphi)3J6VDNPHb6Mw<&;$TZQ2{;x literal 0 HcmV?d00001 diff --git a/doc/tutorial/images/c++-source-code.png b/doc/tutorial/images/c++-source-code.png new file mode 100755 index 0000000000000000000000000000000000000000..8328062fa46b91592f64efe249383dcd44ad6d47 GIT binary patch literal 1296 zcmeAS@N?(olHy`uVBq!ia0y~yU{GUVV36ftV_;x7)*yF)fq{XsILO_JVcj{ImkbOH zY)RhkE)4%caKYZ?lNlHoI14-?iy0VruY)k7lg8`{1_lQ95>H=O_S;+ntg6CCn4%Ui zFfd4#xJHyX=jZ08=9Mrw7o{eaq^2m8XO?6rxO@5rgg5euGcd4Zd%8G=L>xXl?X15@ zq{z|pzgMhUx9;6Cb~m@Si7l-&9|(x;Dm-{ewa`^zQ(5@iIOnvZYtrJi|1t0!aS@;3 z8R6s4#Nsn$L6daCLWQ*|CC=u)wR^(z#UfPKuKnU+T{Ou{Yi0EJzpwWF_KSTmr;EYC zZoWOs1QQY5nlu!Nd-sNpi+;H<|Wa-mWqDz7_CE6Ih zUe0W25wNhZIIz3?{fA#)v%h@#(jXudqBYfa>6L=``1|(DpDtjyaOqN0j+u0G=B%=3 z+B1EeE}H~+J^an6bNZ6e%rpKi6ZX%ut^T$Sog=jYr1uP!V!{Or2HfJd+`@w3!)0fS=)EZdi57R2)JT6er)*E;E4 z>%Pxkw)4xEmzTNcvvM~vI0~4E_62cWHks%#W5JY$V!7tM?~{*N{ue#)>eHuBPj@Bk zdw=-zo@H|7UYaJp%*i5+0uzGVu3B-rTRgXCim3YY<758(hS1faZ{ELm=D1j5aZF;# z6agm%p2M@4g$^?QXf!n2zh%o6*}bP37X+=`^MBX>XYpPuXYE_{Jw|gukX~|L9v_23 zDu+X3VPA<>tBaDL>@G2epC?bAyti=SLL*zgX$7&{(-wMs{`~pH`}givbKUau_0`nW z9?k2CI#Bw$dRd}GM*jYWzCON~Jr#mCbHtX-Y!F~Nnk4x8_3Mbp$b+Y+>u=n*kMI2F zx|eU>*mP(glUU9D_0?7FJ9{dHx98tK_V@SqK&`0;W@c^C+w)BKOr7b&wrkzt&o(TM z42mp$eSHsh>3J;`I`x#R=DxFpR!&Y%!0AnPDl=xx2xxUWI5lY1I zeB-n;hOcEp#laVL(@&dk6~7yhOQL{i_Za%9Ospx3{h8 z%?;UeV%vA_T&bq69_oAaRc1m0!{f(~C1hofe*0z?x2K}<;lqddW->+R9;S7_%FPrFep)z?CLX z&4<73mQ1}{KQT!#YcrFO7G5c zoT{&{?|s-{RsOv_o=gXxJyWxIUf495_owb`+g<5Bp@s9l>h}kQ=KR(SFlJz2VDNPH Kb6Mw<&;$S=7*_89 literal 0 HcmV?d00001 diff --git a/doc/tutorial/release_notes.txt b/doc/tutorial/release_notes.txt new file mode 100755 index 00000000..42e1fbdf --- /dev/null +++ b/doc/tutorial/release_notes.txt @@ -0,0 +1,36 @@ +IMPORTANT: + +This is the last release from me as EOS employee. I plan to contribute all of this +work to the official boost libraries distribution and will continue to support users. +Francois Mauger joined me recently and already added a valuable tutorial for you! + + +Dear user, + +I am proud to announce the very first release of our portable_binary_[io]archive +which we use here at EOS to move data between different platforms. It really is +a conglomerate of pieces that already were there - as is most often the case in +OO world - we simply put them together in a way that seemed to make sense. I know +a lot of people were interested in portable binary archives, so here you are - +give it a try and let me know what you think about it! + +We rely heavily on boost::serialization and really appreciate the amount of time +and knowledge that went into it. By publishing this small missing piece we hope +to contribute our mite to this great library. + +The work extends the portable binary example which was done by Robert Ramey and +uses Beman Dawes' endian library plus the fp_utilities by Johan Rade. You will +need to get those two libraries in order to use our classes - look for them at +the boost vault (http://www.boost-consulting.com/vault/) in categories 'integer' +and 'math - numerics'. Finally you will find the portable binary archive in +category 'serialization' as well. + +Regards, +Christian Pfligersdorffer + +Munich, End of 2007 + +-- +christian.pfligersdorffer@eos.info +christian.pfligersdorffer@gmx.at +http://www.eos.info \ No newline at end of file diff --git a/doc/tutorial/scripts/jquery-1.4.min.js b/doc/tutorial/scripts/jquery-1.4.min.js new file mode 100755 index 00000000..5c70e4c5 --- /dev/null +++ b/doc/tutorial/scripts/jquery-1.4.min.js @@ -0,0 +1,151 @@ +/*! + * jQuery JavaScript Library v1.4 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://docs.jquery.com/License + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Wed Jan 13 15:23:05 2010 -0500 + */ +(function(A,w){function oa(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(oa,1);return}c.ready()}}function La(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function $(a,b,d,f,e,i){var j=a.length;if(typeof b==="object"){for(var o in b)$(a,o,b[o],f,e,d);return a}if(d!==w){f=!i&&f&&c.isFunction(d);for(o=0;o-1){i=j.data;i.beforeFilter&&i.beforeFilter[a.type]&&!i.beforeFilter[a.type](a)||f.push(j.selector)}else delete t[p]}i=c(a.target).closest(f,a.currentTarget); +n=0;for(l=i.length;n)[^>]*$|^#([\w-]+)$/,Pa=/^.[^:#\[\.,]*$/,Qa=/\S/, +Ra=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Sa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],M,ca=Object.prototype.toString,da=Object.prototype.hasOwnProperty,ea=Array.prototype.push,R=Array.prototype.slice,V=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(typeof a==="string")if((d=Oa.exec(a))&&(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Sa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])]; +c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=ua([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return U.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a)}else return!b||b.jquery?(b||U).find(a):c(b).find(a);else if(c.isFunction(a))return U.ready(a);if(a.selector!==w){this.selector=a.selector; +this.context=a.context}return c.isArray(a)?this.setArray(a):c.makeArray(a,this)},selector:"",jquery:"1.4",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){a=c(a||null);a.prevObject=this;a.context=this.context;if(b==="find")a.selector=this.selector+(this.selector?" ":"")+d;else if(b)a.selector=this.selector+"."+b+"("+d+")";return a},setArray:function(a){this.length= +0;ea.apply(this,a);return this},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject|| +c(null)},push:ea,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,i,j,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
a";var e=d.getElementsByTagName("*"),i=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!i)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length, +htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(i.getAttribute("style")),hrefNormalized:i.getAttribute("href")==="/a",opacity:/^0.55$/.test(i.style.opacity),cssFloat:!!i.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(j){}a.insertBefore(b, +a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function o(){c.support.noCloneEvent=false;d.detachEvent("onclick",o)});d.cloneNode(true).fireEvent("onclick")}c(function(){var o=s.createElement("div");o.style.width=o.style.paddingLeft="1px";s.body.appendChild(o);c.boxModel=c.support.boxModel=o.offsetWidth===2;s.body.removeChild(o).style.display="none"});a=function(o){var p=s.createElement("div");o="on"+o;var n=o in +p;if(!n){p.setAttribute(o,"return;");n=typeof p[o]==="function"}return n};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=i=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var H="jQuery"+K(),Ta=0,ya={},Ua={};c.extend({cache:{},expando:H,noData:{embed:true,object:true,applet:true},data:function(a, +b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?ya:a;var f=a[H],e=c.cache;if(!b&&!f)return null;f||(f=++Ta);if(typeof b==="object"){a[H]=f;e=e[f]=c.extend(true,{},b)}else e=e[f]?e[f]:typeof d==="undefined"?Ua:(e[f]={});if(d!==w){a[H]=f;e[b]=d}return typeof b==="string"?e[b]:e}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?ya:a;var d=a[H],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{try{delete a[H]}catch(i){a.removeAttribute&& +a.removeAttribute(H)}delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,a,b)})},removeData:function(a){return this.each(function(){c.removeData(this, +a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this, +a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var za=/[\n\t]/g,fa=/\s+/,Va=/\r/g,Wa=/href|src|style/,Xa=/(button|input)/i,Ya=/(button|input|object|select|textarea)/i,Za=/^(a|area)$/i,Aa=/radio|checkbox/;c.fn.extend({attr:function(a, +b){return $(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(p){var n=c(this);n.addClass(a.call(this,p,n.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(fa),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var i=b?d:0;for(d=b?d+1:e.length;i=0;else if(c.nodeName(this,"select")){var z=c.makeArray(t);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),z)>=0});if(!z.length)this.selectedIndex= +-1}else this.value=t}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var i=Wa.test(b);if(b in a&&f&&!i){if(e){if(b==="type"&&Xa.test(a.nodeName)&&a.parentNode)throw"type property can't be changed";a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue; +if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:Ya.test(a.nodeName)||Za.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&i?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var $a=function(a){return a.replace(/[^\w\s\.\|`]/g,function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType=== +3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;if(!d.guid)d.guid=c.guid++;if(f!==w){d=c.proxy(d);d.data=f}var e=c.data(a,"events")||c.data(a,"events",{}),i=c.data(a,"handle"),j;if(!i){j=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(j.elem,arguments):w};i=c.data(a,"handle",j)}if(i){i.elem=a;b=b.split(/\s+/);for(var o,p=0;o=b[p++];){var n=o.split(".");o=n.shift();d.type=n.slice(0).sort().join(".");var t=e[o],z=this.special[o]||{};if(!t){t=e[o]={}; +if(!z.setup||z.setup.call(a,f,n,d)===false)if(a.addEventListener)a.addEventListener(o,i,false);else a.attachEvent&&a.attachEvent("on"+o,i)}if(z.add)if((n=z.add.call(a,d,f,n,t))&&c.isFunction(n)){n.guid=n.guid||d.guid;d=n}t[d.guid]=d;this.global[o]=true}a=null}}},global:{},remove:function(a,b,d){if(!(a.nodeType===3||a.nodeType===8)){var f=c.data(a,"events"),e,i,j;if(f){if(b===w||typeof b==="string"&&b.charAt(0)===".")for(i in f)this.remove(a,i+(b||""));else{if(b.type){d=b.handler;b=b.type}b=b.split(/\s+/); +for(var o=0;i=b[o++];){var p=i.split(".");i=p.shift();var n=!p.length,t=c.map(p.slice(0).sort(),$a);t=new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.)?")+"(\\.|$)");var z=this.special[i]||{};if(f[i]){if(d){j=f[i][d.guid];delete f[i][d.guid]}else for(var B in f[i])if(n||t.test(f[i][B].type))delete f[i][B];z.remove&&z.remove.call(a,p,j);for(e in f[i])break;if(!e){if(!z.teardown||z.teardown.call(a,p)===false)if(a.removeEventListener)a.removeEventListener(i,c.data(a,"handle"),false);else a.detachEvent&&a.detachEvent("on"+ +i,c.data(a,"handle"));e=null;delete f[i]}}}}for(e in f)break;if(!e){if(B=c.data(a,"handle"))B.elem=null;c.removeData(a,"events");c.removeData(a,"handle")}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[H]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();this.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType=== +8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;var i=c.data(d,"handle");i&&i.apply(d,b);var j,o;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()])){j=d[e];o=d["on"+e]}}catch(p){}i=c.nodeName(d,"a")&&e==="click";if(!f&&j&&!a.isDefaultPrevented()&&!i){this.triggered=true;try{d[e]()}catch(n){}}else if(o&&d["on"+e].apply(d,b)===false)a.result=false;this.triggered=false;if(!a.isPropagationStopped())(d=d.parentNode||d.ownerDocument)&&c.event.trigger(a,b,d,true)}, +handle:function(a){var b,d;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;d=a.type.split(".");a.type=d.shift();b=!d.length&&!a.exclusive;var f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)");d=(c.data(this,"events")||{})[a.type];for(var e in d){var i=d[e];if(b||f.test(i.type)){a.handler=i;a.data=i.data;i=i.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}return a.result}, +props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[H])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement|| +s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&& +a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a,b){c.extend(a,b||{});a.guid+=b.selector+b.live;c.event.add(this,b.live,qa,b)},remove:function(a){if(a.length){var b=0,d=new RegExp("(^|\\.)"+a[0]+"(\\.|$)");c.each(c.data(this,"events").live||{},function(){d.test(this.type)&&b++});b<1&&c.event.remove(this,a[0],qa)}},special:{}},beforeunload:{setup:function(a, +b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=K();this[H]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=ba;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped= +ba;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=ba;this.stopPropagation()},isDefaultPrevented:aa,isPropagationStopped:aa,isImmediatePropagationStopped:aa};var Ba=function(a){for(var b=a.relatedTarget;b&&b!==this;)try{b=b.parentNode}catch(d){break}if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}},Ca=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover", +mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ca:Ba,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ca:Ba)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(a,b,d){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="submit"||i==="image")&&c(e).closest("form").length)return pa("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit."+ +d.guid,function(f){var e=f.target,i=e.type;if((i==="text"||i==="password")&&c(e).closest("form").length&&f.keyCode===13)return pa("submit",this,arguments)})}else return false},remove:function(a,b){c.event.remove(this,"click.specialSubmit"+(b?"."+b.guid:""));c.event.remove(this,"keypress.specialSubmit"+(b?"."+b.guid:""))}};if(!c.support.changeBubbles){var ga=/textarea|input|select/i;function Da(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex> +-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d}function ha(a,b){var d=a.target,f,e;if(!(!ga.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Da(d);if(e!==f){if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",e);if(d.type!=="select"&&(f!=null||e)){a.type="change";return c.event.trigger(a,b,this)}}}}c.event.special.change={filters:{focusout:ha,click:function(a){var b=a.target,d=b.type;if(d=== +"radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return ha.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return ha.call(this,a)},beforeactivate:function(a){a=a.target;a.nodeName.toLowerCase()==="input"&&a.type==="radio"&&c.data(a,"_change_data",Da(a))}},setup:function(a,b,d){for(var f in W)c.event.add(this,f+".specialChange."+d.guid,W[f]);return ga.test(this.nodeName)}, +remove:function(a,b){for(var d in W)c.event.remove(this,d+".specialChange"+(b?"."+b.guid:""),W[d]);return ga.test(this.nodeName)}};var W=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d, +f,e){if(typeof d==="object"){for(var i in d)this[b](i,f,d[i],e);return this}if(c.isFunction(f)){thisObject=e;e=f;f=w}var j=b==="one"?c.proxy(e,function(o){c(this).unbind(o,j);return e.apply(this,arguments)}):e;return d==="unload"&&b!=="one"?this.one(d,f,e,thisObject):this.each(function(){c.event.add(this,d,j,f)})}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&!a.preventDefault){for(var d in a)this.unbind(d,a[d]);return this}return this.each(function(){c.event.remove(this,a,b)})},trigger:function(a, +b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},toggle:function(a){for(var b=arguments,d=1;d0){y=u;break}}u=u[g]}m[r]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, +e=0,i=Object.prototype.toString,j=false,o=true;[0,0].sort(function(){o=false;return 0});var p=function(g,h,k,m){k=k||[];var r=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return k;for(var q=[],v,u,y,S,I=true,N=x(h),J=g;(f.exec(""),v=f.exec(J))!==null;){J=v[3];q.push(v[1]);if(v[2]){S=v[3];break}}if(q.length>1&&t.exec(g))if(q.length===2&&n.relative[q[0]])u=ia(q[0]+q[1],h);else for(u=n.relative[q[0]]?[h]:p(q.shift(),h);q.length;){g=q.shift();if(n.relative[g])g+=q.shift(); +u=ia(g,u)}else{if(!m&&q.length>1&&h.nodeType===9&&!N&&n.match.ID.test(q[0])&&!n.match.ID.test(q[q.length-1])){v=p.find(q.shift(),h,N);h=v.expr?p.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:q.pop(),set:B(m)}:p.find(q.pop(),q.length===1&&(q[0]==="~"||q[0]==="+")&&h.parentNode?h.parentNode:h,N);u=v.expr?p.filter(v.expr,v.set):v.set;if(q.length>0)y=B(u);else I=false;for(;q.length;){var E=q.pop();v=E;if(n.relative[E])v=q.pop();else E="";if(v==null)v=h;n.relative[E](y,v,N)}}else y=[]}y||(y=u);if(!y)throw"Syntax error, unrecognized expression: "+ +(E||g);if(i.call(y)==="[object Array]")if(I)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&F(h,y[g])))k.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&k.push(u[g]);else k.push.apply(k,y);else B(y,k);if(S){p(S,r,k,m);p.uniqueSort(k)}return k};p.uniqueSort=function(g){if(D){j=o;g.sort(D);if(j)for(var h=1;h":function(g,h){var k=typeof h==="string";if(k&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,r=g.length;m=0))k||m.push(v);else if(k)h[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, +CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,k,m,r,q){h=g[1].replace(/\\/g,"");if(!q&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,k,m,r){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=p(g[3],null,null,h);else{g=p.filter(g[3],h,k,true^r);k||m.push.apply(m, +g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,k){return!!p(k[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, +text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, +setFilters:{first:function(g,h){return h===0},last:function(g,h,k,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,k){return hk[3]-0},nth:function(g,h,k){return k[3]-0===h},eq:function(g,h,k){return k[3]-0===h}},filter:{PSEUDO:function(g,h,k,m){var r=h[1],q=n.filters[r];if(q)return q(g,k,h,m);else if(r==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(r==="not"){h= +h[3];k=0;for(m=h.length;k=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var k=h[1];g=n.attrHandle[k]?n.attrHandle[k](g):g[k]!=null?g[k]:g.getAttribute(k);k=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== +"="?k===h:m==="*="?k.indexOf(h)>=0:m==="~="?(" "+k+" ").indexOf(h)>=0:!h?k&&g!==false:m==="!="?k!==h:m==="^="?k.indexOf(h)===0:m==="$="?k.substr(k.length-h.length)===h:m==="|="?k===h||k.substr(0,h.length+1)===h+"-":false},POS:function(g,h,k,m){var r=n.setFilters[h[2]];if(r)return r(g,k,h,m)}}},t=n.match.POS;for(var z in n.match){n.match[z]=new RegExp(n.match[z].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[z]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[z].source.replace(/\\(\d+)/g,function(g, +h){return"\\"+(h-0+1)}))}var B=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){B=function(g,h){h=h||[];if(i.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var k=0,m=g.length;k";var k=s.documentElement;k.insertBefore(g,k.firstChild);if(s.getElementById(h)){n.find.ID=function(m,r,q){if(typeof r.getElementById!=="undefined"&&!q)return(r=r.getElementById(m[1]))?r.id===m[1]||typeof r.getAttributeNode!=="undefined"&& +r.getAttributeNode("id").nodeValue===m[1]?[r]:w:[]};n.filter.ID=function(m,r){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===r}}k.removeChild(g);k=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,k){k=k.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;k[m];m++)k[m].nodeType===1&&h.push(k[m]);k=h}return k};g.innerHTML=""; +if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=p,h=s.createElement("div");h.innerHTML="

";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){p=function(m,r,q,v){r=r||s;if(!v&&r.nodeType===9&&!x(r))try{return B(r.querySelectorAll(m),q)}catch(u){}return g(m,r,q,v)};for(var k in g)p[k]=g[k];h=null}}(); +(function(){var g=s.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,k,m){if(typeof k.getElementsByClassName!=="undefined"&&!m)return k.getElementsByClassName(h[1])};g=null}}})();var F=s.compareDocumentPosition?function(g,h){return g.compareDocumentPosition(h)&16}:function(g, +h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ia=function(g,h){var k=[],m="",r;for(h=h.nodeType?[h]:h;r=n.match.PSEUDO.exec(g);){m+=r[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;r=0;for(var q=h.length;r=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var i=d;i0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,i= +{},j;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:j,elem:f});delete i[j]}}f=f.parentNode}}return d}var p=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,t){for(;t&&t.ownerDocument&&t!==b;){if(p?p.index(t)>-1:c(t).is(a))return t;t=t.parentNode}return null})},index:function(a){if(!a||typeof a=== +"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(sa(a[0])||sa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", +d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? +a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);ab.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||cb.test(f))&&bb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||!c(a).is(d));){a.nodeType=== +1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ga=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,db=/(<([\w:]+)[^>]*?)\/>/g,eb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,Ha=/<([\w:]+)/,fb=/"},G={option:[1,""], +legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};G.optgroup=G.option;G.tbody=G.tfoot=G.colgroup=G.caption=G.thead;G.th=G.td;if(!c.support.htmlSerialize)G._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=c(this); +return d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.getText(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&& +this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this.nextSibling)});else if(arguments.length){var a=this.pushStack(this, +"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ga,"").replace(Y,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ta(this,b);ta(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType=== +1?this[0].innerHTML.replace(Ga,""):null;else if(typeof a==="string"&&!/ + + + + + + + + + + + + + + +
+

+ Boost

+
+

Boost/Serialization ‐ Portable Binary Archives (PBA)

+

Tutorial

+

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 :-) +

+
+ + +
+
+
Quick start
+ +
+ +
Format +
+ +
Examples
+ +
+
+ +

+

+
+ +

Quick start

+ +Are you impatient to enjoy the Boost Portable Binary Archives (PBA) ? +If so, this section is for you. + +

How to store some simple data in a portable binary output archive

+ +

+The tutorial_pba_0.cpp sample +program uses a boost::archive::portable_binary_oarchive object +attached to a standard output file stream to store a couple of +variables of primitive types (bool, +char, integer +numbers, floating numbers) and even a std::string. +

+ +
+ The tutorial_pba_0.cpp source code DownloadShow/hide +
+/** 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)
+ *
+ */
+
+/**
+ * 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.
+ *
+ */
+
+#include <string>
+#include <fstream>
+
+#include <boost/cstdint.hpp>
+#include <boost/archive/portable_binary_oarchive.hpp>
+
+int main (void)
+{
+  // The name for the example data file :  
+  std::string filename = "pba_0.data"; 
+
+  // Some variables of various primitive types :
+  bool        b              = true;
+  char        c              = 'B';
+  uint32_t    answer         = 42;
+  float       computing_time = 7.5e6;
+  double      e              = 2.71828182845905;
+  std::string slogan         = "DON'T PANIC";
+  
+  // Open an output file stream in binary mode :
+  std::ofstream fout (filename.c_str (), std::ios_base::binary);
+  
+  {
+    // Create an output portable binary archive attached to the output file :
+    boost::archive::portable_binary_oarchive opba (fout);
+    
+    // Store (serializing) variables :
+    opba & b & c & answer & computing_time & e & slogan;
+  }
+
+  return 0;   
+}
+
+// end of tutorial_pba_0.cpp
+
+
+

+ + +

+The compiled executable creates the pba_0.data file which +contains the following bytes: +

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
+
+This format is explained in details below. + + +

Note: +

    +
  • the output of the byte content in the pba_0.data file +can be obtained invoking some command like +  od -t u1 pba_0.data  +on a GNU/Linux system.
    +
  • one should notice that this program makes use of +the typedef-ed integer types from +the boost/cstdint.hpp header (uint32_t...). It is a +strong recommendation to ensure cross-environment portability while +(de)serializing integer numbers (see also +the Examples section). +
+

+ + + +
+To top +
+
+ + +

How to load some simple data from a portable binary input archive

+ +

+The tutorial_pba_1.cpp sample program uses +a boost::archive::portable_binary_iarchive object +attached to a standard input file stream in order to load the +data previously stored by +the tutorial_pba_0.cpp program in +the pba_0.data file. +

+ + +
+ The tutorial_pba_1.cpp source code DownloadShow/hide +
+/** 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)
+ *
+ */
+
+/**
+ * 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. 
+ *
+ */
+
+#include <iostream>
+#include <string>
+#include <fstream>
+
+#include <boost/cstdint.hpp>
+#include <boost/archive/portable_binary_iarchive.hpp>
+
+int main (void)
+{
+  using namespace std;
+
+  // The name for the example data file :  
+  string filename = "pba_0.data"; 
+
+  // Some variables of various types :
+  bool     b;
+  char     c;
+  uint32_t answer;
+  float    computing_time;
+  double   e;
+  string   slogan;
+   
+  // Open an input file stream in binary mode :
+  ifstream fin (filename.c_str (), ios_base::binary);
+  
+  {
+    // Create an input portable binary archive attached to the input file :
+    boost::archive::portable_binary_iarchive ipba (fin);
+    
+    // Loading (de-serializing) variables using the same 
+    // order than for serialization (see tutorial_pba_0.cpp) :
+    ipba & b & c & answer & computing_time & e & slogan;
+  }
+
+  cout.precision (15);
+  cout << "Variable 'b' is              : " << b << " " << "(bool)" << endl;
+  cout << "Variable 'c' is              : '" << c << "' " << " " << "(char)" << endl;
+  cout << "Variable 'answer' is         : " << answer  << " " << "(unsigned 32-bit integer)" << endl;
+  cout << "Variable 'computing_time' is : " << computing_time  << " " << "(single precision 32-bit float)" << endl;
+  cout << "Variable 'e' is              : " << e  << " " << "(double precision 64-bit float)" << endl;
+  cout << "Variable 'slogan' is         : \"" << slogan  << "\" " << "(std::string)" << endl;
+
+  return 0;   
+}
+
+// end of tutorial_pba_1.cpp
+
+
+

+ + +

+The executable reads the pba_0.data file and deserializes its +contents in the same order it has been stored. It then prints the +restored values of the variables: +

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)
+
+

+ + + +
+To top +
+
+ + + +
+

Format

+ +

+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 pba_0.data file +created by the tutorial_pba_0.cpp +program (see the previous section). +

+ +

+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 this example). This +header is made of two informations : +

    +
  • + a magic byte with the conventionnal decimal value : +
    127
    +
  • + the Boost library version number which is encoded as an integer + number. +

    The PBA encoding of integer numbers uses the following + scheme: + <size> <content>, + where first the size stores the minimal + number of non zero bytes needed to store the binary + representation of the integer value; then the bytes corresponding to the content are stored + starting from the less significant ones (see + also this example). For the library + version number we have here: +

    1 9
    + where 1 is the number of byte needed to store the + value 9 which comes with the Serialization library for + Boost version 1.47.0. Here, the 9 value being less than 256, + one unique byte is enough to store this number. +
+

+

+ +

+Now we are done with the header, let's have a look on the serialized data ! +

+ +
    +
  • +The first variable is of boolean type with value true. Here +the PBA conventionnaly encodes the true value with the +character 'T' which is stored using the corresponding ASCII +integer value (84). As 84 is less +than 256, this uses only 1 byte: +
    1  84
    +

    + +
  • The next variable uses 1 byte to store a 8-bit +character (char) taking value 'B'. Again the PBA +scheme encodes it using its ASCII integer value +(66). This gives: +
    1  66
    +

    + +
  • Then we have an unsigned 32-bit integer with +value 42 (a fondamental constant from +the H2G2). As the natural binary 32-bit encoding of this value +(<256) only needs +1 non-zero byte, the PBA stores : +
    1  42
    +This scheme results in saving 2 bytes compared to the size of the transient value. +

    + +
  • The next variable is a single precision number with +value 7.5×106. Following the IEEE 754 standard one thus uses +32 bits to encode the sign bit, +the 8-bit exponent and +the 23-bit significant (mantissa). +As 7.5×106 can be rewritten +in +1.78813934×222, we have the +following bits contents:
    +
    +010010101111001001110000111000000

    +where the phantom bit (not stored) is conventionaly set +at 1 and the exponent is stored after +being shifted conventionaly by 27-1=127, thus +(10010101)2=(149)10 +(subscripts indicate the number base) and 149-127=22.
    + +
    +Packing these bits using 4 +bytes, we get:

    + + + + + + + + + + + + + +
    01001010111001001110000111000000
    74228225192
    +
    + +Thus the PBA streams the following 5 bytes (first the size then the content +from the least significant byte to the most significant byte), giving : +
    4 192 225 228 74
    + +
  • The next floating number 2.71828182845905 = ++1.35914091422952×2(1024-1023), +is stored using the double precision IEEE 754 64-bit pattern (using the conventionnal exponent shift 210-1=1023): +

    + + + + + + + + + + + + + + + + + + + + + +
    0100000000000101110111110000101010001011000101000101011101110100
    645191101392087116
    +
    + +Thus the PBA uses the following 9 bytes, the first one for the size (8) and the other ones +for the content (starting with the LSB): +
    8 116 87 20 139 10 191 5 64
    + +
  • Finally the string "DON'T PANIC" is stored: +
      +
    • + first is given the number of characters using the PBA + integer encoding scheme; here + 1 byte is enough to store the + value 11:
      +
      1  11
      +
    • then the array of 11 characters is given using the + corresponding ASCII codes: +

      + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      DON'T PANIC
      6879783984328065787367
      +
      +
      68  79  78  39  84  32  80 65  78  73  67 
      +
    + +
+ +

+ +

+Now the contents of the pba_0.data file can be fully +understood : +

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
+
+ +More details about the format (non finite floating point values, +negative integer numbers) will be given in +the sample codes below. +

+ + + +
+To top +
+
+ + + +
+

Examples

+ + + +

Handling special floating point values

+ +

+The PBA has been designed in the aims to handle single and double +precision floating point numbers, including non-finite and special values: +

    +
  • ±infinity +
  • NaN (not a number) +
  • denormalized numbers (i.e. floating point numbers with non-guaranteed roundoff precision) +
+

+ +

+The tutorial_pba_2.cpp sample program +illustrates the use of such special cases while serializing single precision +floating point numbers: +

+ +
+ The tutorial_pba_2.cpp source code DownloadShow/hide +
+/** 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)
+ *
+ */
+
+/**
+ * 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.
+ *
+ */
+
+#include <string>
+#include <fstream>
+#include <limits>
+
+#include <boost/archive/portable_binary_oarchive.hpp>
+#include <boost/archive/portable_binary_iarchive.hpp>
+
+int main (void)
+{
+  using namespace std;
+
+  // The name for the example data file :  
+  string filename = "pba_2.data"; 
+
+  {
+    // A normal single precision floating point number :
+    float pi = 3.14159265; 
+
+    // Single precision zeroed floating point number :
+    float zero = 0.0;
+
+    // A denormalized single precision floating point number :
+    float tiny = 1.e-40;
+    
+    // A single precision floating point number with `+Infinity' value :
+    float plus_infinity = numeric_limits<float>::infinity ();
+    
+    // A single precision floating point number with `-Infinity' value :
+    float minus_infinity = -numeric_limits<float>::infinity ();
+    
+    // A single precision `Not-a-Number' (NaN):
+    float nan = numeric_limits<float>::quiet_NaN ();
+    
+    // Open an output file stream in binary mode :
+    ofstream fout (filename.c_str (), ios_base::binary);
+    
+    {
+      // Create an output portable binary archive attached to the output file :
+      boost::archive::portable_binary_oarchive opba (fout);
+      
+      // Store (serialize) variables :
+      opba & pi & zero & tiny & plus_infinity & minus_infinity & nan;
+    }
+  }
+
+  { 
+    // Single precision floating point numbers to be loaded :
+    float x[6];
+
+    // Open an input file stream in binary mode :
+    ifstream fin (filename.c_str (), ios_base::binary);
+  
+    {
+      // Create an input portable binary archive attached to the input file :
+      boost::archive::portable_binary_iarchive ipba (fin);
+      
+      // Load (de-serialize) variables using the same 
+      // order than for serialization :
+      for (int i = 0; i < 6; ++i)
+	{
+	  ipba & x[i];
+	}
+    }
+
+    // Print :
+    for (int i = 0; i < 6; ++i)
+      {
+	cout.precision (8);
+	cout << "Loaded x[" << i << "] = " << x[i];
+	switch (fp::fpclassify(x[i]))
+	  {
+	  case FP_NAN: cout << " (NaN)"; break;
+	  case FP_INFINITE: cout << " (infinite)"; break;
+	  case FP_SUBNORMAL: cout << " (denormalized)"; break;
+	  case FP_NORMAL:  cout << " (normalized)"; break;
+	  }
+	cout << endl;
+      }
+  }
+
+  return 0;   
+}
+
+// end of tutorial_pba_2.cpp
+
+
+

+ + +

+The pba_2.data output data file thus contains the following bytes: +

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
+
+where: +
    + +
  • 127 1 9 is the standard archive header + +
  • 5 bytes are used to encode the value of π : one byte for the size=4 and 4 bytes for the content + (reversed order): +

    + + + + + + + + + + + + + +
    647315219
    01000000010010010000111111011011
    +
    + and π = +1.5707963×2(128-127) = 3.14159265. + +
  • the value zero is stored using only + one 0 byte (this is called zero optimization and this save bytes for storage). + +
  • a denormalized value then comes with only 3 bytes (note that the MSB byte is zero so it is omitted) +

    + + + + + + + + + + + + + +
    122194
    00000000000000010001011011000010
    +
    + Here the value + is +0.017014027×2(0-127) + = 0.9999946×10-40 which, as expected for + denormalized numbers, misses the requested + value 10-40 by the relative error of + magnitude 5.4×10-6, which is larger than the machine + roundoff precision (~10-7 for the single precision scheme). + +
  • the +∞ value is stored using one byte for the size + plus 4 content bytes, fulfilling the IEEE 754 standard, + i.e. maximal exponent and zero mantissa : +

    + + + + + + + + + + + + + +
    12712800
    01111111100000000000000000000000
    +
    + +
  • the -∞ value is stored using the same scheme as above, but the sign bit : +

    + + + + + + + + + + + + + +
    25512800
    11111111100000000000000000000000
    +
    + +
  • the final NaN value is stored also using one size byte plus 4 content bytes with maximal exponent and non-zero mantissa : +

    + + + + + + + + + + + + + +
    127255255255
    01111111111111111111111111111111
    +
    + See this link for an explanation of the IEEE 754 standard. + +
+

+ + + +
+To top +
+
+ + + +

Forbidding the serialization of non finite float values

+ +

+One can ask a PBA to reject non-finite values. This is done by +passing the boost::archive::no_infnan flag to the constructor +of the output archive. Note that in this case, denormalized values are +still accepted, but infinite and NaNs aren't. +

+ +

+The tutorial_pba_3.cpp sample +program that illustrates this special case: +

+ +
+ The tutorial_pba_3.cpp source code DownloadShow/hide +
+/** 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)
+ *
+ */
+
+/**
+ * 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.
+ *
+ */
+
+#include <string>
+#include <fstream>
+#include <limits>
+
+#include <boost/archive/portable_binary_oarchive.hpp>
+
+int main (void)
+{
+  using namespace std;
+
+  // The name for the example data file :  
+  string filename = "pba_3.data"; 
+
+  try 
+    {
+      // An array of single precision floating numbers:
+      float x[5]; 
+      x[0] = 3.14159;  // Pi
+      x[1] = 6.022e22; // Avogadro constant
+      x[2] = 1.6e-19;  // Electron charge magnitude
+      x[3] = 1.e-40;   // A tiny (denormalized) value
+      x[4] = numeric_limits<float>::infinity (); // This will fail while serializing...
+
+      // Open an output file stream in binary mode :
+      ofstream fout (filename.c_str (), ios_base::binary);
+    
+      {
+	// Create an output portable binary archive attached to the output file,
+	// using the special 'boost::archive::no_infnan' flag :
+	boost::archive::portable_binary_oarchive opba (fout, boost::archive::no_infnan);
+	
+	// Store (serialize) variables :
+	for (int i = 0; i < 5; ++i)
+	  {
+	    clog << "Serializing value : " << x[i] << " ... ";
+	    opba & x[i];
+	    clog << "Ok !" << endl;
+	  }
+      }
+    }
+  catch (exception & x)
+    {
+      cerr << "ERROR: " << x.what () << endl;
+      return 1;
+    }
+
+  return 0;   
+}
+
+// end of tutorial_pba_3.cpp
+
+
+

+ + +

+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: +

+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
+
+
+

+ + + +
+To top +
+
+ + + +

Serializing integer numbers

+ +

+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. +

+

The Boost library +addresses this issue through a collection of typedefs 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 boost/cstdint.hpp header file and +the typedefs defined therein. +

+

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 (short int) and then +deserialize it using another integer type (long long). +

+

+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 structs and classes and should allows the transparent switching +to another kind of archive (text, XML) thanks to the serialize template method. +

+ +

+The tutorial_pba_4.cpp sample +program illustrates the serialization/deserialization of 8-bit, +16-bit, 32-bit and 64-bit integer numbers: +

+ +
+ The tutorial_pba_4.cpp source code DownloadShow/hide +
+/** 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)
+ *
+ */
+
+/**
+ * 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.
+ *
+ */
+
+#include <string>
+#include <fstream>
+
+#include <boost/cstdint.hpp>
+#include <boost/archive/portable_binary_oarchive.hpp>
+#include <boost/archive/portable_binary_iarchive.hpp>
+
+int main (void)
+{
+  using namespace std;
+
+  // The name for the example data file :  
+  string filename = "pba_4.data"; 
+
+  {
+    // Some integer numbers :
+    bool t = true;
+    char c = 'c';
+    unsigned char u = 'u';
+    int8_t   b = -3; // char
+    uint8_t  B = +6; // unsigned char 
+    int16_t  s = -16;
+    uint16_t S = +32;
+    int32_t  l = -128;
+    uint32_t L = +127;
+    int64_t  ll = -1024;
+    uint64_t LL = +2048;
+
+    // Open an output file stream in binary mode :
+    ofstream fout (filename.c_str (), ios_base::binary);
+    
+    {
+      // Create an output portable binary archive attached to the output file :
+      boost::archive::portable_binary_oarchive opba (fout);
+      
+      // Store (serialize) variables :
+      opba & t & c & u & b & B & s & S & l & L & ll & LL;
+    }
+  }
+
+  { 
+    // Single precision floating numbers to be loaded :
+    // Some integer numbers :
+    bool t;
+    char c;
+    unsigned char 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;
+
+    // Open an input file stream in binary mode :
+    ifstream fin (filename.c_str (), ios_base::binary);
+  
+    {
+      // Create an input portable binary archive attached to the input file :
+      boost::archive::portable_binary_iarchive ipba (fin);
+      
+      // Load (de-serialize) variables using the same 
+      // order than for serialization :
+      ipba & t & c & u & b & B & s & S & l & L & ll & LL;
+    }
+
+    clog << "t  = " << t << " (bool)" << endl;
+    clog << "c  = '" << c << "' (char)" << endl;
+    clog << "u  = '" << u << "' (unsigned char)" << endl;
+    clog << "b  = " << (int) b << " (int8_t)" << endl;
+    clog << "B  = " << (int) B << " (uint8_t)" << endl;
+    clog << "s  = " << s << " (int16_t)" << endl;
+    clog << "S  = " << S << " (uint16_t)" << endl;
+    clog << "l  = " << l << " (int32_t)" << endl;
+    clog << "L  = " << L << " (uint32_t)" << endl;
+    clog << "ll = " << ll << " (int64_t)" << endl;
+    clog << "LL = " << LL << " (uint64_t)" << endl;
+  }
+
+  return 0;   
+}
+
+// end of tutorial_pba_4.cpp
+
+
+

+ + +

+The resulting PBA file is: +

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
+
+ +where: +
    + +
  • 127 1 9 is the archive header. + +
  • 1 84 indicates 1 byte to +store the true boolean value (ASCII code +is 84). + +
  • 1 99 indicates 1 byte to +store the ASCII code of character 'c' (99). + +
  • 1 117 indicates 1 byte to +store the ASCII code of character 'u' +(117). + +
  • 255 253 corresponds to the special case for a +negative integer: + 255 is the binary coding for value -1 +which means that the integer is negative and needs 1 byte to be +stored, 253, i.e. the 8-bit encoding of the signed +decimal value -3. + +
  • 1 6 indicates 1 byte to store +value 6. + +
  • 255 240 corresponds again to a negative +integer: + 255 is the byte coding for value -1 +(negative integer encoded using 1 single byte) +and 240 is the 8-bit encoding of decimal +value -16. + +
  • the same scheme is used for all remaining values in the archive : + the verification is let as an exercise. + +
+ +

+ +

Note that this coding scheme optimizes the number of streamed +bytes. Particularly, it discards the leading zero-ed bytes +(MSB) of the binary encoding of any integer value in order to save +storage. Also we recall that the exact 0 value (zero +or false for a boolean data) is always encoded using a +unique 0 byte (zero optimization). Note this approach is also +used for floating point numbers. +

+ + + +
+To top +
+
+ + + +

Using PBA serialization with a memory buffer

+ +

+In some case, we don't want to serialize some data in a file +(std::ofstream), but we simply plan to stream it in a memory buffer. +

+ +

+The tutorial_pba_5.cpp 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 : +

+ +
+ The tutorial_pba_5.cpp source code DownloadShow/hide +
+/** 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)
+ *
+ */
+
+/**
+ * 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.
+ *
+ */
+
+#include <string>
+#include <vector>
+
+#include <boost/iostreams/stream.hpp>
+#include <boost/iostreams/device/back_inserter.hpp>
+#include <boost/iostreams/device/array.hpp>
+
+#include <boost/cstdint.hpp>
+#include <boost/archive/portable_binary_oarchive.hpp>
+#include <boost/archive/portable_binary_iarchive.hpp>
+
+int main (void)
+{
+  using namespace std;
+
+  // The memory buffer is implemented using a STL vector :
+  typedef std::vector<char> buffer_type;
+  buffer_type buffer; 
+
+  {
+    // Some data to be stored :
+    bool    t = true;
+    char    c = 'c';
+    int16_t s = +16;
+    int32_t l = -128;
+    int64_t ll = +10000000000;
+    float   pi = 3.14159;
+    double  nan = numeric_limits<double>::quiet_NaN ();
+    string  hello = "World !";
+
+    buffer.reserve (1024); // pre-allocate some memory
+
+    // The output stream interface to the buffer :
+    boost::iostreams::stream<boost::iostreams::back_insert_device<buffer_type> > output_stream (buffer);
+
+    {    
+      // Create an output portable binary archive attached to the output file :
+      boost::archive::portable_binary_oarchive opba (output_stream);
+      
+      // Store (serialize) variables :
+      opba & t & c & s & l & ll & pi & nan & hello;
+    }
+
+  }
+
+  clog << "Buffer content is " << buffer.size () << " bytes : " << endl << "  ";
+  for (int i = 0; i < buffer.size (); ++i)
+    {
+      clog << (int) ((unsigned char) buffer[i]) << ' '; 
+      if ((i + 1) % 20 == 0) clog << endl << "  ";
+    }
+  clog << endl;
+
+  { 
+    // Some data to be loaded :
+    bool    t;
+    char    c;
+    int16_t s;
+    int32_t l;
+    int64_t ll;
+    float   pi;
+    double  nan;
+    string  hello;
+
+    // The input stream interface to the buffer :
+    boost::iostreams::stream<boost::iostreams::array_source> input_stream (&buffer[0], 
+									   buffer.size ());
+
+    {
+      // Create an input portable binary archive attached to the input file :
+      boost::archive::portable_binary_iarchive ipba (input_stream);
+      
+      // Load (de-serialize) variables :
+      ipba & t & c & s & l & ll & pi & nan & hello;
+    }
+
+    clog << "Loaded values from the buffer are: " << endl;
+    clog << "  t  = " << t << " (bool)" << endl;
+    clog << "  c  = '" << c << "' (char)" << endl;
+    clog << "  s  = " << s << " (int16_t)" << endl;
+    clog << "  l  = " << l << " (int32_t)" << endl;
+    clog << "  ll = " << ll << " (int64_t)" << endl;
+    clog << "  pi = " << pi << " (float)" << endl;
+    clog << "  nan = " << nan << " (double)" << endl;
+    clog << "  hello = \"" << hello << "\" (std::string)" << endl;
+  }
+
+  return 0;   
+}
+
+// end of tutorial_pba_5.cpp
+
+
+

+ + +

+After the storing of data in the archive, the content of the buffer of +characters is printed: +

+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)
+
+
+Again the PBA encoding scheme can be easily interpreted. This is let +as an exercise. +

+ +

Extra:

+

+You may have a look on the tutorial_pba_6.cpp 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. +

+ +
+ The tutorial_pba_6.cpp source code DownloadShow/hide +
+/** 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)
+ *
+ */
+
+/**
+ * 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.
+ *
+ */
+
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include <boost/utility.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/iostreams/device/back_inserter.hpp>
+#include <boost/iostreams/device/array.hpp>
+
+#include <boost/cstdint.hpp>
+#include <boost/archive/portable_binary_oarchive.hpp>
+#include <boost/archive/portable_binary_iarchive.hpp>
+
+using namespace std;
+
+/* A foo noncopyable class */
+struct foo : boost::noncopyable
+{
+  uint32_t status;
+  double   value;
+  double   special;
+
+  string to_string () const
+  {
+    ostringstream sout;
+    sout << "foo={status=" << status << "; value=" << value  << "; special=" << special<< "}";
+    return sout.str();
+  }
+
+  template<class Archive>
+  void serialize (Archive & ar, const unsigned int version)
+  {
+    ar & status;
+    ar & value;
+    ar & special;
+    return;
+  }
+
+};
+
+// A templatized copy function for Boost/Serialization equipped classes.
+// Here we use PBAs associated to a memory buffer :
+template <class Serializable>
+void copy (const Serializable & source, Serializable & target)
+{
+  namespace io = boost::iostreams;
+  namespace ba = boost::archive;
+  if (&source == &target) return; // self-copy guard
+  typedef std::vector<char> buffer_type;
+  buffer_type buffer;
+  buffer.reserve (1024);
+  {
+    io::stream<io::back_insert_device<buffer_type> > output_stream (buffer);
+    ba::portable_binary_oarchive opba (output_stream);
+    opba & source;
+  }
+  {
+    io::stream<io::array_source> input_stream (&buffer[0], buffer.size ());
+    ba::portable_binary_iarchive ipba (input_stream);
+    ipba & target;
+  }
+  return;
+}
+
+int main (void)
+{
+  // Some instance of the 'foo' class :
+  foo dummy;
+  dummy.status = 1;
+  dummy.value = 3.14159;
+  dummy.special = numeric_limits<double>::quiet_NaN ();
+  clog << "dummy is : " << dummy.to_string () << endl;
+
+  // Another instance of the 'foo' class :
+  foo clone;
+
+  /* The following instruction is forbidden because foo 
+     inherits 'boost::noncopyable' :
+   
+   clone = dummy; // this ends in a compilation error.
+   
+   */
+
+  // Anyway, we can use this workaround :
+  copy (dummy, clone);
+  clog << "clone is : " << clone.to_string () << endl;
+
+  return 0;
+}
+
+// end of tutorial_pba_6.cpp
+
+
+

+ + +

Remark : if a class has been made non-copyable 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 ! +

+ + + +
+To top +
+
+ + + +

An alternative to PBA using text or XML archives made portable

+ +

+In some circonstances, it may be useful to use the Boost text +and XML 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 text and XML 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 +tutorial_pba_7.cpp sample program below : +

+ +
+ The tutorial_pba_7.cpp source code DownloadShow/hide +
+/** 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)
+ *
+ */
+
+/**
+ * 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.
+ *
+ */
+
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <limits>
+
+using namespace std;
+
+int main (void)
+{
+  {
+    float x = numeric_limits<float>::infinity ();
+    double y = numeric_limits<double>::quiet_NaN ();
+    cout.precision (8);
+    cout << "x = " << x << endl;
+    cout.precision (16);
+    cout << "y = " << y << endl;
+  }
+
+  {
+    string input ("inf nan");
+    istringstream iss (input);
+    float x; 
+    double y;
+    iss >> x >> y;
+    if (! iss)
+      {
+	cerr << "Cannot read 'x' or 'y' : non finite values are not supported !" << endl;
+      }
+  }
+  return 0;
+}
+
+// end of tutorial_pba_7.cpp
+
+
+

+ + +

+Depending on the system, one can get some various representation +respectively for the infinity and NaN values : +

    +
  • typically on Windows : +
    +1.#INF
    +
    +and +
    +-1.#IND
    +
    +
  • and on Linux : +
    +inf
    +
    +and +
    +nan
    +
    + +
+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 ! +

+ +

+Hopefully this issue can be solved by configuring the I/O streams with +some special locale features provided by Boost +(see this +link). +

+ +

+The tutorial_pba_8.cpp program +shows how this can be achieved through the use of special resources +from the boost/archive/codecvt_null.hpp and +boost/math/special_functions/nonfinite_num_facets.hpp headers : +

+ +
+ The tutorial_pba_8.cpp source code DownloadShow/hide +
+/** 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)
+ *
+ */
+
+/**
+ * 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.
+ *
+ */
+
+#include <string>
+#include <fstream>
+#include <limits>
+#include <locale>
+
+#include <boost/cstdint.hpp>
+#include <boost/archive/xml_oarchive.hpp>
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/serialization/nvp.hpp>
+#include <boost/archive/codecvt_null.hpp>
+#include <boost/math/special_functions/nonfinite_num_facets.hpp>
+
+using namespace std;
+
+void do_text_out (void)
+{
+  // The name for the example data text file :  
+  string filename = "pba_8.txt"; 
+
+  // Some variables of various primitive types :
+  bool        b         = true;
+  char        c         = 'B';
+  uint32_t    answer    = 42;
+  float       value     = numeric_limits<float>::infinity ();
+  double      precision = numeric_limits<double>::quiet_NaN ();
+  string      question  = "What makes you think she's a witch?";
+  
+  // Open an output file stream :
+  ofstream fout (filename.c_str ());
+
+  // Prepare the output file stream for inf/NaN support :
+  locale default_locale (locale::classic (),
+			 new boost::archive::codecvt_null<char>);
+  locale infnan_locale (default_locale,
+			new boost::math::nonfinite_num_put<char>);
+  fout.imbue (infnan_locale);
+  
+  {
+    // Create an output text archive attached to the output file :
+    boost::archive::text_oarchive ota (fout, boost::archive::no_codecvt);
+    
+    // Store (serializing) variables :
+    ota & b & c & answer & value & precision & question;
+  }
+
+  return;   
+}
+
+void do_xml_out (void)
+{
+  // The name for the example data XML file :  
+  string filename = "pba_8.xml"; 
+
+  // Some variables of various primitive types :
+  bool        b         = true;
+  char        c         = 'B';
+  uint32_t    answer    = 42;
+  float       value     = numeric_limits<float>::infinity ();
+  double      precision = numeric_limits<double>::quiet_NaN ();
+  string      question  = "What makes you think she's a witch?";
+  
+  // Open an output file stream :
+  ofstream fout (filename.c_str ());
+
+  // Prepare the output file stream for inf/NaN support :
+  locale default_locale (locale::classic (),
+			 new boost::archive::codecvt_null<char>);
+  locale infnan_locale (default_locale,
+			new boost::math::nonfinite_num_put<char>);
+  fout.imbue (infnan_locale);
+   
+  {
+    // Create an output text archive attached to the output file :
+    boost::archive::xml_oarchive oxa (fout, boost::archive::no_codecvt);
+    
+    // Store (serializing) variables :
+    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);
+  }
+
+  return;   
+}
+
+int main (void)
+{
+  do_text_out ();
+  do_xml_out ();
+  return 0;
+}
+
+// end of tutorial_pba_8.cpp
+
+
+

+ + +

+The program creates two output files : +

    +
  • pba_8.txt stores a text archive with + non finite floating point values : +
    +22 serialization::archive 9 1 66 42 inf nan 35 What makes you think she's a witch?
    +
    +
    +
  • pba_8.xml which stored the equivalent content + using the XML archive format : + +
    +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
    +<!DOCTYPE boost_serialization>
    +<boost_serialization signature="serialization::archive" version="9">
    +<b>1</b>
    +<c>66</c>
    +<answer>42</answer>
    +<value>inf</value>
    +<precision>nan</precision>
    +<question>What makes you think she&apos;s a witch?</question>
    +</boost_serialization>
    +
    +
    + + +
+

+ +

+The tutorial_pba_9.cpp program +deserializes the data from the text and XML archive files (respectively +pba_8.txt and pba_8.xml) and prints the restored variables : +

+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?"
+
+
+

+ +

+

+ The tutorial_pba_9.cpp source code DownloadShow/hide +
+/** 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)
+ *
+ */
+
+/**
+ * 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.
+ *
+ */
+
+#include <string>
+#include <fstream>
+#include <limits>
+#include <locale>
+
+#include <boost/cstdint.hpp>
+#include <boost/archive/xml_iarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/serialization/nvp.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/archive/codecvt_null.hpp>
+#include <boost/math/special_functions/nonfinite_num_facets.hpp>
+
+using namespace std;
+
+void do_text_in (void)
+{
+  // The name for the example data text file :  
+  string filename = "pba_8.txt"; 
+  // Some variables of various primitive types :
+  bool        b;
+  char        c;
+  uint32_t    answer;
+  float       value;
+  double      precision;
+  string      question;
+  
+  // Open an input file stream :
+  ifstream fin (filename.c_str ());
+
+  // Prepare the input file stream for inf/NaN support :
+  locale default_locale (locale::classic (),
+			 new boost::archive::codecvt_null<char>);
+  locale infnan_locale (default_locale,
+			new boost::math::nonfinite_num_get<char>);
+  fin.imbue (infnan_locale);
+ 
+  {
+    // Create an input text archive attached to the input file :
+    boost::archive::text_iarchive ita (fin, boost::archive::no_codecvt);
+    
+    // Store (serializing) variables :
+    ita & b & c & answer & value & precision & question;
+  }
+
+  clog << "Loaded values from text archive are: " << endl;
+  clog << "  b         = " << b << endl;
+  clog << "  c         = '" << c << "'" <<  endl;
+  clog << "  answer    = " << answer << endl;
+  clog << "  value     = " << value << endl;
+  clog << "  precision = " << precision << endl;
+  clog << "  question  = \"" << question << "\"" << endl;
+
+  return;   
+}
+
+void do_xml_in (void)
+{
+  // The name for the example data text file :  
+  string filename = "pba_8.xml"; 
+
+  // Some variables of various primitive types :
+  bool        b;
+  char        c;
+  uint32_t    answer;
+  float       value;
+  double      precision;
+  string      question;
+  
+  // Open an input file stream :
+  ifstream fin (filename.c_str ());
+
+  // Prepare the input file stream for inf/NaN support :
+  locale default_locale (locale::classic (),
+			 new boost::archive::codecvt_null<char>);
+  locale infnan_locale (default_locale,
+			new boost::math::nonfinite_num_get<char>);
+  fin.imbue (infnan_locale);
+
+  {
+    // Create an output text archive attached to the output file :
+    boost::archive::xml_iarchive ixa (fin, boost::archive::no_codecvt);
+    
+    // Store (serializing) variables :
+    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 << "Loaded values from XML archive are: " << endl;
+  clog << "  b         = " << b << endl;
+  clog << "  c         = '" << c << "'" <<  endl;
+  clog << "  answer    = " << answer << endl;
+  clog << "  value     = " << value << endl;
+  clog << "  precision = " << precision << endl;
+  clog << "  question  = \"" << question << "\"" << endl;
+
+  return;   
+}
+
+int main (void)
+{
+  do_text_in ();
+  do_xml_in ();
+  return 0;
+}
+
+// end of tutorial_pba_9.cpp
+
+
+

+ +

+ + + +
+To top +
+
+ + + +

Using PBA serialization associated with on-the-fly (de)compressed file streams

+ +

+The tutorial_pba_10.cpp 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: +

+ +
+ The tutorial_pba_10.cpp source code DownloadShow/hide +
+/** 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)
+ *
+ */
+
+/**
+ * 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.
+ *
+ */
+
+#include <string>
+#include <fstream>
+#include <limits>
+#include <vector>
+
+#include <boost/cstdint.hpp>
+#include <boost/archive/portable_binary_oarchive.hpp>
+#include <boost/archive/portable_binary_iarchive.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/iostreams/filter/gzip.hpp>
+#include <boost/serialization/access.hpp>
+#include <boost/serialization/vector.hpp>
+
+using namespace std;
+
+class data_type
+{
+private:
+  friend class boost::serialization::access;
+  template<class Archive>
+  void serialize (Archive & ar, const unsigned int version);
+public:
+  void print (ostream & out, const string & title) const;
+public:
+  vector<double> values;
+  data_type ();
+};
+
+data_type::data_type () : values ()
+{
+  return;
+}
+
+void data_type::print (ostream & out, const string & title) const
+{
+  out << endl;
+  out << title << " :" << endl;
+  for (int i = 0; i < this->values.size (); ++i)
+    {
+      out.precision (16);
+      out.width (18);
+      out << this->values [i] << ' ' ;
+      if ((i%4) == 3) clog << endl;
+    }
+  out << endl;
+  return;
+}
+  
+template<class Archive>
+void data_type::serialize (Archive & ar, const unsigned int version)
+{
+  ar & values;
+  return;
+}
+
+void do_gzipped_out (void)
+{
+  // The name for the output data file :  
+  string filename = "pba_10.data.gz"; 
+
+  // A data structure to be stored :
+  data_type my_data;
+
+  // Fill the vector with arbitrary (possibly non-finite) values :
+  size_t dim = 1000;
+  my_data.values.reserve (dim);
+  for (int i = 0; i < dim; ++i)
+    {      
+      double val = (i + 1) * (1.0 + 3 * numeric_limits<double>::epsilon ());
+      if (i == 4) val = numeric_limits<double>::quiet_NaN ();
+      if (i == 23) val = numeric_limits<double>::infinity ();
+      if (i == 73) val = -numeric_limits<double>::infinity ();
+      if (i == 90) val = 0.0;
+      my_data.values.push_back (val);
+    }
+
+  // Print:
+  my_data.print (clog, "Stored data");
+
+  // Create an output filtering stream :
+  boost::iostreams::filtering_ostream zout;
+  zout.push (boost::iostreams::gzip_compressor ());
+  
+  // Open an output file stream in binary mode :
+  ofstream fout (filename.c_str (), ios_base::binary);
+  zout.push (fout);
+
+  // Save to PBA :
+  {
+    // Create an output portable binary archive attached to the output file :
+    boost::archive::portable_binary_oarchive opba (zout);
+    
+    // Store (serializing) the data :
+    opba & my_data;
+  }
+
+  // Clean termination of the streams :
+  zout.flush ();
+  zout.reset ();
+
+  return;   
+}
+
+void do_gzipped_in (void)
+{
+  // The name for the input data file :  
+  string filename = "pba_10.data.gz"; 
+
+  // A data structure to be loaded :
+  data_type my_data;
+
+  // Create an input filtering stream :
+  boost::iostreams::filtering_istream zin;
+  zin.push (boost::iostreams::gzip_decompressor ());
+  
+  // Open an input file stream in binary mode :
+  ifstream fin (filename.c_str (), ios_base::binary);
+  zin.push (fin);
+
+  // Load from PBA :
+  {
+    // Create an input portable binary archive attached to the input file :
+    boost::archive::portable_binary_iarchive ipba (zin);
+    
+    // Load (deserializing) the data :
+    ipba & my_data;
+  }
+
+  // Print:
+  my_data.print (clog, "Loaded data");
+
+  return;   
+}
+
+int main (void)
+{
+  do_gzipped_out (); 
+  do_gzipped_in ();
+  return 0;
+}
+
+// end of tutorial_pba_10.cpp
+
+
+

+ + +

The resulting compressed pba_10.data.gz file contains 1,574 bytes. +This has to be compared with the size of the plain (uncompressed) +binary archive which equals 9,001 bytes: + +

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
+...
+
+ +which can be interpreted as : +
    +
  • 3 bytes for the usual archive header : 127 1 +9, +
  • 2 zero-optimized bytes to store the class ID + and the class version :0 0, +
  • 3 bytes to store the size of the vector (1000) using the PBA +representation of integers (2 232 3), +
  • 1 zero-optimized byte to store the class version of the +objects stored in the STL vector (here +the primitive double type) : 0, +
  • 999 non-zero double precision floating point values (including non-finite values) each using 9 bytes (1 byte for +the size and 8 bytes for the content) : 8 ? ? ? ? ? +? ? ?, +
  • 1 zero floating point value that uses only one zero-optimized byte : 0. +
+Thus one here achieves a very interesting compression level. +

+

+It is also possible to use BZIP2 in a similar fashion +(using ressources from the boost/iostreams/filter/bzip2.hpp header +in place of boost/iostreams/filter/gzip.hpp). +

+ + + +
+To top +
+
+ + +

A simple PBA versus text archive benchmark test

+ +

+The tutorial_pba_11.cpp 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 (107) +random double values and prints the associated (de)serialization time for both kinds of archives: +

+ +
+ The tutorial_pba_11.cpp source code DownloadShow/hide +
+/** 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)
+ *
+ */
+
+/**
+ * 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.
+ *
+ */
+
+#include <string>
+#include <fstream>
+#include <vector>
+
+#include <boost/archive/portable_binary_oarchive.hpp>
+#include <boost/archive/portable_binary_iarchive.hpp>
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/serialization/access.hpp>
+#include <boost/serialization/vector.hpp>
+#include <boost/random/mersenne_twister.hpp>
+#include <boost/random/uniform_real_distribution.hpp>
+#include <boost/timer.hpp>
+
+using namespace std;
+
+class data_type
+{
+private:
+  friend class boost::serialization::access;
+  template<class Archive>
+  void serialize (Archive & ar, const unsigned int version);
+public:
+  void print (ostream & out, const string & title) const;
+public:
+  vector<double> values;
+  data_type ();
+};
+
+data_type::data_type () : values ()
+{
+  return;
+}
+
+void data_type::print (ostream & out, const string & title) const
+{
+  out << endl;
+  out << title << " :" << endl;
+  bool skip = false;
+  for (int i = 0; i < this->values.size (); ++i)
+    {
+      if ((i >= 12) && (i < (int) this->values.size () - 8)) 
+	{
+	  if (! skip) out << " ..." << endl;
+	  skip = true;
+	  continue;
+	}
+      out.precision (16);
+      out.width (18);
+      out << this->values [i] << ' ' ;
+      if ((i%4) == 3) clog << endl;
+    }
+  out << endl;
+  return;
+}
+  
+template<class Archive>
+void data_type::serialize (Archive & ar, const unsigned int version)
+{
+  ar & values;
+  return;
+}
+
+double do_pba_out (const data_type & a_data)
+{
+  string filename = "pba_11.data"; 
+  ofstream fout (filename.c_str (), ios_base::binary);
+  boost::timer io_timer;    
+  {
+    boost::archive::portable_binary_oarchive opba (fout);
+    opba & a_data;
+  }
+  return io_timer.elapsed ();
+}
+
+double do_pba_in (data_type & a_data)
+{
+  string filename = "pba_11.data"; 
+  ifstream fin (filename.c_str (), ios_base::binary);
+  boost::timer io_timer;    
+  {
+    boost::archive::portable_binary_iarchive ipba (fin);
+    ipba & a_data;
+  }
+  return io_timer.elapsed ();
+}
+
+double do_text_out (const data_type & a_data)
+{
+  string filename = "pba_11.txt"; 
+  ofstream fout (filename.c_str ());
+  boost::timer io_timer;    
+  {
+    boost::archive::text_oarchive ota (fout);
+    ota & a_data;
+  }
+  return io_timer.elapsed ();
+}
+
+double do_text_in (data_type & a_data)
+{
+  string filename = "pba_11.txt"; 
+  ifstream fin (filename.c_str ());
+  boost::timer io_timer;    
+  {
+    boost::archive::text_iarchive ita (fin);
+    ita & a_data;
+  }
+  return io_timer.elapsed ();
+}
+
+int main (void)
+{
+  double elapsed_time_pba_out; 
+  double elapsed_time_text_out; 
+  double elapsed_time_pba_in; 
+  double elapsed_time_text_in; 
+  data_type my_data; // A data structure to be stored then loaded.
+
+  {
+    // Fill the vector with random values :
+    size_t dim = 10000000;
+    my_data.values.reserve (dim);
+    boost::random::mt19937 rng;
+    boost::random::uniform_real_distribution<> flat (0.0, 100.0);
+    for (int i = 0; i < dim; ++i)
+      {      
+	double val = flat (rng);
+	my_data.values.push_back (val);
+      }
+    my_data.print (clog, "Stored data in PBA and text archive");
+  }
+
+  {
+    // Store in PBA :
+    elapsed_time_pba_out = do_pba_out (my_data);
+  }
+
+  {
+    // Store in text archive :
+    elapsed_time_text_out = do_text_out (my_data);
+  }     
+
+  {
+    my_data.values.clear ();
+    // Load from PBA :
+    elapsed_time_pba_in = do_pba_in (my_data);
+    my_data.print (clog, "Loaded data from PBA");
+  }
+
+  {
+    my_data.values.clear ();
+    // Load from text archive :
+    elapsed_time_text_in = do_text_in (my_data);
+    my_data.print (clog, "Loaded data from text archive");
+  }
+  
+  clog << "PBA  store I/O elapsed time : " << elapsed_time_pba_out  << " (second)" << endl;
+  clog << "Text store I/O elapsed time : " << elapsed_time_text_out << " (second)" << endl;  
+  clog << "PBA  load  I/O elapsed time : " << elapsed_time_pba_in   << " (second)" << endl;
+  clog << "Text load  I/O elapsed time : " << elapsed_time_text_in  << " (second)" << endl;
+
+  return 0;
+}
+
+// end of tutorial_pba_11.cpp
+
+
+

+ + +

On a 1.60 GHz processor running gcc 4.5.2 on Linux 2.6.38, the result is the following: +

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)
+
+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. +

+ +

+One can also consider the sizes of the resulting archive files: +

    +
  • pba_11.data (PBA) : 90,000,010 bytes +
  • pba_11.txt (text archive) : 189,000,040 bytes +
+The PBA allows to save a typical factor 2 in storage space compared to text archive. +This is another strong argument for using PBA. +

+ + + +
+To top +
+
+ + + +
+

Revised 2011-11-07 +

© Copyright François Mauger, +Christian Pfligersdorffer 2011.
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +
+

+ + + + + diff --git a/include/boost/archive/portable_archive.hpp b/include/boost/archive/portable_archive.hpp new file mode 100755 index 00000000..ec8149cc --- /dev/null +++ b/include/boost/archive/portable_archive.hpp @@ -0,0 +1,35 @@ +/*****************************************************************************/ +/** + * \file portable_archive.hpp + * \brief Needed for unit tests on portable archives. + * \author christian.pfligersdorffer@gmx.at + * + * Header for testing portable archives with all of the serialization tests. + * Before use copy all hpp files from this directory to your boost folder + * boost_.../libs/serialization/test and run from there a visual studio + * prompt with b2 oder bjam -sBOOST_ARCHIVE_LIST=portable_archive.hpp + * + * \note Since portable archives version 5.0 we depend on program_options! + * Edit libs/serialization/test/Jamfile.v2 and change the requirements to + * : requirements /boost/filesystem /boost/program_options + */ +/****************************************************************************/ + +#pragma warning( disable:4217 4127 4310 4244 4800 4267 ) + +// portable_archive test header +// include output archive header +#include "portable_oarchive.hpp" +// set name of test output archive +typedef eos::portable_oarchive test_oarchive; +// set name of test output stream +typedef std::ofstream test_ostream; + +// repeat the above for input archive +#include "portable_iarchive.hpp" +typedef eos::portable_iarchive test_iarchive; +typedef std::ifstream test_istream; + +// define open mode for streams +// binary archives should use std::ios_base::binary +#define TEST_STREAM_FLAGS std::ios_base::binary diff --git a/include/boost/archive/portable_archive_exception.hpp b/include/boost/archive/portable_archive_exception.hpp new file mode 100755 index 00000000..719fc004 --- /dev/null +++ b/include/boost/archive/portable_archive_exception.hpp @@ -0,0 +1,93 @@ +/*****************************************************************************/ +/** + * \file portable_archive_exception.hpp + * \brief Provides error handling and constants. + * \author christian.pfligersdorffer@gmx.at + * + * Portable archive exceptions derive from the boost archive exceptions + * and add failure causes specific to the portable binary usecase. + * + * Additionally this header serves as common include for important + * constants or typedefs. + */ +/****************************************************************************/ + +#pragma once + +#include +#include +#include + +namespace eos { + + // this value is written to the top of the stream + const signed char magic_byte = 'e' | 'o' | 's'; + + // flag for fp serialization + const unsigned no_infnan = 64; + + // integral type for the archive version + #if BOOST_VERSION < 104400 + typedef boost::archive::version_type archive_version_type; + #else + typedef boost::archive::library_version_type archive_version_type; + #endif + + // version of the linked boost archive library + const archive_version_type archive_version( + #if BOOST_VERSION < 103700 + boost::archive::ARCHIVE_VERSION() + #else + boost::archive::BOOST_ARCHIVE_VERSION() + #endif + ); + + /** + * \brief Exception being thrown when serialization cannot proceed. + * + * There are several situations in which the portable archives may fail and + * hence throw an exception: + * -# deserialization of an integer value that exceeds the range of the type + * -# (de)serialization of inf/nan through an archive with no_infnan flag set + * -# deserialization of a denormalized value without the floating point type + * supporting denormalized numbers + * + * Note that this exception will also be thrown if you mixed up your stream + * position and accidentially interpret some value for size data (in this case + * the reported size will be totally amiss most of the time). + */ + class portable_archive_exception : public boost::archive::archive_exception + { + std::string msg; + + public: + //! type size is not large enough for deserialized number + portable_archive_exception(signed char invalid_size) + : boost::archive::archive_exception(other_exception) + , msg("requested integer size exceeds type size: ") + { + msg += boost::lexical_cast(invalid_size); + } + + //! negative number in unsigned type + portable_archive_exception() + : boost::archive::archive_exception(other_exception) + , msg("cannot read a negative number into an unsigned type") + { + } + + //! serialization of inf, nan and denormals + template + portable_archive_exception(const T& abnormal) + : boost::archive::archive_exception(other_exception) + , msg("serialization of illegal floating point value: ") + { + msg += boost::lexical_cast(abnormal); + } + + //! override the base class function with our message + const char* what() const throw() { return msg.c_str(); } + ~portable_archive_exception() throw() {} + }; + +} // namespace eos diff --git a/include/boost/archive/portable_iarchive.hpp b/include/boost/archive/portable_iarchive.hpp new file mode 100755 index 00000000..67763f22 --- /dev/null +++ b/include/boost/archive/portable_iarchive.hpp @@ -0,0 +1,487 @@ +/*****************************************************************************/ +/** + * \file portable_iarchive.hpp + * \brief Provides an archive to read from portable binary files. + * \author christian.pfligersdorffer@gmx.at + * \version 5.1 + * + * This pair of archives brings the advantages of binary streams to the cross + * platform boost::serialization user. While being almost as fast as the native + * binary archive it allows its files to be exchanged between cpu architectures + * using different byte order (endianness). Speaking of speed: in serializing + * numbers the (portable) binary approach is approximately ten times faster than + * the ascii implementation (that is inherently portable)! + * + * Based on the portable archive example by Robert Ramey this implementation + * uses Beman Dawes endian library and fp_utilities from Johan Rade, both being + * in boost since 1.36. Prior to that you need to add them both (header only) + * to your boost directory before you're able to use the archives provided. + * Our archives have been tested successfully for boost versions 1.33 to 1.49! + * + * \note Correct behaviour has so far been confirmed using PowerPC-32, x86-32 + * and x86-64 platforms featuring different byte order. So there is a good + * chance it will instantly work for your specific setup. If you encounter + * problems or have suggestions please contact the author. + * + * \note Version 5.1 is now compatible with boost up to version 1.59. Thanks to + * ecotax for pointing to the issue with shared_ptr_helper. + * + * \note Version 5.0 is now compatible with boost up to version 1.49 and enables + * serialization of std::wstring by converting it to/from utf8 (thanks to + * Arash Abghari for this suggestion). With that all unit tests from the + * serialization library pass again with the notable exception of user + * defined primitive types. Those are not supported and as a result any + * user defined type to be used with the portable archives are required + * to be at least object_serializable. + * + * \note Version 4.2 maintains compatibility with the latest boost 1.45 and adds + * serialization of special floating point values inf and NaN as proposed + * by Francois Mauger. + * + * \note Version 4.1 makes the archives work together with boost 1.40 and 1.41. + * Thanks to Francois Mauger for his suggestions. + * + * \note Version 4 removes one level of the inheritance hierarchy and directly + * builds upon binary primitive and basic binary archive, thereby fixing + * the last open issue regarding array serialization. Thanks to Robert + * Ramey for the hint. + * + * \note A few fixes introduced in version 3.1 let the archives pass all of the + * serialization tests. Thanks to Sergey Morozov for running the tests. + * Wouter Bijlsma pointed out where to find the fp_utilities and endian + * libraries headers inside the boost distribution. I would never have + * found them so thank him it works out of the box since boost 1.36. + * + * \note With Version 3.0 the archives have been made portable across different + * boost versions. For that purpose a header is added to the data that + * supplies the underlying serialization library version. Backwards + * compatibility is maintained by assuming library version boost 1.33 if + * the iarchive is created using the no_header flag. Whether a header is + * present or not can be guessed by peeking into the stream: the header's + * first byte is the magic number 127 coinciding with 'e'|'o'|'s' :-) + * + * \note Version 2.1 removes several compiler warnings and enhances floating + * point diagnostics to inform the user if some preconditions are violated + * on his platform. We do not strive for the universally portable solution + * in binary floating point serialization as desired by some boost users. + * Instead we support only the most widely used IEEE 754 format and try to + * detect when requirements are not met and hence our approach must fail. + * Contributions we made by Johan Rade and Ákos Maróy. + * + * \note Version 2.0 fixes a serious bug that effectively transformed most + * of negative integral values into positive values! For example the two + * numbers -12 and 234 were stored in the same 8-bit pattern and later + * always restored to 234. This was fixed in this version in a way that + * does not change the interpretation of existing archives that did work + * because there were no negative numbers. The other way round archives + * created by version 2.0 and containing negative numbers will raise an + * integer type size exception when reading it with version 1.0. Thanks + * to Markus Frohnmaier for testing the archives and finding the bug. + * + * \copyright The boost software license applies. + */ +/*****************************************************************************/ + +#pragma once + +#include + +// basic headers +#include +#include +#include +#include + +#if BOOST_VERSION >= 103500 && BOOST_VERSION < 105600 +#include +#endif + +// funny polymorphics +#if BOOST_VERSION < 103500 +#include +#define POLYMORPHIC(T) boost::archive::detail::polymorphic_iarchive_impl + +#elif BOOST_VERSION < 103600 +#include +#define POLYMORPHIC(T) boost::archive::detail::polymorphic_iarchive_dispatch + +#else +#include +#define POLYMORPHIC(T) boost::archive::detail::polymorphic_iarchive_route +#endif + +// endian and fpclassify +#if BOOST_VERSION < 103600 +#include +#include +#elif BOOST_VERSION < 104800 +#include +#include +#else +#include +#include +#endif + +// namespace alias +#if BOOST_VERSION < 103800 +namespace fp = boost::math; +#else +namespace fp = boost::spirit::math; +#endif + +// namespace alias endian +#if BOOST_VERSION < 104800 +namespace endian = boost::detail; +#else +namespace endian = boost::spirit::detail; +#endif + +#if BOOST_VERSION >= 104500 && !defined BOOST_NO_STD_WSTRING +// used for wstring to utf8 conversion +#include +#include +#endif + +// generic type traits for numeric types +#include +#include +#include +#include + +#include "portable_archive_exception.hpp" + +// hint from Johan Rade: on VMS there is still support for +// the VAX floating point format and this macro detects it +#if defined(__vms) && defined(__DECCXX) && !__IEEE_FLOAT +#error "VAX floating point format is not supported!" +#endif + +namespace eos { + + // forward declaration + class portable_iarchive; + + typedef boost::archive::basic_binary_iprimitive< + portable_iarchive + #if BOOST_VERSION < 103400 + , std::istream + #else + , std::istream::char_type + , std::istream::traits_type + #endif + > portable_iprimitive; + + /** + * \brief Portable binary input archive using little endian format. + * + * This archive addresses integer size, endianness and floating point types so + * that data can be transferred across different systems. There may still be + * constraints as to what systems are compatible and the user will have to take + * care that e.g. a very large int being saved on a 64 bit machine will result + * in a portable_archive_exception if loaded into an int on a 32 bit system. + * A possible workaround to this would be to use fixed types like + * boost::uint64_t in your serialization structures. + * + * \note The class is based on the portable binary example by Robert Ramey and + * uses Beman Dawes endian library plus fp_utilities by Johan Rade. + */ + class portable_iarchive : public portable_iprimitive + + // the example derives from common_oarchive but that lacks the + // load_override functions so we chose to stay one level higher + , public boost::archive::basic_binary_iarchive + + #if BOOST_VERSION >= 103500 && BOOST_VERSION < 105600 + // mix-in helper class for serializing shared_ptr + , public boost::archive::detail::shared_ptr_helper + #endif + { + // only needed for Robert's hack in basic_binary_iarchive::init + friend class boost::archive::basic_binary_iarchive; + + // workaround for gcc: use a dummy struct + // as additional argument type for overloading + template struct dummy { dummy(int) {}}; + + // loads directly from stream + inline signed char load_signed_char() + { + signed char c; + portable_iprimitive::load(c); + return c; + } + + // archive initialization + void init(unsigned flags) + { + using namespace boost::archive; + archive_version_type input_library_version(3); + + // it is vital to have version information! + // if we don't have any we assume boost 1.33 + if (flags & no_header) + set_library_version(input_library_version); + + // extract and check the magic eos byte + else if (load_signed_char() != magic_byte) + throw archive_exception(archive_exception::invalid_signature); + + else + { + // extract version information + operator>>(input_library_version); + + // throw if file version is newer than we are + if (input_library_version > archive_version) + throw archive_exception(archive_exception::unsupported_version); + + // else set the library version accordingly + else set_library_version(input_library_version); + } + } + + public: + /** + * \brief Constructor on a stream using ios::binary mode! + * + * We cannot call basic_binary_iprimitive::init which tries to detect + * if the binary archive stems from a different platform by examining + * type sizes. + * + * We could have called basic_binary_iarchive::init which would create + * the boost::serialization standard archive header containing also the + * library version. Due to efficiency we stick with our own. + */ + portable_iarchive(std::istream& is, unsigned flags = 0) + #if BOOST_VERSION < 103400 + : portable_iprimitive(is, flags & boost::archive::no_codecvt) + #else + : portable_iprimitive(*is.rdbuf(), flags & boost::archive::no_codecvt) + #endif + , boost::archive::basic_binary_iarchive(flags) + { + init(flags); + } + + #if BOOST_VERSION >= 103400 + portable_iarchive(std::streambuf& sb, unsigned flags = 0) + : portable_iprimitive(sb, flags & boost::archive::no_codecvt) + , boost::archive::basic_binary_iarchive(flags) + { + init(flags); + } + #endif + + //! Load narrow strings. + void load(std::string& s) + { + portable_iprimitive::load(s); + } + + #ifndef BOOST_NO_STD_WSTRING + /** + * \brief Load wide strings. + * + * This is rather tricky to get right for true portability as there + * are so many different character encodings around. However, wide + * strings that are encoded in one of the Unicode schemes only need + * to be _transcoded_ which is a lot easier actually. + * + * We generate the output string to be encoded in the system's native + * format, ie. UTF-16 on Windows and UTF-32 on Linux machines. Don't + * know about Mac here so I can't really say about that. + */ + void load(std::wstring& s) + { + std::string utf8; + load(utf8); + s = boost::from_utf8(utf8); + } + #endif + + /** + * \brief Loading bool type. + * + * Byte pattern is same as with integer types, so this function + * is somewhat redundant but treating bool as integer generates + * a lot of compiler warnings. + * + * \note If you cannot compile your application and it says something + * about load(bool) cannot convert your type A& into bool& then you + * should check your BOOST_CLASS_IMPLEMENTATION setting for A, as + * portable_archive is not able to handle custom primitive types in + * a general manner. + */ + void load(bool& b) + { + switch (signed char c = load_signed_char()) + { + case 0: b = false; break; + case 1: b = load_signed_char(); break; + default: throw portable_archive_exception(c); + } + } + + /** + * \brief Load integer types. + * + * First we load the size information ie. the number of bytes that + * hold the actual data. Then we retrieve the data and transform it + * to the original value by using load_little_endian. + */ + template + typename boost::enable_if >::type + load(T & t, dummy<2> = 0) + { + // get the number of bytes in the stream + if (signed char size = load_signed_char()) + { + // check for negative value in unsigned type + if (size < 0 && boost::is_unsigned::value) + throw portable_archive_exception(); + + // check that our type T is large enough + else if ((unsigned) abs(size) > sizeof(T)) + throw portable_archive_exception(size); + + // reconstruct the value + T temp = size < 0 ? -1 : 0; + load_binary(&temp, abs(size)); + + // load the value from little endian - it is then converted + // to the target type T and fits it because size <= sizeof(T) + t = endian::load_little_endian(&temp); + } + + else t = 0; // zero optimization + } + + /** + * \brief Load floating point types. + * + * We simply rely on fp_traits to set the bit pattern from the (unsigned) + * integral type that was stored in the stream. Francois Mauger provided + * standardized behaviour for special values like inf and NaN, that need to + * be serialized in his application. + * + * \note by Johan Rade (author of the floating point utilities library): + * Be warned that the math::detail::fp_traits::type::get_bits() function + * is *not* guaranteed to give you all bits of the floating point number. It + * will give you all bits if and only if there is an integer type that has + * the same size as the floating point you are copying from. It will not + * give you all bits for double if there is no uint64_t. It will not give + * you all bits for long double if sizeof(long double) > 8 or there is no + * uint64_t. + * + * The member fp_traits::type::coverage will tell you whether all bits + * are copied. This is a typedef for either math::detail::all_bits or + * math::detail::not_all_bits. + * + * If the function does not copy all bits, then it will copy the most + * significant bits. So if you serialize and deserialize the way you + * describe, and fp_traits::type::coverage is math::detail::not_all_bits, + * then your floating point numbers will be truncated. This will introduce + * small rounding off errors. + */ + template + typename boost::enable_if >::type + load(T & t, dummy<3> = 0) + { + typedef typename fp::detail::fp_traits::type traits; + + // if you end here there are three possibilities: + // 1. you're serializing a long double which is not portable + // 2. you're serializing a double but have no 64 bit integer + // 3. your machine is using an unknown floating point format + // after reading the note above you still might decide to + // deactivate this static assert and try if it works out. + typename traits::bits bits; + BOOST_STATIC_ASSERT(sizeof(bits) == sizeof(T)); + BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + + load(bits); + traits::set_bits(t, bits); + + // if the no_infnan flag is set we must throw here + if (get_flags() & no_infnan && !fp::isfinite(t)) + throw portable_archive_exception(t); + + // if you end here your floating point type does not support + // denormalized numbers. this might be the case even though + // your type conforms to IEC 559 (and thus to IEEE 754) + if (std::numeric_limits::has_denorm == std::denorm_absent + && fp::fpclassify(t) == (int) FP_SUBNORMAL) // GCC4 + throw portable_archive_exception(t); + } + + // in boost 1.44 version_type was splitted into library_version_type and + // item_version_type, plus a whole bunch of additional strong typedefs. + template + typename boost::disable_if >::type + load(T& t, dummy<4> = 0) + { + // we provide a generic load routine for all types that feature + // conversion operators into an unsigned integer value like those + // created through BOOST_STRONG_TYPEDEF(X, some unsigned int) like + // library_version_type, collection_size_type, item_version_type, + // class_id_type, object_id_type, version_type and tracking_type + load((typename boost::uint_t::least&)(t)); + } + }; + + // polymorphic portable binary iarchive typedef + typedef POLYMORPHIC(portable_iarchive) polymorphic_portable_iarchive; + #undef POLYMORPHIC + +} // namespace eos + +// this is required by export which registers all of your +// classes with all the inbuilt archives plus our archive. +#if BOOST_VERSION < 103500 +#define BOOST_ARCHIVE_CUSTOM_IARCHIVE_TYPES eos::portable_iarchive +#else +BOOST_SERIALIZATION_REGISTER_ARCHIVE(eos::portable_iarchive) +BOOST_SERIALIZATION_REGISTER_ARCHIVE(eos::polymorphic_portable_iarchive) +#endif + +// if you include this header multiple times and your compiler is picky +// about multiple template instantiations (eg. gcc is) then you need to +// define NO_EXPLICIT_TEMPLATE_INSTANTIATION before every include but one +// or you move the instantiation section into an implementation file +#ifndef NO_EXPLICIT_TEMPLATE_INSTANTIATION + +#include +#include + +#if BOOST_VERSION < 104000 +#include +#elif !defined BOOST_ARCHIVE_SERIALIZER_INCLUDED +#include +#define BOOST_ARCHIVE_SERIALIZER_INCLUDED +#endif + +namespace boost { namespace archive { + + // explicitly instantiate for this type of binary stream + template class basic_binary_iarchive; + + template class basic_binary_iprimitive< + eos::portable_iarchive + #if BOOST_VERSION < 103400 + , std::istream + #else + , std::istream::char_type + , std::istream::traits_type + #endif + >; + +#if BOOST_VERSION < 104000 + template class detail::archive_pointer_iserializer; +#else + template class detail::archive_serializer_map; + //template class detail::archive_serializer_map; +#endif + +} } // namespace boost::archive + +#endif diff --git a/include/boost/archive/portable_oarchive.hpp b/include/boost/archive/portable_oarchive.hpp new file mode 100755 index 00000000..100176e9 --- /dev/null +++ b/include/boost/archive/portable_oarchive.hpp @@ -0,0 +1,470 @@ +/*****************************************************************************/ +/** + * \file portable_oarchive.hpp + * \brief Provides an archive to create portable binary files. + * \author christian.pfligersdorffer@gmx.at + * \version 5.1 + * + * This pair of archives brings the advantages of binary streams to the cross + * platform boost::serialization user. While being almost as fast as the native + * binary archive it allows its files to be exchanged between cpu architectures + * using different byte order (endianness). Speaking of speed: in serializing + * numbers the (portable) binary approach is approximately ten times faster than + * the ascii implementation (that is inherently portable)! + * + * Based on the portable archive example by Robert Ramey this implementation + * uses Beman Dawes endian library and fp_utilities from Johan Rade, both being + * in boost since 1.36. Prior to that you need to add them both (header only) + * to your boost directory before you're able to use the archives provided. + * Our archives have been tested successfully for boost versions 1.33 to 1.49! + * + * \note Correct behaviour has so far been confirmed using PowerPC-32, x86-32 + * and x86-64 platforms featuring different byte order. So there is a good + * chance it will instantly work for your specific setup. If you encounter + * problems or have suggestions please contact the author. + * + * \note Version 5.1 is now compatible with boost up to version 1.59. Thanks to + * ecotax for pointing to the issue with shared_ptr_helper. + * + * \note Version 5.0 is now compatible with boost up to version 1.49 and enables + * serialization of std::wstring by converting it to/from utf8 (thanks to + * Arash Abghari for this suggestion). With that all unit tests from the + * serialization library pass again with the notable exception of user + * defined primitive types. Those are not supported and as a result any + * user defined type to be used with the portable archives are required + * to be at least object_serializable. + * + * \note Oliver Putz pointed out that -0.0 was not serialized correctly, so + * version 4.3 provides a fix for that. Thanks Ollie! + * + * \note Version 4.2 maintains compatibility with the latest boost 1.45 and adds + * serialization of special floating point values inf and NaN as proposed + * by Francois Mauger. + * + * \note Version 4.1 makes the archives work together with boost 1.40 and 1.41. + * Thanks to Francois Mauger for his suggestions. + * + * \note Version 4 removes one level of the inheritance hierarchy and directly + * builds upon binary primitive and basic binary archive, thereby fixing + * the last open issue regarding array serialization. Thanks to Robert + * Ramey for the hint. + * + * \note A few fixes introduced in version 3.1 let the archives pass all of the + * serialization tests. Thanks to Sergey Morozov for running the tests. + * Wouter Bijlsma pointed out where to find the fp_utilities and endian + * libraries headers inside the boost distribution. I would never have + * found them so thank him it works out of the box since boost 1.36. + * + * \note With Version 3.0 the archives have been made portable across different + * boost versions. For that purpose a header is added to the data that + * supplies the underlying serialization library version. Backwards + * compatibility is maintained by assuming library version boost 1.33 if + * the iarchive is created using the no_header flag. Whether a header is + * present or not can be guessed by peeking into the stream: the header's + * first byte is the magic number 127 coinciding with 'e'|'o'|'s' :-) + * + * \note Version 2.1 removes several compiler warnings and enhances floating + * point diagnostics to inform the user if some preconditions are violated + * on his platform. We do not strive for the universally portable solution + * in binary floating point serialization as desired by some boost users. + * Instead we support only the most widely used IEEE 754 format and try to + * detect when requirements are not met and hence our approach must fail. + * Contributions we made by Johan Rade and Ákos Maróy. + * + * \note Version 2.0 fixes a serious bug that effectively transformed most + * of negative integral values into positive values! For example the two + * numbers -12 and 234 were stored in the same 8-bit pattern and later + * always restored to 234. This was fixed in this version in a way that + * does not change the interpretation of existing archives that did work + * because there were no negative numbers. The other way round archives + * created by version 2.0 and containing negative numbers will raise an + * integer type size exception when reading it with version 1.0. Thanks + * to Markus Frohnmaier for testing the archives and finding the bug. + * + * \copyright The boost software license applies. + */ +/*****************************************************************************/ + +#pragma once + +#include + +// basic headers +#include +#include +#include +#include + +#if BOOST_VERSION >= 103500 && BOOST_VERSION < 105600 +#include +#endif + +// funny polymorphics +#if BOOST_VERSION < 103500 +#include +#define POLYMORPHIC(T) boost::archive::detail::polymorphic_oarchive_impl + +#elif BOOST_VERSION < 103600 +#include +#define POLYMORPHIC(T) boost::archive::detail::polymorphic_oarchive_dispatch + +#else +#include +#define POLYMORPHIC(T) boost::archive::detail::polymorphic_oarchive_route +#endif + +// endian and fpclassify +#if BOOST_VERSION < 103600 +#include +#include +#elif BOOST_VERSION < 104800 +#include +#include +#else +#include +#include +#endif + +// namespace alias fp_classify +#if BOOST_VERSION < 103800 +namespace fp = boost::math; +#else +namespace fp = boost::spirit::math; +#endif + +// namespace alias endian +#if BOOST_VERSION < 104800 +namespace endian = boost::detail; +#else +namespace endian = boost::spirit::detail; +#endif + +#if BOOST_VERSION >= 104500 && !defined BOOST_NO_STD_WSTRING +// used for wstring to utf8 conversion +#include +#include +#endif + +// generic type traits for numeric types +#include +#include +#include +#include + +#include "portable_archive_exception.hpp" + +// hint from Johan Rade: on VMS there is still support for +// the VAX floating point format and this macro detects it +#if defined(__vms) && defined(__DECCXX) && !__IEEE_FLOAT +#error "VAX floating point format is not supported!" +#endif + +namespace eos { + + // forward declaration + class portable_oarchive; + + typedef boost::archive::basic_binary_oprimitive< + portable_oarchive + #if BOOST_VERSION < 103400 + , std::ostream + #else + , std::ostream::char_type + , std::ostream::traits_type + #endif + > portable_oprimitive; + + /** + * \brief Portable binary output archive using little endian format. + * + * This archive addresses integer size, endianness and floating point types so + * that data can be transferred across different systems. The archive consists + * primarily of three different save implementations for integral types, + * floating point types and string types. Those functions are templates and use + * enable_if to be correctly selected for overloading. + * + * \note The class is based on the portable binary example by Robert Ramey and + * uses Beman Dawes endian library plus fp_utilities by Johan Rade. + */ + class portable_oarchive : public portable_oprimitive + + // the example derives from common_oarchive but that lacks the + // save_override functions so we chose to stay one level higher + , public boost::archive::basic_binary_oarchive + + #if BOOST_VERSION >= 103500 && BOOST_VERSION < 105600 + // mix-in helper class for serializing shared_ptr + , public boost::archive::detail::shared_ptr_helper + #endif + { + // workaround for gcc: use a dummy struct + // as additional argument type for overloading + template struct dummy { dummy(int) {}}; + + // stores a signed char directly to stream + inline void save_signed_char(const signed char& c) + { + portable_oprimitive::save(c); + } + + // archive initialization + void init(unsigned flags) + { + // it is vital to have version information if the archive is + // to be parsed with a newer version of boost::serialization + // therefor we create a header, no header means boost 1.33 + if (flags & boost::archive::no_header) + BOOST_ASSERT(archive_version == 3); + else + { + // write our minimalistic header (magic byte plus version) + // the boost archives write a string instead - by calling + // boost::archive::basic_binary_oarchive::init() + save_signed_char(magic_byte); + + // write current version +// save(archive_version); + operator<<(archive_version); + } + } + + public: + /** + * \brief Constructor on a stream using ios::binary mode! + * + * We cannot call basic_binary_oprimitive::init which stores type + * sizes to the archive in order to detect transfers to non-compatible + * platforms. + * + * We could have called basic_binary_oarchive::init which would create + * the boost::serialization standard archive header containing also the + * library version. Due to efficiency we stick with our own. + */ + portable_oarchive(std::ostream& os, unsigned flags = 0) + #if BOOST_VERSION < 103400 + : portable_oprimitive(os, flags & boost::archive::no_codecvt) + #else + : portable_oprimitive(*os.rdbuf(), flags & boost::archive::no_codecvt) + #endif + , boost::archive::basic_binary_oarchive(flags) + { + init(flags); + } + + #if BOOST_VERSION >= 103400 + portable_oarchive(std::streambuf& sb, unsigned flags = 0) + : portable_oprimitive(sb, flags & boost::archive::no_codecvt) + , boost::archive::basic_binary_oarchive(flags) + { + init(flags); + } + #endif + + //! Save narrow strings. + void save(const std::string& s) + { + portable_oprimitive::save(s); + } + + #ifndef BOOST_NO_STD_WSTRING + /** + * \brief Save wide strings. + * + * This is rather tricky to get right for true portability as there + * are so many different character encodings around. However, wide + * strings that are encoded in one of the Unicode schemes only need + * to be _transcoded_ which is a lot easier actually. + * + * We expect the input string to be encoded in the system's native + * format, ie. UTF-16 on Windows and UTF-32 on Linux machines. Don't + * know about Mac here so I can't really say about that. + */ + void save(const std::wstring& s) + { + save(boost::to_utf8(s)); + } + #endif + + /** + * \brief Saving bool type. + * + * Saving bool directly, not by const reference + * because of tracking_type's operator (bool). + * + * \note If you cannot compile your application and it says something + * about save(bool) cannot convert your type const A& into bool then + * you should check your BOOST_CLASS_IMPLEMENTATION setting for A, as + * portable_archive is not able to handle custom primitive types in + * a general manner. + */ + void save(const bool& b) + { + save_signed_char(b); + if (b) save_signed_char('T'); + } + + /** + * \brief Save integer types. + * + * First we save the size information ie. the number of bytes that hold the + * actual data. We subsequently transform the data using store_little_endian + * and store non-zero bytes to the stream. + */ + template + typename boost::enable_if >::type + save(const T & t, dummy<2> = 0) + { + if (T temp = t) + { + // examine the number of bytes + // needed to represent the number + signed char size = 0; + do { temp >>= CHAR_BIT; ++size; } + while (temp != 0 && temp != (T) -1); + + // encode the sign bit into the size + save_signed_char(t > 0 ? size : -size); + BOOST_ASSERT(t > 0 || boost::is_signed::value); + + // we choose to use little endian because this way we just + // save the first size bytes to the stream and skip the rest + endian::store_little_endian(&temp, t); + + save_binary(&temp, size); + } + // zero optimization + else save_signed_char(0); + } + + /** + * \brief Save floating point types. + * + * We simply rely on fp_traits to extract the bit pattern into an (unsigned) + * integral type and store that into the stream. Francois Mauger provided + * standardized behaviour for special values like inf and NaN, that need to + * be serialized in his application. + * + * \note by Johan Rade (author of the floating point utilities library): + * Be warned that the math::detail::fp_traits::type::get_bits() function + * is *not* guaranteed to give you all bits of the floating point number. It + * will give you all bits if and only if there is an integer type that has + * the same size as the floating point you are copying from. It will not + * give you all bits for double if there is no uint64_t. It will not give + * you all bits for long double if sizeof(long double) > 8 or there is no + * uint64_t. + * + * The member fp_traits::type::coverage will tell you whether all bits + * are copied. This is a typedef for either math::detail::all_bits or + * math::detail::not_all_bits. + * + * If the function does not copy all bits, then it will copy the most + * significant bits. So if you serialize and deserialize the way you + * describe, and fp_traits::type::coverage is math::detail::not_all_bits, + * then your floating point numbers will be truncated. This will introduce + * small rounding off errors. + */ + template + typename boost::enable_if >::type + save(const T & t, dummy<3> = 0) + { + typedef typename fp::detail::fp_traits::type traits; + + // if the no_infnan flag is set we must throw here + if (get_flags() & no_infnan && !fp::isfinite(t)) + throw portable_archive_exception(t); + + // if you end here there are three possibilities: + // 1. you're serializing a long double which is not portable + // 2. you're serializing a double but have no 64 bit integer + // 3. your machine is using an unknown floating point format + // after reading the note above you still might decide to + // deactivate this static assert and try if it works out. + typename traits::bits bits; + BOOST_STATIC_ASSERT(sizeof(bits) == sizeof(T)); + BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + + // examine value closely + switch (fp::fpclassify(t)) + { + //case FP_ZERO: bits = 0; break; + case FP_NAN: bits = traits::exponent | traits::mantissa; break; + case FP_INFINITE: bits = traits::exponent | (t<0) * traits::sign; break; + case FP_SUBNORMAL: assert(std::numeric_limits::has_denorm); // pass + case FP_ZERO: // note that floats can be ±0.0 + case FP_NORMAL: traits::get_bits(t, bits); break; + default: throw portable_archive_exception(t); + } + + save(bits); + } + + // in boost 1.44 version_type was splitted into library_version_type and + // item_version_type, plus a whole bunch of additional strong typedefs. + template + typename boost::disable_if >::type + save(const T& t, dummy<4> = 0) + { + // we provide a generic save routine for all types that feature + // conversion operators into an unsigned integer value like those + // created through BOOST_STRONG_TYPEDEF(X, some unsigned int) like + // library_version_type, collection_size_type, item_version_type, + // class_id_type, object_id_type, version_type and tracking_type + save((typename boost::uint_t::least)(t)); + } + }; + + // polymorphic portable binary oarchive typedef + typedef POLYMORPHIC(portable_oarchive) polymorphic_portable_oarchive; + #undef POLYMORPHIC + +} // namespace eos + +// required by export +#if BOOST_VERSION < 103500 +#define BOOST_ARCHIVE_CUSTOM_OARCHIVE_TYPES eos::portable_oarchive +#else +BOOST_SERIALIZATION_REGISTER_ARCHIVE(eos::portable_oarchive) +BOOST_SERIALIZATION_REGISTER_ARCHIVE(eos::polymorphic_portable_oarchive) +#endif + +// if you include this header multiple times and your compiler is picky +// about multiple template instantiations (eg. gcc is) then you need to +// define NO_EXPLICIT_TEMPLATE_INSTANTIATION before every include but one +// or you move the instantiation section into an implementation file +#ifndef NO_EXPLICIT_TEMPLATE_INSTANTIATION + +#include +#include + +#if BOOST_VERSION < 104000 +#include +#elif !defined BOOST_ARCHIVE_SERIALIZER_INCLUDED +#include +#define BOOST_ARCHIVE_SERIALIZER_INCLUDED +#endif + +namespace boost { namespace archive { + + // explicitly instantiate for this type of binary stream + template class basic_binary_oarchive; + + template class basic_binary_oprimitive< + eos::portable_oarchive + #if BOOST_VERSION < 103400 + , std::ostream + #else + , std::ostream::char_type + , std::ostream::traits_type + #endif + >; + +#if BOOST_VERSION < 104000 + template class detail::archive_pointer_oserializer; +#else + template class detail::archive_serializer_map; + //template class detail::archive_serializer_map; +#endif + +} } // namespace boost::archive + +#endif diff --git a/test/polymorphic_portable_archive.hpp b/test/polymorphic_portable_archive.hpp new file mode 100755 index 00000000..91d4cc3c --- /dev/null +++ b/test/polymorphic_portable_archive.hpp @@ -0,0 +1,35 @@ +/*****************************************************************************/ +/** + * \file polymorphic_portable_archive.hpp + * \brief Needed for unit tests on portable archives. + * \author christian.pfligersdorffer@gmx.at + * + * Header for testing portable archives with all of the serialization tests. + * Before use copy all hpp files from this directory to your boost folder + * boost_.../libs/serialization/test and run from there a visual studio + * prompt with b2 oder bjam -sBOOST_ARCHIVE_LIST=portable_archive.hpp + * + * \note Since portable archives version 5.0 we depend on program_options! + * Edit libs/serialization/test/Jamfile.v2 and change the requirements to + * : requirements /boost/filesystem /boost/program_options + */ +/****************************************************************************/ + +#pragma warning( disable:4217 4127 4310 4244 4800 4267 ) + +// portable_archive test header +// include output archive header +#include +// set name of test output archive +typedef eos::polymorphic_portable_oarchive test_oarchive; +// set name of test output stream +typedef std::ofstream test_ostream; + +// repeat the above for input archive +#include +typedef eos::polymorphic_portable_iarchive test_iarchive; +typedef std::ifstream test_istream; + +// define open mode for streams +// binary archives should use std::ios_base::binary +#define TEST_STREAM_FLAGS std::ios_base::binary diff --git a/test/portable_archive.hpp b/test/portable_archive.hpp new file mode 100644 index 00000000..95b0cda8 --- /dev/null +++ b/test/portable_archive.hpp @@ -0,0 +1,25 @@ +// (C) Copyright 2002-4 Robert Ramey - http://www.rrsd.com . +// 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) + +// See http://www.boost.org for updates, documentation, and revision history. +// file includes for testing a custom archive. +// as an example this tests the portable binary archive + +#include + +// #include output archive header +#include +// define output archive class to be used +typedef eos::portable_oarchive test_oarchive; +// and corresponding stream +typedef std::ofstream test_ostream; + +// repeat the above for correspondng input archive +#include +typedef eos::portable_iarchive test_iarchive; +typedef std::ifstream test_istream; + +// and stream open flags +#define TEST_STREAM_FLAGS std::ios::binary