mirror of
https://github.com/boostorg/serialization.git
synced 2026-01-24 06:22:08 +00:00
555 lines
22 KiB
HTML
555 lines
22 KiB
HTML
<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|
<link rel="stylesheet" type="text/css" href="../../../boost.css">
|
|
<link rel="stylesheet" type="text/css" href="style.css">
|
|
<title>Serialization - Archives</title>
|
|
</head>
|
|
<body link="#0000ff" vlink="#800080">
|
|
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary="header">
|
|
<tr>
|
|
<td valign="top" width="300">
|
|
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
|
</td>
|
|
<td valign="top">
|
|
<h1 align="center">Serialization</h1>
|
|
<h2 align="center">Archive Class Usage</h2>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<hr>
|
|
<dl class="page-index">
|
|
<dt><a href="#creation">Archive Classes</a>
|
|
<dt><a href="#interface">Library Interface</a>
|
|
<dl class="page-index">
|
|
<dt><a href="#saving_interface">Saving</a>
|
|
<dt><a href="#loading_interface">Loading</a>
|
|
</dl>
|
|
<dt><a href="#details_by_type">Details by Type</a>
|
|
<dl class="page-index">
|
|
<dt><a href="#primitiveoperators">Primitive Types</a>
|
|
<dt><a href="#classoperators">Class Types</a>
|
|
<dt><a href="#baseclasses">Base Classes</a>
|
|
<dt><a href="#pointeroperators">Pointers</a>
|
|
<dt><a href="#referenceoperators">References</a>
|
|
</dl>
|
|
<dt><a href="#charactersets">Character Sets</a>
|
|
</dl>
|
|
|
|
<h3><a name="archive_classes">Archive Classes</a></h3>
|
|
An archive is defined by two complementary classes. One is for saving data while
|
|
the other is for loading it.
|
|
The system includes a number of archive implementations "ready to go" for the
|
|
most common requirements. These can be used "as is" or as a basis for developing
|
|
one's own particular type of archive. To invoke serialization using one of
|
|
these archives, one or more of the following header files must be
|
|
included in the code module containing the serialization code.
|
|
<pre><code>
|
|
// a portable text archive</a>
|
|
<a href="../../../boost/archive/text_oarchive.hpp" target="text_oarchive_cpp">boost::archive::text_oarchive(ostream &s)</a> // saving
|
|
<a href="../../../boost/archive/text_iarchive.hpp" target="text_iarchive_cpp">boost::archive::text_iarchive(istream &s)</a> // loading
|
|
|
|
// a portable text archive using a wide character stream</a>
|
|
<a href="../../../boost/archive/text_woarchive.hpp">boost::archive::text_woarchive(wostream &s)</a> // saving
|
|
<a href="../../../boost/archive/text_wiarchive.hpp">boost::archive::text_wiarchive(wistream &s)</a> // loading
|
|
|
|
// a non-portable native binary archive</a>
|
|
<a href="../../../boost/archive/binary_oarchive.hpp" target="binary_oarchive_cpp">boost::archive::binary_oarchive(ostream &s)</a> // saving
|
|
<a href="../../../boost/archive/binary_iarchive.hpp" target="binary_iarchive_cpp">boost::archive::binary_iarchive(istream &s)</a> // loading
|
|
<!--
|
|
// a non-portable native binary archive which use wide character streams
|
|
<a href="../../../boost/archive/binary_woarchive.hpp">boost::archive::binary_woarchive(wostream &s)</a> // saving
|
|
<a href="../../../boost/archive/binary_wiarchive.hpp">boost::archive::binary_wiarchive(wistream &s)</a> // loading
|
|
-->
|
|
// a portable XML archive</a>
|
|
<a href="../../../boost/archive/xml_oarchive.hpp" target="xml_oarchive_cpp">boost::archive::xml_oarchive(ostream &s)</a> // saving
|
|
<a href="../../../boost/archive/xml_iarchive.hpp" target="xml_iarchive_cpp">boost::archive::xml_iarchive(istream &s)</a> // loading
|
|
|
|
// a portable XML archive which uses wide characters - use for utf-8 output</a>
|
|
<a href="../../../boost/archive/xml_woarchive.hpp" target="xml_woarchive_cpp">boost::archive::xml_woarchive(wostream &s)</a> // saving
|
|
<a href="../../../boost/archive/xml_wiarchive.hpp" target="xml_wiarchive_cpp">boost::archive::xml_wiarchive(wistream &s)</a> // loading
|
|
</code></pre>
|
|
<h3><a name="interface">Archive Library Interface</a></h3>
|
|
An <strong>archive</strong> contains a sequence of bytes created from
|
|
an arbitrary nested set of C++ data structures. Archives are implemented as a
|
|
hierarchy of classes. However, the interface to all archives included with
|
|
the library can best be represented by the following public interface.
|
|
|
|
<h4><a name="saving_interface">Saving</a></h4>
|
|
<pre><code>
|
|
namespace boost {
|
|
namespace archive {
|
|
|
|
enum archive_flags {
|
|
no_header = 1, // suppress archive header info
|
|
no_codecvt = 2, // suppress alteration of codecvt facet
|
|
no_xml_tag_checking = 4 // suppress checking of xml tags - igored on saving
|
|
};
|
|
</code></pre>
|
|
|
|
<pre><code>
|
|
template<class OStream>
|
|
class oarchive : ...
|
|
{
|
|
...
|
|
public:
|
|
// called to save objects
|
|
template<class T>
|
|
oarchive & operator<<(const T & t);
|
|
|
|
template<class T>
|
|
oarchive & operator&(T & t)
|
|
{
|
|
return *this << t;
|
|
}
|
|
|
|
void save_binary(const void *address, std::size_t count);
|
|
|
|
template<class T>
|
|
register_type(T * t = NULL);
|
|
|
|
unsigned int library_version() const;
|
|
|
|
struct is_saving {
|
|
typedef mpl::bool_<true> type;
|
|
BOOST_STATIC_CONSTANT(bool, value=true);
|
|
};
|
|
|
|
struct is_loading {
|
|
typedef mpl::bool_<false> type;
|
|
BOOST_STATIC_CONSTANT(bool, value=false);
|
|
};
|
|
|
|
oarchive(OStream & os, unsigned int flags = 0);
|
|
|
|
~oarchive();
|
|
};
|
|
</code></pre>
|
|
|
|
<dl>
|
|
|
|
<dt><h4><code>
|
|
template<class T>
|
|
oarchive & operator<<(const T & t);
|
|
|
|
template<class T>
|
|
oarchive & operator&(T & t);
|
|
</code></h4></dt>
|
|
<dd>
|
|
<p>
|
|
Appends an object of type T to the archive. The object may be
|
|
<ul>
|
|
<li>A primitive data type such as int, char, float, etc.
|
|
<li>A class or struct for which a <code style="white-space: normal">serialize</code>
|
|
function has been defined.
|
|
<li>A pointer to a serializable object.
|
|
</ul>
|
|
</dd>
|
|
|
|
<dt><h4><code>
|
|
void save_binary(const void *address, std::size_t count);
|
|
</code></h4></dt>
|
|
<dd>
|
|
Appends to the archive <code style="white-space: normal">count</code> bytes found at
|
|
<code style="white-space: normal">address</code>.
|
|
</dd>
|
|
<dt><h4><code>
|
|
template<class T>
|
|
register_type(T * t = NULL);
|
|
</code></h4></dt>
|
|
<dd>
|
|
Appends a sequential integer to the archive. This integer becomes the "key" used
|
|
to look up the class type when the archive is later loaded. This process is
|
|
referred to as "class registration". It is only necessary to invoke this function for
|
|
objects of derived classes which are serialized through a base class pointer. This
|
|
is explained in detail in
|
|
<a href="special.html#derivedpointers">Special Considerations - Derived Pointers</a>
|
|
</dd>
|
|
|
|
<dt><h4><code>
|
|
unsigned int library_version() const;
|
|
</code></h4></dt>
|
|
<dd>
|
|
Returns the version number of the serialization library that created the archive.
|
|
This number will be incremented each time the library is altered in such a way
|
|
that serialization could be altered for some type. For example, suppose the type
|
|
used for a count of collection members is changed. The code that loads collections
|
|
might be conditioned on the library version to make sure that libraries created by
|
|
previous versions of the library can still be read.
|
|
</dd>
|
|
|
|
<dt><h4><code>
|
|
is_saving::type = mpl::bool<true>;
|
|
is_saving::value= true;
|
|
is_loading::type = mpl::bool<false>;
|
|
is_loading::value= false;
|
|
</code></h4></dt>
|
|
<dd>
|
|
These integral constants permit archive attributes to be queried at compiler
|
|
or execution time. They can used to generate code with boost
|
|
<a href="../../mpl/doc/index.html">mpl</a>
|
|
. For and example
|
|
showing how these can beused, see the implementation of
|
|
<a target="splithpp" href="../../../boost/serialization/split_free.hpp">split_free.hpp</a>.
|
|
</dd>
|
|
|
|
<dt><h4><code>
|
|
oarchive(OStream & os, unsigned int flags = 0);
|
|
</code></h4></dt>
|
|
<dd>
|
|
Contructs and archive given an open <code style="white-space: normal">stream</code> as
|
|
an argument and optional flags. For most applications there will be no need to use
|
|
flags. Flags are taken from the following table and can be combined with the
|
|
<code style="white-space: normal">|</code> operator.By default, archives prepend
|
|
output with initial data which helps identify them as archives produced by this system.
|
|
This permits a more graceful in the case where attempt is made to load an archive
|
|
from an invalid file format. In addition to this, each type of archive might have
|
|
its own information. For example, native binary archives include information about
|
|
sizes of native types and endianess to gracefully handle the case where it has been
|
|
erroneously assumed that such an archive is portable across platforms. In some cases
|
|
where this extra overhead might be considered objectionable, it can be suppressed with the
|
|
<code style="white-space: normal">no_header</code> flag.
|
|
<p>
|
|
In some cases, an archive may alter (and later restore)
|
|
the codecvt facet of the stream locale. To suppress this action,
|
|
include the <code style="white-space: normal">no_codecvt</code> flag.
|
|
<p>
|
|
XML archives contain nested tags signifying the start and end of data fields.
|
|
These tags are normally checked for aggreement with the object name when
|
|
data is loaded. If a mismatch occurs an exception is thrown. Its possible
|
|
that this may not be desired behavior. To suppress this checking of XML
|
|
tags, use <code style="white-space: normal">no_xml_tag_checking</code> flag.
|
|
</dd>
|
|
|
|
<dt><h4><code>
|
|
~oarchive();
|
|
</code></h4></dt>
|
|
<dd>
|
|
Destructor for an archive. This should be called before the stream is
|
|
closed. It restores any altered stream facets to thier state before the
|
|
the archive was opened.
|
|
</dd>
|
|
|
|
</dl>
|
|
|
|
<h4><a name="loading_interface">Loading</a></h4>
|
|
|
|
<pre><code>
|
|
template<class IStream>
|
|
class iarchive : ...
|
|
{
|
|
...
|
|
public:
|
|
// called to load objects
|
|
template<class T>
|
|
iarchive & operator>>(T & t);
|
|
|
|
template<class T>
|
|
iarchive & operator&(T & t)
|
|
{
|
|
return *this >> t;
|
|
}
|
|
|
|
void delete_created_pointers();
|
|
|
|
void load_binary(void *address, std::size_t count);
|
|
|
|
template<class T>
|
|
register_type(T * t = NULL);
|
|
|
|
unsigned int library_version() const;
|
|
|
|
struct is_saving {
|
|
typedef mpl::bool_<false> type;
|
|
BOOST_STATIC_CONSTANT(bool, value=false);
|
|
};
|
|
|
|
struct is_loading {
|
|
typedef mpl::bool_<true> type;
|
|
BOOST_STATIC_CONSTANT(bool, value=true);
|
|
};
|
|
|
|
iarchive(IStream & is, unsigned int flags = 0);
|
|
|
|
~iarchive();
|
|
};
|
|
|
|
} //namespace archive
|
|
) //namespace boost
|
|
|
|
</code></pre>
|
|
|
|
<dl>
|
|
|
|
<dt><h4><code>
|
|
template<class T>
|
|
iarchive & operator>>(T & t);
|
|
|
|
template<class T>
|
|
iarchive & operator&(T & t);
|
|
</code></h4></dt>
|
|
<dd>
|
|
<p>
|
|
Retrieves an object of type T from the archive. The object may be
|
|
<ul>
|
|
<li>A primitive data type such as int, char, float, etc.
|
|
<li>A class or struct for which a <code style="white-space: normal">serialize</code>
|
|
function has been defined.
|
|
<li>A pointer to a serializable object.
|
|
</ul>
|
|
</dd>
|
|
|
|
<dt><h4><code>
|
|
void load_binary(void *address, std::size_t count);
|
|
</code></h4></dt>
|
|
<dd>
|
|
Retrieves from the archive <code style="white-space: normal">count</code> bytes and stores
|
|
them in memory starting at <code style="white-space: normal">address</code>.
|
|
</dd>
|
|
|
|
<dt><h4><code>
|
|
void delete_created_pointers();
|
|
</code></h4></dt>
|
|
<dd>
|
|
Deletes all objects created by the loading of pointers. This can be used to
|
|
avoid memory leaks that might otherwise occur if pointers are being loaded
|
|
and the archive load encounters an exception.
|
|
</dd>
|
|
|
|
<dt><h4><code>
|
|
template<class T>
|
|
register_type(T * t = NULL);
|
|
</code></h4></dt>
|
|
<dd>
|
|
Retrieves the next integer from the archive and adds an entry to a table which
|
|
relates the integer to the type T. When pointers are loaded, this integer is
|
|
used to indicate which object type should be created. This process is
|
|
referred to as "class registration". It is only necessary to invoke this function for
|
|
objects of derived classes which are serialized through a base class pointer. If this
|
|
function is called during the saving of data to the archive, it should be called during the
|
|
loading of the data from the archive at the same point in the serialization process.
|
|
This is explained in detail in
|
|
<a href="special.html#derivedpointers">Special Considerations - Derived Pointers</a>
|
|
</dd>
|
|
|
|
<dt><h4><code>
|
|
unsigned int library_version() const;
|
|
</code></h4></dt>
|
|
<dd>
|
|
Returns the version number of the serialization library that created the archive.
|
|
This number will be incremented each time the library is altered in such a way
|
|
that serialization could be altered for some type. For example, suppose the type
|
|
used for a count of collection members is changed. The code that loads collections
|
|
might be conditioned on the library version to make sure that libraries created by
|
|
previous versions of the library can still be read.
|
|
</dd>
|
|
|
|
<dt><h4><code>
|
|
is_saving::type = mpl::bool<false>;
|
|
is_saving::value= false;
|
|
is_loading::type = mpl::bool<true>;
|
|
is_loading::value= true;
|
|
</code></h4></dt>
|
|
<dd>
|
|
These integral constants permit archive attributes to be queried at compiler
|
|
or execution time. They can used to generate code with boost
|
|
<a href="../../mpl/doc/index.html">mpl</a>
|
|
. For and example
|
|
showing how these can beused, see the implementation of
|
|
<a target="splithpp" href="../../../boost/serialization/split_free.hpp">split_free.hpp</a>.
|
|
</dd>
|
|
|
|
<dt><h4><code>
|
|
iarchive(IStream & is, unsigned int flags = 0);
|
|
</code></h4></dt>
|
|
<dd>
|
|
Contructs an archive given an open <code style="white-space: normal">stream</code> as
|
|
an argument and optional flags. If flags are used, they should be the same
|
|
as those used when the archive was created. Function and usage of flags is described
|
|
above.
|
|
</dd>
|
|
|
|
<dt><h4><code>
|
|
~iarchive();
|
|
</code></h4></dt>
|
|
<dd>
|
|
Destructor for an archive. This should be called before the stream is
|
|
closed. It restores any altered stream facets to thier state before the
|
|
the archive was opened.
|
|
</dd>
|
|
|
|
</dl>
|
|
|
|
There are archives based on text, binary and XML file
|
|
formats but all have the above interface. Given that all archives present
|
|
the same public interface, specifcation of serialization is exactly the same
|
|
for all archives. Archive classes have other members not mentioned here.
|
|
However they are related to the internal functioning of the library and
|
|
are not meant to be called by users of an archive. Implementation of new
|
|
archives is discussed in
|
|
<a href="archive_reference.html#implementation">New Archives - Implementation</a>.
|
|
|
|
<p>
|
|
The existence of the <code style="white-space: normal"><<</code>
|
|
and <code style="white-space: normal">>></code> suggest
|
|
a relationship between archives and C++ i/o streams. <strong>Archives are not
|
|
C++ i/o streams</strong>. All the archives included with this system take a stream
|
|
as an argument in the constructor and that stream is used for output or input.
|
|
However, this is not a requirement of the serialization functions or the
|
|
archive interface. It just turns out that the archives written so far have
|
|
found it useful to base their implementation on streams.
|
|
|
|
<h3><a name="details_by_type">Details by Type</a></h3>
|
|
|
|
<h4><a name="primitiveoperators">Primitive Types</a></h4>
|
|
In this document, we use the term primitive type to mean
|
|
types whose data is simply saved/loaded to/from an archive
|
|
with no further processing. By default, arithmetic (including characters),
|
|
bool, and enum types are primitive types. Using
|
|
<a target="detail" href="traits.html#Traits">serialization traits</a>,
|
|
any user type can also be designated as "primitive"
|
|
so that it is handled in this way.
|
|
<p>
|
|
The template operators &, <<, and >> of the archive classes
|
|
described above will generate code to save/load all primitive types
|
|
to/from an archive. This code will usually just add the
|
|
data to the archive according to the archive format.
|
|
For example, a four byte integer is appended to a binary archive
|
|
as 4 binary bytes while a to a text archive it would be
|
|
rendered as a space followed by a string representation.
|
|
|
|
<h4><a name="classoperators">Class Types</a></h4>
|
|
For class/struct types, the template operators &, <<, and >>
|
|
will generate code that invokes the programmer's serialization code for the
|
|
particular data type. There is no default. An attempt to serialize a
|
|
class/struct for which no serialization has been explicitly specified
|
|
will result in a compile time error. Specification of serialization
|
|
for user defined types is explained in detail in the next section
|
|
of this manual.
|
|
|
|
<h4><a name="baseclasses">Base Classes</a></h4>
|
|
The header file
|
|
<a href="../../../boost/serialization/base_object.hpp" target="base_object_hpp">
|
|
base_object.hpp
|
|
</a>
|
|
includes the template:
|
|
<pre><code>
|
|
template<class Base, class Derived>
|
|
Base & base_object(Derived &d);
|
|
</code></pre>
|
|
which should be used to create a reference to an object of the base
|
|
which can be used as an argument to the archive save/load operators:
|
|
<pre><code>
|
|
ar & boost::serialization::base_object<Base>(*this);
|
|
</code></pre>
|
|
Resist the temptation to just cast <code style="white-space: normal">*this</code> to the base class.
|
|
This might seem to work but may fail to invoke code necessary for
|
|
proper serialization.
|
|
<h4><a name="pointeroperators">Pointers</a></h4>
|
|
A pointer to any class instance can be serialized with any of the archive
|
|
save/load operators.
|
|
<p>
|
|
To properly save and restore an object through a pointer the
|
|
following situations must be addressed:
|
|
<ol>
|
|
<li>If the same object is saved multiple times through different
|
|
pointers, only one copy of the object need be saved.
|
|
<li>If an object is loaded multiple times through different pointers,
|
|
only one new object should be created and all returned pointers
|
|
should point to it.
|
|
<li>The system must detect the case where an object is first
|
|
saved through a pointer then the object itself is saved.
|
|
Without taking extra precautions, loading would result in the
|
|
creation of multiple copies of the original object. This system detects
|
|
this case when saving and throws an exception - see below.
|
|
<li>An object of a derived class may be stored through a
|
|
pointer to the base class. The true type of the object must
|
|
be determined and saved. Upon restoration the correct type
|
|
must be created and its address correctly cast to the base
|
|
class. That is, polymorphic pointers have to be considered.
|
|
<li>NULL pointers must be dectected when saved and restored
|
|
to NULL when deserialized.
|
|
</ol>
|
|
|
|
This serialization library addresses all of the above
|
|
considerations. The process of saving and loading an object
|
|
through a pointer is non-trivial. It can be summarized as
|
|
follows:
|
|
<p>Saving a pointer:
|
|
<ol>
|
|
<li>determine the true type of the object being pointed to.
|
|
<li>write a special tag to the archive
|
|
<li>if the object pointed to has not already been written
|
|
to the archive, do so now
|
|
</ol>
|
|
Loading a pointer:
|
|
<ol>
|
|
<li>read a tag from the archive.
|
|
<li>determine the type of object to be created
|
|
<li>if the object has already been loaded, return it's address.
|
|
<li>otherwise, create a new instance of the object
|
|
<li>read the data back in using the operators described above
|
|
<li>return the address of the newly created object.
|
|
</ol>
|
|
|
|
Given that class instances are saved/loaded to/from the archive
|
|
only once, regardless of how many times they are serialized with
|
|
the <code style="white-space: normal"><<</code>
|
|
and <code style="white-space: normal">>></code> operators
|
|
<ul>
|
|
<li>Loading the same pointer object multiple times
|
|
results in only one object being created, thereby replicating
|
|
the original pointer configuration.
|
|
<li>Structures such as collections of polymorphic pointers,
|
|
are handled with no special effort on the part of users of this library.
|
|
</ul>
|
|
Serialization of pointers of derived types through a pointer to the
|
|
base class may require a little extra "help". Also, the programmer
|
|
may desire to modify the process described above for his own reasons.
|
|
For example, it might be desired to suppress the tracking of objects
|
|
as it is known a priori that the application in question can never
|
|
create duplicate objects. Serialization of pointers can be "fine tuned"
|
|
via the specification of <a target="detail" href="traits.html#Traits">Class Serialization Traits</a>
|
|
as described in
|
|
<a target="detail" href="special.html#derivedpointers">
|
|
another section of this manual
|
|
</a>
|
|
<h4><a name="referenceoperators">References</a></h4>
|
|
In general, references are serialized just as any other objects are.
|
|
However, references have the property that several references may
|
|
refer to the same object - much like pointers. So, there exists
|
|
the opportunity to gain some storage efficiency by storing only
|
|
one copy. This subject is addressed the chapter Class Serialization Traits -
|
|
<a target="detail" href="traits.html#tracking">Object Tracking</a>.
|
|
|
|
<h3><a name="charactersets">Character Sets</h3>
|
|
This library includes two archive classes for XML. The wide character
|
|
version (<code style="white-space: normal">xml_w?archive</code>) renders it output as UTF-8 which can
|
|
handle any wide character without loss of information.
|
|
<code style="white-space: normal">std::string</code> data is converted from multi-byte format to wide
|
|
character format using the current <code style="white-space: normal">
|
|
locale</code>. Hence this version should give a fair rendering of all
|
|
C++ data for all cases. This could result in some unexpected behavior.
|
|
Suppose an <code style="white-space: normal">std::string</code>
|
|
is created with the <code style="white-space: normal">locale</code> character
|
|
set to hebrew characters. On output this is converted to wide characters.
|
|
On input however, there could be a problem if the <code style="white-space: normal">locale</code> is
|
|
not set the same as when the archive is created.
|
|
<p>
|
|
The normal character version (<code style="white-space: normal">xml_?archive</code>) renders
|
|
<code style="white-space: normal">std::string</code> output without any conversion. Though this may work
|
|
fine for serialization, it may create difficulties if the XML archive is used
|
|
for some other purpose.
|
|
|
|
<hr>
|
|
<p>Revised
|
|
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
24 January, 2004
|
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
</p>
|
|
<p><i>© Copyright <a href="http://www.rrsd.com">Robert Ramey</a>
|
|
2002-4. All Rights Reserved.</i></p>
|
|
</body>
|
|
</html>
|