mirror of
https://github.com/boostorg/serialization.git
synced 2026-07-21 13:33:32 +00:00
Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d4a5c4810f | |||
| f976f993ae | |||
| b724041a6e | |||
| 43892a0b2b | |||
| afb4250f38 | |||
| a54da565ef | |||
| bd84d08b40 | |||
| 9dbb735f0e | |||
| a5549c8daa | |||
| b6f3b37c86 | |||
| e89dc7cec6 | |||
| ed3a89bc7a | |||
| 0ca9f4f7a6 | |||
| a9a8d219ca | |||
| b067cfc518 | |||
| 5ac1d1156e | |||
| 2f11734b5f | |||
| 23b8fb8785 | |||
| 1749bf9c03 | |||
| 2f119f0694 | |||
| a3f6ecee7f | |||
| e553bbfb0d | |||
| c0a5309e93 | |||
| c852736757 | |||
| 6a1209e115 | |||
| 24b596bcf4 | |||
| ca999aaa88 | |||
| 903da1f79a | |||
| 51be585b61 | |||
| 814429125c | |||
| 9a1a43dd68 | |||
| 0d4712f1cb | |||
| 2afb64b2e6 | |||
| 142db7e716 | |||
| 33750658a3 | |||
| 10c0efac47 | |||
| 66685340a0 | |||
| 65a3901e68 | |||
| 81402ffadc | |||
| 4cce79fffc | |||
| fb8b2f0825 | |||
| 67cda7157c | |||
| f055298bcf | |||
| 181abc0c76 | |||
| 8d8f08e9c7 | |||
| d45be5d5cc | |||
| 2dd7478b0d | |||
| fc4f873b14 | |||
| e7cf216b41 | |||
| f622a85d1d | |||
| 4e506b8b20 | |||
| 99e810a2ad | |||
| d3399abe7d | |||
| d1ddaf6d40 | |||
| 5e92b44ac0 | |||
| 35e5022b1d | |||
| 43b1e020f6 | |||
| 157b54fbb0 | |||
| 4a997c5ee3 | |||
| c5d7d99379 | |||
| 76f2cb91ea | |||
| 87685cc870 | |||
| 24d628a70e | |||
| 5d989c4d98 | |||
| 52a0ddee21 | |||
| 34d7b41249 | |||
| 6a45041ca8 | |||
| 31eb724fd0 | |||
| c0b4cf938b | |||
| 34c29757e4 | |||
| 04a833252c | |||
| 8fd0680eff | |||
| a3922971b4 | |||
| f606820031 | |||
| d3ed1792fc | |||
| 094071d25e | |||
| b85d43ac2b | |||
| 72db2ac39b | |||
| 0606fd8027 | |||
| ef8745cf48 | |||
| 25b0ed093c | |||
| 01adcfc182 | |||
| 3d715fa6ad | |||
| e1176c244c | |||
| d15db6d4c4 |
+3
-2
@@ -43,6 +43,7 @@ SOURCES =
|
||||
|
||||
WSOURCES =
|
||||
codecvt_null
|
||||
utf8_codecvt_facet
|
||||
basic_text_wiprimitive
|
||||
basic_text_woprimitive
|
||||
binary_wiarchive
|
||||
@@ -52,7 +53,6 @@ WSOURCES =
|
||||
xml_wgrammar
|
||||
xml_wiarchive
|
||||
xml_woarchive
|
||||
utf8_codecvt_facet
|
||||
;
|
||||
|
||||
template boost_serialization_base
|
||||
@@ -60,13 +60,14 @@ template boost_serialization_base
|
||||
: ## requirements ##
|
||||
std::locale-support
|
||||
toolset::require-boost-spirit-support
|
||||
toolset::suppress-warnings
|
||||
toolset::optimizations
|
||||
# the common names rule ensures that the library will
|
||||
# be named according to the rules used by the install
|
||||
# and auto-link features:
|
||||
common-variant-tag
|
||||
<sysinclude>$(BOOST_ROOT)
|
||||
<stlport-iostream>on
|
||||
<borland*><*><cxxflags>"-w-8080 -w-8071 -w-8057 -w-8062 -w-8008 -w-8001 -w-0018 -w-8066"
|
||||
<msvc><*><cxxflags>-Gy
|
||||
<vc*><*><cxxflags>-Gy
|
||||
<define>BOOST_LIB_DIAGNOSTIC=1
|
||||
|
||||
+38
-2
@@ -51,8 +51,11 @@ rule toolset::require-wide-char-io-support ( toolset variant : subvariant-path p
|
||||
echo **** wide char i/o not supported by libcomo standard library **** ;
|
||||
properties = [ impose-requirements $(properties) : <build>no ] ;
|
||||
case "mingw*" :
|
||||
echo **** wide char i/o not supported by the mingw standard library **** ;
|
||||
properties = [ impose-requirements $(properties) : <build>no ] ;
|
||||
if ! [ MATCH "^([5][.][0])$" : [ get-values <stlport-version> : $(properties) ] ]
|
||||
{
|
||||
echo **** wide char i/o not supported by the mingw standard library **** ;
|
||||
properties = [ impose-requirements $(properties) : <build>no ] ;
|
||||
}
|
||||
}
|
||||
return $(subvariant-path) $(properties) ;
|
||||
}
|
||||
@@ -80,3 +83,36 @@ rule toolset::require-shared-libraries-support ( toolset variant : subvariant-pa
|
||||
}
|
||||
return $(subvariant-path) $(properties) ;
|
||||
}
|
||||
|
||||
# certain tool sets display warnings which are not applicable to the serialization library
|
||||
rule toolset::suppress-warnings ( toolset variant : subvariant-path properties * )
|
||||
{
|
||||
switch $(toolset) {
|
||||
case "vc-8*" :
|
||||
properties = [ impose-requirements $(properties) : <cxxflags>"-wd4996" ] ;
|
||||
case "*cygwin*" :
|
||||
properties = [ impose-requirements $(properties) : <cxxflags>"-Wno-non-virtual-dtor -Wno-ctor-dtor-privacy" ] ;
|
||||
case "gcc*" :
|
||||
properties = [ impose-requirements $(properties) : <cxxflags>"-Wno-non-virtual-dtor -Wno-ctor-dtor-privacy" ] ;
|
||||
case "mingw*" :
|
||||
properties = [ impose-requirements $(properties) : <cxxflags>"-Wno-non-virtual-dtor -Wno-ctor-dtor-privacy" ] ;
|
||||
case "borland*" :
|
||||
properties = [ impose-requirements $(properties) : <cxxflags>"-w-8080 -w-8071 -w-8057 -w-8062 -w-8008 -w-0018 -w-8066" ] ;
|
||||
}
|
||||
return $(subvariant-path) $(properties) ;
|
||||
}
|
||||
|
||||
# set optimization switches for certain toolsets. We do it here rather than in the
|
||||
# Jamfile requirements because here we can use a regex for the compiler name.
|
||||
rule toolset::optimizations ( toolset variant : subvariant-path properties * )
|
||||
{
|
||||
switch $(toolset) {
|
||||
case "vc*" :
|
||||
properties = [ impose-requirements $(properties) : <cxxflags>"-Gy" ] ;
|
||||
case "msvc" :
|
||||
properties = [ impose-requirements $(properties) : <cxxflags>"-Gy" ] ;
|
||||
}
|
||||
return $(subvariant-path) $(properties) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+186
-266
@@ -14,273 +14,194 @@
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Serialization</h1>
|
||||
<h2 align="center">Archive Concept</h2>
|
||||
<h2 align="center">Archive Concepts</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#saving_interface">Saving</a>
|
||||
<dt><a href="#loading_interface">Loading</a>
|
||||
<dt><a href="#saving_interface">Saving Archive Concept</a>
|
||||
<dt><a href="#loading_interface">Loading Archive Concept</a>
|
||||
<dt><a href="#archive_models">Models</a>
|
||||
<dt><a href="#exceptions">Exceptions</a>
|
||||
<dt><a href="#charactersets">Character Sets</a>
|
||||
</dl>
|
||||
|
||||
An <strong>Archive</strong> contains a sequence of bytes created from
|
||||
an arbitrary nested set of C++ data structures.
|
||||
|
||||
<h4><a name="saving_interface">Saving</a></h4>
|
||||
An object that saves data to an archive implements the following interface.
|
||||
<pre><code>
|
||||
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);
|
||||
};
|
||||
...
|
||||
};
|
||||
</code></pre>
|
||||
|
||||
The template parameter <code>T</code> must correspond to a type which
|
||||
models the <a href="serialization.html"><strong>Serializable</strong></a> concept.
|
||||
|
||||
<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
|
||||
<h4>Notation</h4>
|
||||
In the following descriptions
|
||||
<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.
|
||||
<li><code>SA</code> is an type modeling the <a href="#loading_interface">Saving Archive Concept</a>
|
||||
<li><code>sa</code> is an instance of type SA.
|
||||
<li><code>LA</code> is an type modeling the <a href="#loading_interface">Loading Archive Concept</a>
|
||||
<li><code>la</code> is an instance of type LA.
|
||||
<li><code>T</code> is an <a href="serialization.html"><strong>Serializable</strong></a> Type
|
||||
<li><code>x</code> is an instance of type T Type</li>.
|
||||
<li><code>u,v</code> is a pointer to a an instance of type T
|
||||
<li><code>count</code> is an instance of a type that can be converted to <code>std::size_t</code>.
|
||||
</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>
|
||||
|
||||
<h4><a name="saving_interface">Saving Archive Concept</a></h4>
|
||||
<h4>Associated Types</h4>
|
||||
Intuitively, a type modeling this concept will generate a sequence of bytes
|
||||
correpsonding to an arbitrary set of C++ data structures. Each type modeling the
|
||||
Saving Archive concept (SA) may be associated with another type modeling the
|
||||
<a href="#loading_interface">Loading Archive Concept</a>(LA).
|
||||
This associated type will perform the inverse operation.
|
||||
That is, given a sequence of bytes generated by SA, it will generate a set of
|
||||
C++ data structures the is equivalent to the original.
|
||||
The notion of equivalence is defined by the implementations of the pair of archives and the
|
||||
way the data is are rendered <a href="serialization.html">serializable</a>.
|
||||
<p>
|
||||
<h4>Valid Expressions</h4>
|
||||
<dl>
|
||||
<dt><h4><code>
|
||||
SA::is_saving
|
||||
</code></h4></dt>
|
||||
<dd>
|
||||
Returns the Boost MPL Integral Constant type boost::mpl::bool_<true>
|
||||
</dd>
|
||||
<dt><h4><code>
|
||||
SA::is_loading
|
||||
</code></h4></dt>
|
||||
<dd>
|
||||
Returns the Boost MPL Integral Constant type boost::mpl::bool_<false>
|
||||
</dd>
|
||||
<dt><h4><code>
|
||||
sa << x
|
||||
<br>
|
||||
sa & x
|
||||
</code></h4></dt>
|
||||
<dd>
|
||||
These expressions must perform exactly the same function. They append the
|
||||
value of <code style="white-space: normal">x</code> along with other information to <code>sa</code>.
|
||||
This other information is defined by the implementation of the archive.
|
||||
Typically this information is that which is required by a corresponding
|
||||
Loading Archive type to properly restore the value of <code>x</code>.
|
||||
<p>
|
||||
Returns a reference to <code>sa</code>.
|
||||
</dd>
|
||||
<dt><h4><code>
|
||||
sa.save_binary(u, count)
|
||||
</code></h4></dt>
|
||||
<dd>
|
||||
Appends to the archive <code style="white-space: normal">size_t(count)</code> bytes found at
|
||||
<code style="white-space: normal">u</code>.
|
||||
</dd>
|
||||
<dt><h4><code>
|
||||
sa.register_type<T>()
|
||||
<br>
|
||||
sa.register_type(u)
|
||||
</code></h4></dt>
|
||||
<dd>
|
||||
Appends information about class T to the archive. This information is used to
|
||||
construct the correct class when a derived pointer is loaded by a corresponding
|
||||
Loading Archive type.
|
||||
Invocation of this member function is referred to as "class registration".
|
||||
This is explained in detail in
|
||||
<a href="special.html#derivedpointers">Special Considerations - Derived Pointers</a>.
|
||||
The second syntax is included to permit this function to be called on non-conforming
|
||||
compilers when <code style="white-space: normal">sa</code> is a template argument.
|
||||
For more information, see <a target="detail" href="implementation.html#tempatesyntax">Template Invocation syntax</a>
|
||||
</dd>
|
||||
<dt><h4><code>
|
||||
sa.library_version()
|
||||
</code></h4></dt>
|
||||
<dd>
|
||||
Returns an unsigned integer containing the current version number of the serialization
|
||||
library. 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>
|
||||
</dl>
|
||||
|
||||
<h4><a name="loading_interface">Loading</a></h4>
|
||||
An object that saves data to an archive implements the following interface.
|
||||
|
||||
<pre><code>
|
||||
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);
|
||||
|
||||
reset_object_address(void * old_address, void * new_address);
|
||||
|
||||
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);
|
||||
};
|
||||
...
|
||||
};
|
||||
|
||||
} //namespace archive
|
||||
) //namespace boost
|
||||
|
||||
</code></pre>
|
||||
|
||||
<h4><a name="loading_interface">Loading Archive Concept</a></h4>
|
||||
<h4>Associated Types</h4>
|
||||
Each model of this concept presumes the
|
||||
existence of a corresponding type modeling the
|
||||
<a href="#saving_interface">Saving Archive Concept</a>.
|
||||
The purpose of an instance of this concept is to convert a sequence of bytes
|
||||
generated by this corresponding type to a set of C++ data structures
|
||||
equivalent to the original.
|
||||
<h4>Valid Expressions</h4>
|
||||
<dl>
|
||||
|
||||
The template parameter <code>T</code> must correspond to a type which
|
||||
models the <a href="serialization.html"><strong>Serializable</strong></a> concept.
|
||||
|
||||
<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>
|
||||
void reset_object_address(void * new_address, void * old_address);
|
||||
</code></h4></dt>
|
||||
<dd>
|
||||
In order to facilitate loading of objects through a pointer
|
||||
and to elminate redundant loading of objects, this system implements object address tracking.
|
||||
Normally this is done automatically with no action required on the part of the user. However,
|
||||
there are cases when an object must be de-serialized to a temporary location then
|
||||
moved to its final destination. This is common in loading collections.
|
||||
<p>
|
||||
In such cases, reset_object_address should be invoked to communicate the final address
|
||||
of the last item loaded. This permits the internal tables to be correctly maintained
|
||||
in these special case.
|
||||
</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>
|
||||
LA::is_saving
|
||||
</code></h4></dt>
|
||||
<dd>
|
||||
Returns the Boost MPL Integral Constant type boost::mpl::bool_<false>
|
||||
</dd>
|
||||
<dt><h4><code>
|
||||
LA::is_loading
|
||||
</code></h4></dt>
|
||||
<dd>
|
||||
Returns the Boost MPL Integral Constant type boost::mpl::bool_<true>
|
||||
</dd>
|
||||
<dt><h4><code>
|
||||
la >> x
|
||||
<br>
|
||||
la & x
|
||||
</code></h4></dt>
|
||||
<dd>
|
||||
These expressions must perform exactly the same function.
|
||||
Sets <code>x</code> to a value retrieved from <code>la</code>.
|
||||
<p>
|
||||
Returns a reference to <code>la</code>.
|
||||
</dd>
|
||||
<dt><h4><code>
|
||||
la.load_binary(u, count)
|
||||
</code></h4></dt>
|
||||
<dd>
|
||||
Retrieves from <code style="white-space: normal">la</code> <code style="white-space: normal">size_t(count)</code> bytes and stores
|
||||
them in memory starting at <code style="white-space: normal">u</code>.
|
||||
</dd>
|
||||
<dt>
|
||||
<dt><h4><code>
|
||||
la.register_type<T>()
|
||||
<br>
|
||||
la.register_type(u)
|
||||
</code></h4></dt>
|
||||
<dd>
|
||||
Retrieves information about class T from the archive. This information is used to
|
||||
construct the correct class when loading a pointer to a derived class not
|
||||
otherwise referred to in the program by name.
|
||||
Invocation of this member function is referred to as "class registration".
|
||||
This is explained in detail in
|
||||
<a href="special.html#derivedpointers">Special Considerations - Derived Pointers</a>.
|
||||
The second syntax is included to permit this function to be called on non-conforming
|
||||
compilers when <code style="white-space: normal">la</code> is a template argument.
|
||||
For more information, see <a target="detail" href="implementation.html#tempatesyntax">Template Invocation syntax</a>
|
||||
</dd>
|
||||
<dt><h4><code>
|
||||
la.library_version()
|
||||
</code></h4></dt>
|
||||
<dd>
|
||||
Returns an unsigned integer containing 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>
|
||||
la.reset_object_address(v, u)
|
||||
</code></h4></dt>
|
||||
<dd>
|
||||
Communicates to the archive that the object originally at address u has been
|
||||
moved to address v.
|
||||
<p>
|
||||
When an object is loaded to a temporary variable and later moved to another location,
|
||||
This function must be called in order communicate this fact. This is permits the
|
||||
the archive to properly implement object tracking. Object tracking is required in order
|
||||
to correctly implement serialization of pointers to instances of derived classes.
|
||||
</dd>
|
||||
<dt><h4><code>
|
||||
la.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>
|
||||
</dl>
|
||||
|
||||
There are archives based on text, binary and XML file
|
||||
@@ -308,7 +229,6 @@ This library includes a various implementation of the Archive concept.
|
||||
An archive is defined by two complementary classes. One is for saving data while
|
||||
the other is for loading it.
|
||||
|
||||
|
||||
This library includes a number of archive implementations that are "ready to go" for the
|
||||
most common requirements. These classes implement the archive concept for differing data formats.
|
||||
They can be used "as is" or as a basis for developing one's own particular type of archive.
|
||||
@@ -319,28 +239,28 @@ 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 href="../../../boost/archive/text_oarchive.hpp" target="text_oarchive_cpp">boost::archive::text_oarchive</a> // saving
|
||||
<a href="../../../boost/archive/text_iarchive.hpp" target="text_iarchive_cpp">boost::archive::text_iarchive</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 href="../../../boost/archive/text_woarchive.hpp">boost::archive::text_woarchive</a> // saving
|
||||
<a href="../../../boost/archive/text_wiarchive.hpp">boost::archive::text_wiarchive</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 href="../../../boost/archive/binary_oarchive.hpp" target="binary_oarchive_cpp">boost::archive::binary_oarchive</a> // saving
|
||||
<a href="../../../boost/archive/binary_iarchive.hpp" target="binary_iarchive_cpp">boost::archive::binary_iarchive</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 href="../../../boost/archive/binary_woarchive.hpp">boost::archive::binary_woarchive</a> // saving
|
||||
<a href="../../../boost/archive/binary_wiarchive.hpp">boost::archive::binary_wiarchive</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 href="../../../boost/archive/xml_oarchive.hpp" target="xml_oarchive_cpp">boost::archive::xml_oarchive</a> // saving
|
||||
<a href="../../../boost/archive/xml_iarchive.hpp" target="xml_iarchive_cpp">boost::archive::xml_iarchive</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
|
||||
<a href="../../../boost/archive/xml_woarchive.hpp" target="xml_woarchive_cpp">boost::archive::xml_woarchive</a> // saving
|
||||
<a href="../../../boost/archive/xml_wiarchive.hpp" target="xml_wiarchive_cpp">boost::archive::xml_wiarchive</a> // loading
|
||||
</code></pre>
|
||||
|
||||
All of these archives implement the same inteface. Hence, it should suffice to describe only one
|
||||
|
||||
+21
-21
@@ -1,4 +1,4 @@
|
||||
<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!--
|
||||
(C) Copyright 2002-4 Robert Ramey - http://www.rrsd.com .
|
||||
@@ -111,12 +111,12 @@ function initialize() {
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="tutorial.html#examples">List of Examples</a>
|
||||
</dl></div></dd>
|
||||
|
||||
<dt><img style="display:none" src="plus.gif" id="reference"><a target="detail" href="archives.html">Reference</a></dt>
|
||||
<dt><img style="display:none" src="plus.gif" id="reference"><a target="detail" href="reference.html">Reference</a></dt>
|
||||
<dd><div id="reference_detail"><dl class="page-index">
|
||||
<dt><img style="display:none" src="plus.gif" id="archive_concept"><a target="detail" href="archives.html">Archive Concept</a>
|
||||
<dt><img style="display:none" src="plus.gif" id="archive_concept"><a target="detail" href="archives.html">Archive Concepts</a>
|
||||
<dd><div id="archive_concept_detail"><dl class="page-index">
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="archives.html#saving_interface">Saving</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="archives.html#loading_interface">Loading</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="archives.html#saving_interface">Saving Archive Concept</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="archives.html#loading_interface">Loading Archive Concept</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="archives.html#archive_models">Archive Models</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="archives.html#exceptions">Exceptions</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="archives.html#charactersets">Character Sets</a>
|
||||
@@ -159,7 +159,7 @@ function initialize() {
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="wrappers.html#nvp">Name-Value Pairs</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="wrappers.html#composition">Composition</a>
|
||||
</dl></div></dd>
|
||||
<dt><img style="display:none" src="plus.gif" id="traits"><a target="detail" href="traits.html#Traits">Class Serialization Traits</a>
|
||||
<dt><img style="display:none" src="plus.gif" id="traits"><a target="detail" href="traits.html">Class Serialization Traits</a>
|
||||
<dd><div id="traits_detail"><dl class="page-index">
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="traits.html#version">Version</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="traits.html#level">Implementation Level</a>
|
||||
@@ -173,8 +173,8 @@ function initialize() {
|
||||
</dl></div></dd>
|
||||
<dt><img style="display:none" src="plus.gif" id="special"><a target="detail" href="special.html">Special Considerations</a>
|
||||
<dd><div id="special_detail"><dl class="page-index">
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="special.html#headersequence">Header Inclusion Sequence</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="special.html#objecttracking">Object Tracking</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="special.html#export">Exporting Class Serialization</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="special.html#classinfo">Class Information</a>
|
||||
<dt><img style="display:none" src="plus.gif" id="portability"><a target="detail" href="special.html#portability">Archive Portability</a>
|
||||
<dd><div id="portability_detail"><dl class="page-index">
|
||||
@@ -194,19 +194,19 @@ function initialize() {
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="exceptions.html#stream_error"><code>stream_error</code></a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="exceptions.html#invalid_class_name"><code>invalid_class_name</code></a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="exceptions.html#unregistered_cast"><code>unregistered_cast</code></a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="exceptions.html#xml_archive_parse_error"><code>xml_archive_parse_error</code></a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="exceptions.html#xml_archive_parsing_error"><code>xml_archive_parsing_error</code></a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="exceptions.html#xml_archive_tag_mismatch"><code>xml_archive_tag_mismatch</code></a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="exceptions.html#xml_archive_tag_name_error"><code>xml_archive_tag_name_error</code></a>
|
||||
</dl></div></dd>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="exception_safety.html">Exception Safety</a>
|
||||
</dl></div></dd>
|
||||
<dt><img style="display:none" src="plus.gif" id="archive_reference"><a target="detail" href="archive_reference.html">Archive Class Reference</a>
|
||||
<dd><div id="archive_reference_detail"><dl class="page-index">
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="archive_reference.html#implementation">Implementation</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="archive_reference.html#usage">Usage</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="archive_reference.html#testing">Testing</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="archive_reference.html#polymorphic">Polymorphic Archives</a>
|
||||
</dl></div></dd>
|
||||
</dl></div></dd>
|
||||
<dt><img style="display:none" src="plus.gif" id="archive_reference"><a target="detail" href="archive_reference.html">Archive Class Reference</a>
|
||||
<dd><div id="archive_reference_detail"><dl class="page-index">
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="archive_reference.html#implementation">Implementation</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="archive_reference.html#usage">Usage</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="archive_reference.html#testing">Testing</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="archive_reference.html#polymorphic">Polymorphic Archives</a>
|
||||
</dl></div></dd>
|
||||
<dt><img style="display:none" src="plus.gif" id="implementation"><a target="detail" href="implementation.html">Implementation Notes</a>
|
||||
<dd><div id="implementation_detail"><dl class="page-index">
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="implementation.html#functiontemplateordering">Partial Function Template Ordering</a>
|
||||
@@ -215,9 +215,10 @@ function initialize() {
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="implementation.html#partialtemplatespecialization">Partial Template Specialization</a>
|
||||
<dt><img style="display:none" src="plus.gif" id="othercompilerissues"><a target="detail" href="implementation.html#othercompilerissues">Specific Compiler/Library Issues</a>
|
||||
<div id="othercompilerissues_detail"><dl class="page-index">
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="implementation.html#gcc3x">GCC 3.x</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="implementation.html#gcc3x">GCC 3.X,4.X</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="implementation.html#gcc295">GCC 2.95</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="implementation.html#intel80">Intel 8.0</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="implementation.html#vc80">Visual C++ 8.0</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="implementation.html#vc71">Visual C++ 7.1</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="implementation.html#vc70">Visual C++ 7.0</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="implementation.html#vc6">Visual C++ 6.0</a>
|
||||
@@ -261,7 +262,7 @@ function initialize() {
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="extended_type_info.html#runtime">Runtime Interface</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="extended_type_info.html#requirements">Requirements</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="extended_type_info.html#models">Models</a>
|
||||
</dl>
|
||||
</dl></div></dd>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="void_cast.html"><code>void_cast</code></a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="codecvt.html">utf-8 code_cvt</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="strong_typedef.html"><code>BOOST_STRONG_TYPEDEF</code></a>
|
||||
@@ -269,7 +270,7 @@ function initialize() {
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="dataflow.html">Dataflow Iterators</a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="smart_cast.html"><code>smart_cast</code></a>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="static_warning.html"><code>BOOST_STATIC_WARNING</code></a>
|
||||
</dl></div></dd>
|
||||
</dl></div></dd>
|
||||
<!--
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="configuration.html">Configuration Information</a></dt>
|
||||
-->
|
||||
@@ -279,7 +280,7 @@ function initialize() {
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="rationale.html#archives">Archives are not streams</a></dt>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="rationale.html#typeid"><code style="white-space: normal">typeid</code> information is not included in archives</a></dt>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="rationale.html#trap">Compile time trap when saving a non-const value</a></dt>
|
||||
</dl>
|
||||
</dl></div></dd>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="history.html">History</a>
|
||||
<!--
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="definitions.html">Definitions</a></dt>
|
||||
@@ -287,7 +288,6 @@ function initialize() {
|
||||
-->
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="bibliography.html">Bibliography</a></dt>
|
||||
<dt><img style="display:none" src="dot.gif"><a target="detail" href="acknowledgments.html">Acknowledgments</a></dt>
|
||||
|
||||
</dl></div>
|
||||
</small>
|
||||
</body>
|
||||
|
||||
+1
-1
@@ -200,7 +200,7 @@ at runtime, a collection of legitimate conversions is maintained by the system.
|
||||
Normally this collection is maintained without any explicit action
|
||||
on the part of the user of the library. However, there are special cases
|
||||
where this might have to be done explicitly and could be overlooked. This
|
||||
is described in <a href="special.html#runtimecasting">Runtime Casting</a>.
|
||||
is described in <a href="serialization.html#runtimecasting">Runtime Casting</a>.
|
||||
This exception is thrown if an attempt is made to convert between two pointers
|
||||
whose relationship has not been registered,
|
||||
|
||||
|
||||
+42
-13
@@ -32,9 +32,10 @@ http://www.boost.org/LICENSE_1_0.txt)
|
||||
<dt><a href="#partialtemplatespecialization">Partial Template Specialization</a>
|
||||
<dt><a href="#othercompilerissues">Specific Compiler/Library Issues</a>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#gcc3x">GCC 3.X, 4.x</a>
|
||||
<dt><a href="#gcc3x">GCC 3.X, 4.X</a>
|
||||
<dt><a href="#gcc295">GCC 2.95</a>
|
||||
<dt><a href="#intel80">Intel 8.0</a>
|
||||
<dt><a href="#vc80">Visual C++ 8.0</a>
|
||||
<dt><a href="#vc71">Visual C++ 7.1</a>
|
||||
<dt><a href="#vc70">Visual C++ 7.0</a>
|
||||
<dt><a href="#vc6">Visual C++ 6.0</a>
|
||||
@@ -199,11 +200,26 @@ the syntax described above.
|
||||
</ul>
|
||||
<h3><a name="othercompilerissues">Specific Compiler/Library Issues</a></h3>
|
||||
|
||||
<h4><a name="gcc3x">GCC 3.X, 4.x</a></h4>
|
||||
GCC versions for Cygwin and MinGW fail to support wide character I/O.
|
||||
So all tests using wide char I/O fail. Note that if wide character I/O support
|
||||
is added with STLPort, all tests complete successfully.
|
||||
|
||||
<h4><a name="gcc3x">GCC 3.X, 4.X</a></h4>
|
||||
<ul>
|
||||
<li>GCC versions for Cygwin and MinGW fail to support wide character I/O.
|
||||
So all tests using wide char I/O fail. Note that if wide character I/O support
|
||||
is added with STLPort, all tests complete successfully.
|
||||
<li>This compiler generates long warning messages related to the usage of
|
||||
non virtual destructors in polymorphic classes. These warnings have been
|
||||
carfully considered and the code that generates these warning has been
|
||||
unchanged. In this case the warning should should be ignored as in certain
|
||||
usages of the library, making the destructors virtual could lead to problems.
|
||||
As an alternative, base class destructors have been make "protected" to
|
||||
address the concerns that motivate these warning messages. When building
|
||||
the serialization library and tests with bjam, these warnings are suppressed.
|
||||
When building one's own applications, these warnings can be suppressed by
|
||||
adding the following to the compiler command line:
|
||||
<pre><code>
|
||||
-Wno-non-virtual-dtor
|
||||
-Wno-ctor-dtor-privacy
|
||||
</code></pre>
|
||||
</ul>
|
||||
<h4><a name="gcc295">GCC 2.95</a></h4>
|
||||
All of the above plus:<br>
|
||||
<ul>
|
||||
@@ -212,11 +228,21 @@ All of the above plus:<br>
|
||||
<li>Polymorphic archive tests fail.
|
||||
<li>XML serialization only works with version 1.6x of spirit. In order to build
|
||||
and use this library with this compiler, one must use version 1.6x rather than the
|
||||
latest version shipped with boost. See Release Notes.
|
||||
latest version shipped with boost. See <a href="release.html">Release Notes</a>.
|
||||
</ul>
|
||||
<h4><a name="Intel80">Intel C++ 8.0</a></h4>
|
||||
No known issues. All tests compile and run in debug and release modes.
|
||||
|
||||
<h4><a name="vc80">Visual C++ 8.0</a></h4>
|
||||
This compiler emits warnings for calls to functions from the standard
|
||||
library which are deemed security risks. The serialization depends upon
|
||||
making some of these calls so programs which use the serialization library
|
||||
will get warning messages. These messages can be suppressed from the command
|
||||
line by including the following switch:
|
||||
<pre><code>
|
||||
/wd4996
|
||||
</code></pre>
|
||||
|
||||
<h4><a name="vc71">Visual C++ 7.1</a></h4>
|
||||
Derivation from an archive class defined in a DLL as described in ... will not work.
|
||||
This is due to the way that VC++ handles templeted code with __decl(dllexport) and
|
||||
@@ -280,15 +306,19 @@ decided to use these configurations.
|
||||
<li>The "pimpl" demo fails to link. Cause and workaround for this is unknown
|
||||
<li>XML serialization only works with version 1.6x of spirit. In order to build and use this
|
||||
library with this compiler, one must use version 1.6x rather than the latest version
|
||||
shipped with boost. See <a href="release.html#Installation">Release Notes</a>.
|
||||
shipped with boost. See <a href="release.html">Release Notes</a>.
|
||||
<li>This compiler does not support partial template specialization.
|
||||
The implementation of the new <code>shared_ptr</code> serialization depends upon
|
||||
compiler support for partial template specialization. This compiler doesn't implement this
|
||||
feature. In order to serialize <code style="white-space: normal">shared_ptr<A></code>,
|
||||
invoke the macro <code style="white-space: normal">BOOST_SERIALIZATION_SHARED_PTR(A)</code>
|
||||
in the header code.
|
||||
<li>Lack of support for partial template specialization also creates problems for
|
||||
serialization of <code style="white-space: normal">std::map</code>. In order to serialize
|
||||
instances of this type include the invocation of BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION
|
||||
for the key type of the map.
|
||||
</ul>
|
||||
<h4><a name="vc6">Visual C++ 6.0</a></h4>
|
||||
<h4><a name="vc6">Visual C++ 6.5</a></h4>
|
||||
all the above issues for Visual C++ 7.0 plus:
|
||||
<ul>
|
||||
<li>Out of line template definitions are not recognized and fail with a confusing
|
||||
@@ -326,7 +356,6 @@ all the above issues for Visual C++ 7.0 plus:
|
||||
<li>Code modules exceeding some undetermined size that use the library will fail with
|
||||
<i>fatal error C1204: compiler limit : internal structure overflow</i>. This can be addressed
|
||||
by dividing the module into smaller ones.
|
||||
<li>The library cannot be built as a DLL with this compiler.
|
||||
</ul>
|
||||
<h4><a name="borland">Borland 5.64 and 5.51</a></h4>
|
||||
<ul>
|
||||
@@ -341,7 +370,7 @@ all the above issues for Visual C++ 7.0 plus:
|
||||
with this compiler.
|
||||
<li>XML serialization only works with version 1.6x of spirit. In order to build
|
||||
and use this library with this compiler, one must use version 1.6x rather than the
|
||||
latest version shipped with boost. See Release Notes.
|
||||
latest version shipped with boost. See <a href="release.html">Release Notes</a>.
|
||||
</ul>
|
||||
<h4><a name="comeau">Comeau 4.3.3</a></h4>
|
||||
<ul>
|
||||
@@ -375,8 +404,8 @@ These platforms have several issues:
|
||||
<li>The dinkumware library shipped with this compiler does not change the locale facet
|
||||
of an i/o stream unless the <code style="white-space: normal">imbue</code> function is called before the the
|
||||
stream is opened. In order to use this library with this environment to generate UTF-8
|
||||
files, one cannot depend on the "automatic" setting of local that archives implement. The
|
||||
stream local must be set explicitly on the stream before an archive is opened on it. The
|
||||
files, one cannot depend on the "automatic" setting of locale that archives implement. The
|
||||
stream locale must be set explicitly on the stream before an archive is opened on it. The
|
||||
archive should be opened with the <code style="white-space: normal">no_codecvt</code> flag. Note this problem will
|
||||
occur on all compilers shipped with this library.
|
||||
<li>Other issues have been worked around in the file.
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ http://www.boost.org/LICENSE_1_0.txt)
|
||||
the reversible deconstruction of an arbitrary set of C++ data structures
|
||||
to a sequence of bytes. Such a system can be used to reconstitute
|
||||
an equivalent structure in another program context. Depending on
|
||||
this context, this might used implement object persistence, remote
|
||||
the context, this might used implement object persistence, remote
|
||||
parameter passing or other facility. In this system we use the term
|
||||
<strong>"archive"</strong> to refer to a specific rendering of this
|
||||
stream of bytes. This could be a file of binary data, text data,
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!--
|
||||
(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)
|
||||
-->
|
||||
<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 - Serialization of Classes</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="../../../boost.png" border="0"></a></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Serialization</h1>
|
||||
<h2 align="center">Serializable Concept</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<dl class="page-index">
|
||||
<dt><a href="archives.html">Archive Concepts</a>
|
||||
<dt><a href="serialization.html">Serializable Concept</a>
|
||||
<dt><a href="special.html">Special Considerations</a>
|
||||
<dt><a href="archive_reference.html">Archive Class Reference</a>
|
||||
<dt><a href="implementation.html">Implementation Notes</a>
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
<p><i>© Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2002-2004.
|
||||
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)
|
||||
</i></p>
|
||||
</body>
|
||||
</html>
|
||||
+4
-1
@@ -90,13 +90,16 @@ at the front of the list of include paths.
|
||||
and <code style="white-space: normal">std::wstring</code> contain characters such as
|
||||
'\0' which cannot be rendered in XML without an escape mechanism. Currently there is
|
||||
no such escape mechanism implemented.
|
||||
<li>A subtle error in the implementation of serialiaton of <code style="white-space: normal">std::map</code>
|
||||
is fixed in this version. Unfortunately, the fix breaks serialization of
|
||||
<code style="white-space: normal">std::map</code> for those compilers which do not support
|
||||
partial template specialization.
|
||||
</ul>
|
||||
<p>
|
||||
Aside from the above, there are a number of issus related to specific platforms.
|
||||
These are listed in <a href="implementation.html#othercompilerissues">Specific Compiler/Library Issues</a>.
|
||||
|
||||
|
||||
|
||||
<hr>
|
||||
<p><i>© Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2002-2004.
|
||||
Distributed under the Boost Software License, Version 1.0. (See
|
||||
|
||||
+39
-20
@@ -1,4 +1,4 @@
|
||||
<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!--
|
||||
(C) Copyright 2002-4 Robert Ramey - http://www.rrsd.com .
|
||||
@@ -77,8 +77,7 @@ if and only if one of the following is true:
|
||||
<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.
|
||||
<li>it is a class type one of the following is true for all archive classes:
|
||||
it is a class type and for all <strong>Archive</strong> classes, one of the following
|
||||
<li>It is a class type and for all <strong>Archive</strong> classes, one of the following
|
||||
has been declared:
|
||||
<ul>
|
||||
<li>a class member function <code style="white-space: normal">serialize</code>
|
||||
@@ -194,6 +193,12 @@ templates can be in any of the following namespaces:
|
||||
<li>namespace of the archive class
|
||||
<li>namespace of the type being serialized
|
||||
</ul>
|
||||
<p>
|
||||
Note that, at first glance, this suggestion may seem to be wrong for compilers which implement
|
||||
two phase lookup. In fact, the serialization library used a perhaps overly clever
|
||||
method to support this rule even for such compilers. Those with an interest in studying
|
||||
this furter will find more information in
|
||||
<a target=serialization_hpp href="../../../boost/serialization/serialization.hpp">serialization.hpp</a>
|
||||
|
||||
<h3><a name="classmembers">Serialization of Class Members</a></h3>
|
||||
Regardless of which of the above methods is used, the body of the serialize function must
|
||||
@@ -207,7 +212,6 @@ specify the data to be saved/loaded by sequential application of the archive
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
|
||||
<h4><a name="base">Base Classes</a></h4>
|
||||
The header file
|
||||
<a href="../../../boost/serialization/base_object.hpp" target="base_object_hpp">
|
||||
@@ -285,8 +289,7 @@ shared_ptr.hpp
|
||||
</a>
|
||||
<!--
|
||||
Only the most minimal change to
|
||||
<a href="../../../boost/serialization/shared_count.hpp" target="shared_count_hpp">
|
||||
shared_count.hpp</a>
|
||||
<code>shared_count.hpp</code>
|
||||
(to gain access to some private members) was necessary to achieve this.
|
||||
This should demonstrate how easy it is to non-intrusively
|
||||
implement serialization to any data type or template.
|
||||
@@ -585,19 +588,28 @@ class derived_two : public base {
|
||||
main(){
|
||||
...
|
||||
base *b;
|
||||
...
|
||||
ar & b;
|
||||
}
|
||||
</code></pre>
|
||||
When saving <code style="white-space: normal">b</code> what kind of object should be saved?
|
||||
When loading <code style="white-space: normal">b</code> what kind of object should be created?
|
||||
An object of class <code style="white-space: normal">derived_one</code>,
|
||||
Should it be an object of class <code style="white-space: normal">derived_one</code>,
|
||||
<code style="white-space: normal">derived_two</code>, or maybe <code style="white-space: normal">base</code>?
|
||||
<p>
|
||||
If this situation is not addressed by one of the methods described below,
|
||||
an <a target="detail" href="exceptions.html#unregistered_class">
|
||||
<code style="white-space: normal">unregistered_class</code></a> exception will be thrown when serialization is
|
||||
invoked.
|
||||
<p>Many times this situation is resolved automatically by the serialization
|
||||
library.
|
||||
It turns out that the kind of object serialized depends upon whether the base class
|
||||
(<code style="white-space: normal">base</code> in this case) is polymophic or not.
|
||||
If <code style="white-space: normal">base</code> is not polymorphic, that is if it has no
|
||||
virtual functions, then an object of the type <code style="white-space: normal">base</code>
|
||||
will be serialized. Information in any derived classes will be lost. If this is what is desired
|
||||
(it usually isn't) then no other effort is required.
|
||||
<p>
|
||||
|
||||
If the base class is polymorphic, an object of the most derived type
|
||||
(<code style="white-space: normal">derived_one</code>
|
||||
or <code style="white-space: normal">derived_two</code>
|
||||
in this case) will be serialized. The question of which type of object is to be
|
||||
serialized is (almost) automatically handled by the library.
|
||||
<p>
|
||||
The system "registers" each class in an archive the first time an object of that
|
||||
class it is serialized and assigns a sequential number to it. Next time an
|
||||
@@ -608,31 +620,36 @@ the class being read. Note that this implies that "registration" has to occur
|
||||
during both save and load so that the class-integer table built on load
|
||||
is identical to the class-integer table built on save. In fact, the key to
|
||||
whole serialization system is that things are always saved and loaded in
|
||||
the same sequence. This includes "registration"
|
||||
the same sequence. This includes "registration".
|
||||
<p>
|
||||
In many situations the problem never comes up. Consider:
|
||||
Expanding our previous example:
|
||||
<pre><code>
|
||||
main(){
|
||||
derived_one d1;
|
||||
derived_two d2:
|
||||
...
|
||||
ar >> d1;
|
||||
ar >> d2;
|
||||
ar & d1;
|
||||
ar & d2;
|
||||
// A side effect of serialization of objects d1 and d2 is that
|
||||
// the classes derived_one and derived_two become known to the archive.
|
||||
// So subsequent serialization of those classes by base pointer works
|
||||
// without any special considerations.
|
||||
base *b;
|
||||
...
|
||||
ar & b;
|
||||
}
|
||||
</code></pre>
|
||||
Here, the problem doesn't present itself. When <code style="white-space: normal">b</code> is read it is
|
||||
When <code style="white-space: normal">b</code> is read it is
|
||||
preceded by a unique (to the archive) class identifier which
|
||||
has previously been related to class <code style="white-space: normal">derived_one</code> or
|
||||
<code style="white-space: normal">derived_two</code>.
|
||||
<p>
|
||||
If a derived class hasn't been automatically "registered" as described
|
||||
above, we have the option of registering it explicitly. All archives are
|
||||
If a derived class has NOT been automatically "registered" as described
|
||||
above, an <a target="detail" href="exceptions.html#unregistered_class">
|
||||
<code style="white-space: normal">unregistered_class</code></a> exception
|
||||
will be thrown when serialization is invoked.
|
||||
<p>
|
||||
This can be addressed by registering the derived class explicitly. All archives are
|
||||
derived from a base class which implements the following template:
|
||||
<pre><code>
|
||||
template<class T>
|
||||
@@ -645,6 +662,7 @@ main(){
|
||||
ar.template register_type<derived_one>();
|
||||
ar.template register_type<derived_two>();
|
||||
base *b;
|
||||
...
|
||||
ar & b;
|
||||
}
|
||||
</code></pre>
|
||||
@@ -668,6 +686,7 @@ BOOST_CLASS_EXPORT_GUID(derived_two, "derived_two")
|
||||
main(){
|
||||
...
|
||||
base *b;
|
||||
...
|
||||
ar & b;
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
+101
-14
@@ -26,8 +26,8 @@ http://www.boost.org/LICENSE_1_0.txt)
|
||||
</table>
|
||||
<hr>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#headersequence">Header Inclusion Sequence</a>
|
||||
<dt><a href="#objecttracking">Object Tracking</a>
|
||||
<dt><a href="#export">Exporting Class Serialization</a>
|
||||
<dt><a href="#classinfo">Class Information</a>
|
||||
<dt><a href="#portability">Archive Portability</a>
|
||||
<dl class="page-index">
|
||||
@@ -40,17 +40,6 @@ http://www.boost.org/LICENSE_1_0.txt)
|
||||
<dt><a href="exception_safety.html">Exception Safety</a>
|
||||
</dl>
|
||||
|
||||
<h3><a name="headersequence">Header Inclusion Sequence</a></h3>
|
||||
This library is includes a large number of headers that can be included
|
||||
in user code modules. The section
|
||||
<a href="headers.html">Code Structure</a>
|
||||
contains a summary of these headers.
|
||||
<strong>
|
||||
This library requires that all headers that implement archives be included
|
||||
before any headers that implement class serialization.
|
||||
</strong>
|
||||
Violations of this rule will result in cryptic compile time errors.
|
||||
|
||||
<h3><a name="objecttracking">Object Tracking</a></h3>
|
||||
Depending on how the class is used and other factors, serialized objects
|
||||
may be tracked by memory address. This prevents the same object from being
|
||||
@@ -152,8 +141,6 @@ The alternative of changing the implementation level of a <code style="white-spa
|
||||
would affect all <code style="white-space: normal">long</code>s serialized in the whole
|
||||
program - probably not what one would intend.
|
||||
<p>
|
||||
|
||||
|
||||
It is possible that we may want to track addresses even though
|
||||
the object is never serialized through a pointer. For example,
|
||||
a virtual base class need be saved/loaded only once. By setting
|
||||
@@ -162,6 +149,106 @@ redundant save/load operations.
|
||||
<pre><code>
|
||||
BOOST_CLASS_TRACKING(my_virtual_base_class, boost::serialization::track_always)
|
||||
</code></pre>
|
||||
|
||||
<h3><a name="export">Exporting Class Serialization</a></h3>
|
||||
<a target="detail" href="traits.html#export">Elsewhere</a> in this manual, we have described
|
||||
<code style="white-space: normal">BOOST_CLASS_EXPORT</code>. This is used to make the serialization library aware
|
||||
that code should be instantiated for serialization of a given class even though the
|
||||
class hasn't been otherwise referred to by the program.
|
||||
<p>
|
||||
There are several ways <code style="white-space: normal">BOOST_CLASS_EXPORT</code> could have been
|
||||
implemented.
|
||||
<p>
|
||||
One approach would be to instantiate serialization code for all archive classes included in the library.
|
||||
This would add to each executable a large amount of code that is most likely never called.
|
||||
Also it would needlessly slow down compilations of any program that uses the library. Finally,
|
||||
the list of archives would be "built-in" to the library which would compilicate the addition of
|
||||
new or custom archive classes.
|
||||
<p>
|
||||
Another approach would be for the library user to somehow explicitly instantiate which archive classes
|
||||
code should be instantiated for each class to be serialized. Users would have to include
|
||||
header files corresponding the archive classes to be instantiated.
|
||||
The list of instantiated archive classes would have to be manually kept in sync with the
|
||||
archive class headers actually included. This was considered burdensome and error prone.
|
||||
<p>
|
||||
This implementation of <code style="white-space: normal">BOOST_CLASS_EXPORT</code> works in the
|
||||
following way:
|
||||
<ul>
|
||||
<li>All header modules of the form <boost/archive/*archive.hpp> are required to precede
|
||||
the header module <a href="../../../boost/serialization/export.hpp" target="export_hpp">export.hpp</a>.
|
||||
<li>The header <a href="../../../boost/serialization/export.hpp" target="export_hpp">export.hpp</a>
|
||||
builds a list of archive classes whose header modules have been previously included.
|
||||
It does this by checking to see which inclusion guard constants have been defined.
|
||||
<li><code style="white-space: normal">BOOST_CLASS_EXPORT(my_class)</code> explicitly instantiates
|
||||
serialization code for <code style="white-space: normal">my_class</code> for each archive in the list.
|
||||
</ul>
|
||||
Serialization code will be instantiated for a given archive class
|
||||
if and only if the module that defines that archive class has been included in the program.
|
||||
Given this, our program will contain all necessary code instantiations and no other.
|
||||
<p>
|
||||
For many styles of code organization this header sequencing requirement presents little problem.
|
||||
|
||||
Serialization code organized by class headers that are designed to be independent of archive
|
||||
implementations will look something like the following:
|
||||
<code><pre>
|
||||
// A.hpp
|
||||
// Note:to preserve independence from any particular archive implementation,
|
||||
// no headers from <boost/archive/...> are included.
|
||||
// Headers can be included in any order.
|
||||
#include <boost/serialization/...>
|
||||
#include <boost/serialization/export.hpp>
|
||||
... // include other headers that A depends upon
|
||||
|
||||
class A {
|
||||
...
|
||||
};
|
||||
|
||||
BOOST_CLASS_EXPORT(A) // note: the export name of this class
|
||||
</pre></code>
|
||||
This style:
|
||||
<ul>
|
||||
<li>permits the header to include all aspects of the serialization implementation.
|
||||
<li>permits the header to be included anywhere else as part of some other class declaration.
|
||||
<li>reflects the concept of headers as a "library of types" which
|
||||
can be used independently in other programs or other parts of the same program.
|
||||
<li>reflects a fundamental principle of the serialization library design in that the
|
||||
specification of serialization of any class is independent of any archive implementation.
|
||||
</ul>
|
||||
However, it might not always be possible or convenient to conform to the above style. Something
|
||||
like the following might be required or preferred:
|
||||
<code><pre>
|
||||
// A.hpp
|
||||
// headers can be included in any order
|
||||
#include <boost/archive/text_oarchive.hpp>
|
||||
#include <boost/archive/text_iarchive.hpp>
|
||||
...
|
||||
#include <boost/serialization/...>
|
||||
...
|
||||
// can't do the following because then A.hpp couldn't be included somewhere else
|
||||
// #include <boost/serialization/export.hpp>
|
||||
|
||||
class A {
|
||||
...
|
||||
};
|
||||
// can't do the following because export.hpp is not included !!
|
||||
//BOOST_CLASS_EXPORT(A) // note: the export name of this class
|
||||
</pre></code>
|
||||
As noted in the comments, this would work. But
|
||||
<code style="white-space: normal">#include <.../export.hpp></code> can't be used
|
||||
without conflicting with other modules which use
|
||||
<code style="white-space: normal">#include <.../*archive.hpp></code>. In this
|
||||
case we can move the export to an implementation file:
|
||||
<code><pre>
|
||||
// A.cpp
|
||||
#include "A.hpp"
|
||||
...
|
||||
// export.hpp header should be last;
|
||||
#include <boost/serialization/export.hpp>
|
||||
...
|
||||
BOOST_CLASS_EXPORT(A)
|
||||
...
|
||||
</pre></code>
|
||||
|
||||
<h3><a name="classinfo">Class Information</a></h3>
|
||||
By default, for each class serialized, class information is written to the archive.
|
||||
This information includes version number, implementation level and tracking
|
||||
|
||||
+7
-5
@@ -336,10 +336,11 @@ convenience macros, use the original definitions
|
||||
template<class T>
|
||||
struct implementation_level<nvp<T> >
|
||||
{
|
||||
typedef mpl::int_<object_serializable> type; \
|
||||
typedef mpl::integral_c_tag tag;
|
||||
typedef mpl::int_<object_serializable> type;
|
||||
BOOST_STATIC_CONSTANT(
|
||||
enum level_type,
|
||||
value = static_cast<enum level_type>(type::value)
|
||||
int,
|
||||
value = implementation_level::type::value
|
||||
);
|
||||
};
|
||||
|
||||
@@ -347,10 +348,11 @@ struct implementation_level<nvp<T> >
|
||||
template<class T>
|
||||
struct tracking_level<nvp<T> >
|
||||
{
|
||||
typedef mpl::integral_c_tag tag;
|
||||
typedef mpl::int_<track_never> type;
|
||||
BOOST_STATIC_CONSTANT(
|
||||
enum tracking_type,
|
||||
value = static_cast<enum tracking_type>(type::value)
|
||||
int,
|
||||
value = tracking_level::type::value
|
||||
);
|
||||
};
|
||||
</code></pre>
|
||||
|
||||
+39
-14
@@ -107,24 +107,28 @@ public:
|
||||
int main() {
|
||||
// create and open a character archive for output
|
||||
std::ofstream ofs("filename");
|
||||
boost::archive::text_oarchive oa(ofs);
|
||||
|
||||
// create class instance
|
||||
const gps_position g(35, 59, 24.567f);
|
||||
// write class instance to archive
|
||||
oa << g;
|
||||
// close archive
|
||||
ofs.close();
|
||||
|
||||
// save data to archive
|
||||
{
|
||||
boost::archive::text_oarchive oa(ofs);
|
||||
// write class instance to archive
|
||||
oa << g;
|
||||
// archive and stream closed when destructors are called
|
||||
}
|
||||
|
||||
// ... some time later restore the class instance to its orginal state
|
||||
// create and open an archive for input
|
||||
std::ifstream ifs("filename", std::ios::binary);
|
||||
boost::archive::text_iarchive ia(ifs);
|
||||
// read class state from archive
|
||||
gps_position newg;
|
||||
ia >> newg;
|
||||
// close archive
|
||||
ifs.close();
|
||||
{
|
||||
// create and open an archive for input
|
||||
std::ifstream ifs("filename", std::ios::binary);
|
||||
boost::archive::text_iarchive ia(ifs);
|
||||
// read class state from archive
|
||||
ia >> newg;
|
||||
// archive and stream closed when destructors are called
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
</code>
|
||||
@@ -295,7 +299,7 @@ public:
|
||||
</code>
|
||||
</pre>
|
||||
Each member of the array <code style="white-space: normal">stops</code> will be serialized.
|
||||
But, remember each member is a pointer - so what can this really
|
||||
But remember each member is a pointer - so what can this really
|
||||
mean? The whole object of this serialization is to permit
|
||||
reconstruction of the original data structures at another place
|
||||
and time. In order to accomplish this with a pointer, it is
|
||||
@@ -304,6 +308,27 @@ object it points to must be saved. When the member is later
|
||||
loaded, a new object has to be created and a new pointer has
|
||||
to be loaded into the class member.
|
||||
<p>
|
||||
If the same pointer is serialized more than once, only one instance
|
||||
is be added to the archive. When read back, no data is read back in.
|
||||
The only operation that occurs is for the second pointer is set equal to the first
|
||||
<p>
|
||||
Note that, in this example, the array consists of polymorphic pointers.
|
||||
That is, each array element point to one of several possible
|
||||
kinds of bus stops. So when the pointer is saved, some sort of class
|
||||
identifier must be saved. When the pointer is loaded, the class
|
||||
identifier must be read and and instance of the corresponding class
|
||||
must be constructed. Finally the data can be loaded to newly created
|
||||
instance of the correct type.
|
||||
|
||||
As can be seen in
|
||||
<a href="../example/demo.cpp" target="demo_cpp">demo.cpp</a>,
|
||||
serialization of pointers to derived classes through a base
|
||||
clas pointer may require explicit enumeration of the derived
|
||||
classes to be serialized. This is referred to as "registration" or "export"
|
||||
of derived classes. This requirement and the methods of
|
||||
satisfying it are explained in detail
|
||||
<a href="serialization.html#derivedpointers">here</a>
|
||||
<p>
|
||||
All this is accomplished automatically by the serialization
|
||||
library. The above code is all that is necessary to accomplish
|
||||
the saving and loading of objects accessed through pointers.
|
||||
@@ -515,7 +540,7 @@ This is described later in the manual.
|
||||
<dt><a href="../example/demo_xml.cpp" target="demo_xml_cpp">demo_xml.cpp</a>
|
||||
<dd>This is a variation the original demo which supports xml archives in addition
|
||||
to the others. The extra wrapping macros are needed to associate a data
|
||||
item name with the correspoding xml tag. For more information see
|
||||
item name with the corresponding xml tag. For more information see
|
||||
<a target="detail" href="wrappers.html#nvp">Name-Value Pairs</a>.
|
||||
<a href="../example/demo_save.xml" target="demo_save_xml">Here</a>
|
||||
is what an xml archive looks like.
|
||||
|
||||
@@ -16,10 +16,7 @@
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
#include <exception>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace boost {
|
||||
@@ -28,7 +25,8 @@ namespace archive {
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// exceptions thrown by archives
|
||||
//
|
||||
class archive_exception : public virtual std::exception
|
||||
class archive_exception :
|
||||
public virtual std::exception
|
||||
{
|
||||
public:
|
||||
typedef enum {
|
||||
@@ -114,5 +112,4 @@ protected:
|
||||
}// namespace archive
|
||||
}// namespace boost
|
||||
|
||||
#endif //BOOST_NO_EXCEPTIONS
|
||||
#endif //BOOST_ARCHIVE_ARCHIVE_EXCEPTION_HPP
|
||||
|
||||
@@ -16,11 +16,6 @@
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#if defined(BOOST_SERIALIZATION_TYPE_INFO_IMPLEMENTATION_HPP) \
|
||||
|| defined(BOOST_SERIALIZATION_TRAITS_HPP)
|
||||
#error "no serialization headers my precede any archive headers"
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/strong_typedef.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
@@ -132,5 +127,4 @@ BOOST_CLASS_IMPLEMENTATION(boost::archive::tracking_type, primitive_type)
|
||||
#error "export.hpp must not be included before any archive header"
|
||||
#endif
|
||||
|
||||
|
||||
#endif //BOOST_ARCHIVE_BASIC_ARCHIVE_HPP
|
||||
|
||||
@@ -124,6 +124,10 @@ public:
|
||||
os << std::setprecision(std::numeric_limits<double>::digits10 + 2);
|
||||
os << t;
|
||||
}
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
basic_text_oprimitive(OStream & os, bool no_codecvt);
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
~basic_text_oprimitive();
|
||||
public:
|
||||
// unformatted append of one character
|
||||
void put(int c){
|
||||
@@ -131,7 +135,6 @@ public:
|
||||
boost::throw_exception(archive_exception(archive_exception::stream_error));
|
||||
os.put(c);
|
||||
}
|
||||
|
||||
// unformatted append of null terminated string
|
||||
void put(const char * s){
|
||||
if(os.fail())
|
||||
@@ -139,12 +142,6 @@ public:
|
||||
while('\0' != *s)
|
||||
os.put(*s++);
|
||||
}
|
||||
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
basic_text_oprimitive(OStream & os, bool no_codecvt);
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
~basic_text_oprimitive();
|
||||
public:
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
|
||||
save_binary(const void *address, std::size_t count);
|
||||
};
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
namespace std{
|
||||
#if defined(__LIBCOMO__)
|
||||
using ::mbstate_t;
|
||||
#elif defined(_QNXNTO_)
|
||||
using std::mbstate_t;
|
||||
#elif defined(BOOST_DINKUMWARE_STDLIB)
|
||||
using ::mbstate_t;
|
||||
#elif defined(__SGI_STL_PORT)
|
||||
|
||||
@@ -42,6 +42,8 @@ protected:
|
||||
archive_pointer_iserializer(
|
||||
const boost::serialization::extended_type_info & eti
|
||||
);
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
~archive_pointer_iserializer();
|
||||
public:
|
||||
virtual const basic_iserializer & get_basic_serializer() const
|
||||
// mscvc 6.0 requires template functions to be implemented. For this
|
||||
@@ -75,8 +77,6 @@ public:
|
||||
find(
|
||||
const boost::serialization::extended_type_info & eti
|
||||
);
|
||||
|
||||
virtual ~archive_pointer_iserializer(){}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -39,6 +39,8 @@ protected:
|
||||
archive_pointer_oserializer(
|
||||
const boost::serialization::extended_type_info & eti
|
||||
);
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
~archive_pointer_oserializer();
|
||||
public:
|
||||
// return the type_extended save pointer corresponding to a give
|
||||
// type_info. returns NULL, if there is no such instance. This
|
||||
@@ -49,7 +51,6 @@ public:
|
||||
find(
|
||||
const boost::serialization::extended_type_info & eti
|
||||
);
|
||||
virtual ~archive_pointer_oserializer(){}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -56,7 +56,7 @@ class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive
|
||||
virtual void vload(tracking_type &t) = 0;
|
||||
protected:
|
||||
basic_iarchive(unsigned int flags);
|
||||
virtual ~basic_iarchive();
|
||||
~basic_iarchive();
|
||||
public:
|
||||
// note: NOT part of the public API.
|
||||
void next_object_pointer(void *t);
|
||||
|
||||
@@ -45,7 +45,7 @@ protected:
|
||||
explicit basic_iserializer(
|
||||
const boost::serialization::extended_type_info & type_
|
||||
);
|
||||
virtual ~basic_iserializer();
|
||||
~basic_iserializer();
|
||||
public:
|
||||
bool serialized_as_pointer() const {
|
||||
return bpis != NULL;
|
||||
@@ -56,15 +56,6 @@ public:
|
||||
const basic_pointer_iserializer * get_bpis_ptr() const {
|
||||
return bpis;
|
||||
}
|
||||
#if 0
|
||||
virtual void load_object_data(
|
||||
basic_iarchive & ar,
|
||||
void *x,
|
||||
const unsigned int file_version
|
||||
) const {
|
||||
assert(false);
|
||||
};
|
||||
#endif
|
||||
virtual void load_object_data(
|
||||
basic_iarchive & ar,
|
||||
void *x,
|
||||
|
||||
@@ -63,7 +63,7 @@ class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive
|
||||
virtual void vsave(const tracking_type t) = 0;
|
||||
protected:
|
||||
basic_oarchive(unsigned int flags);
|
||||
virtual ~basic_oarchive();
|
||||
~basic_oarchive();
|
||||
public:
|
||||
// note: NOT part of the public interface
|
||||
void register_basic_serializer(const basic_oserializer & bos);
|
||||
|
||||
@@ -44,7 +44,7 @@ protected:
|
||||
explicit basic_oserializer(
|
||||
const boost::serialization::extended_type_info & type_
|
||||
);
|
||||
virtual ~basic_oserializer();
|
||||
~basic_oserializer();
|
||||
public:
|
||||
bool serialized_as_pointer() const {
|
||||
return bpos != NULL;
|
||||
|
||||
@@ -41,7 +41,7 @@ protected:
|
||||
explicit basic_pointer_iserializer(
|
||||
const boost::serialization::extended_type_info & type_
|
||||
);
|
||||
virtual ~basic_pointer_iserializer();
|
||||
~basic_pointer_iserializer();
|
||||
public:
|
||||
virtual const basic_iserializer & get_basic_serializer() const = 0;
|
||||
virtual void load_object_ptr(
|
||||
|
||||
@@ -40,7 +40,7 @@ protected:
|
||||
explicit basic_pointer_oserializer(
|
||||
const boost::serialization::extended_type_info & type_
|
||||
);
|
||||
virtual ~basic_pointer_oserializer();
|
||||
~basic_pointer_oserializer();
|
||||
public:
|
||||
virtual const basic_oserializer & get_basic_serializer() const = 0;
|
||||
virtual void save_object_ptr(
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/serialization/extended_type_info.hpp>
|
||||
namespace boost {
|
||||
|
||||
namespace boost {
|
||||
namespace archive {
|
||||
namespace detail {
|
||||
|
||||
@@ -38,7 +40,7 @@ public:
|
||||
return m_eti;
|
||||
}
|
||||
bool operator<(const basic_serializer & rhs) const {
|
||||
return m_eti < rhs.get_eti();
|
||||
return & m_eti < & rhs.get_eti();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -33,22 +33,26 @@ namespace detail {
|
||||
|
||||
class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_serializer;
|
||||
|
||||
struct type_info_pointer_compare
|
||||
struct BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) type_info_pointer_compare
|
||||
{
|
||||
bool operator()(
|
||||
const basic_serializer * lhs, const basic_serializer * rhs
|
||||
) const ;
|
||||
};
|
||||
|
||||
struct BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_serializer_map
|
||||
class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_serializer_map
|
||||
{
|
||||
typedef std::set<const basic_serializer *, type_info_pointer_compare> map_type;
|
||||
map_type map;
|
||||
map_type m_map;
|
||||
bool & m_deleted;
|
||||
public:
|
||||
bool insert(const basic_serializer * bs);
|
||||
const basic_serializer * tfind(
|
||||
const boost::serialization::extended_type_info & type_
|
||||
) const;
|
||||
basic_serializer_map();
|
||||
void erase(basic_serializer * bs);
|
||||
basic_serializer_map(bool & deleted);
|
||||
~basic_serializer_map();
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <string>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
#include <boost/archive/detail/auto_link_archive.hpp>
|
||||
#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
|
||||
|
||||
@@ -41,14 +40,8 @@ protected:
|
||||
public:
|
||||
/////////////////////////////////////////////////////////
|
||||
// archive public interface
|
||||
struct is_loading {
|
||||
typedef mpl::bool_<true> type;
|
||||
BOOST_STATIC_CONSTANT(bool, value=true);
|
||||
};
|
||||
struct is_saving {
|
||||
typedef mpl::bool_<false> type;
|
||||
BOOST_STATIC_CONSTANT(bool, value=false);
|
||||
};
|
||||
typedef mpl::bool_<true> is_loading;
|
||||
typedef mpl::bool_<false> is_saving;
|
||||
|
||||
// return a pointer to the most derived class
|
||||
Archive * This(){
|
||||
@@ -56,7 +49,7 @@ public:
|
||||
}
|
||||
|
||||
template<class T>
|
||||
const basic_pointer_iserializer * register_type(T * t = NULL){
|
||||
const basic_pointer_iserializer * register_type(T * = NULL){
|
||||
const basic_pointer_iserializer & bpis =
|
||||
archive::detail::instantiate_pointer_iserializer(
|
||||
static_cast<Archive *>(NULL),
|
||||
@@ -65,19 +58,18 @@ public:
|
||||
this->This()->register_basic_serializer(bpis.get_basic_serializer());
|
||||
return & bpis;
|
||||
}
|
||||
|
||||
void lookup_helper(
|
||||
const boost::serialization::extended_type_info * const eti,
|
||||
shared_ptr<void> & sph
|
||||
boost::shared_ptr<void> & sph
|
||||
){
|
||||
this->This()->basic_iarchive::lookup_basic_helper(eti, sph);
|
||||
this->This()->lookup_basic_helper(eti, sph);
|
||||
}
|
||||
|
||||
void insert_helper(
|
||||
const boost::serialization::extended_type_info * const eti,
|
||||
shared_ptr<void> & sph
|
||||
){
|
||||
this->This()->basic_iarchive::insert_basic_helper(eti, sph);
|
||||
this->This()->insert_basic_helper(eti, sph);
|
||||
}
|
||||
template<class T>
|
||||
Archive & operator>>(T & t){
|
||||
|
||||
@@ -41,15 +41,8 @@ protected:
|
||||
public:
|
||||
/////////////////////////////////////////////////////////
|
||||
// archive public interface
|
||||
|
||||
struct is_loading {
|
||||
typedef mpl::bool_<false> type;
|
||||
BOOST_STATIC_CONSTANT(bool, value=false);
|
||||
};
|
||||
struct is_saving {
|
||||
typedef mpl::bool_<true> type;
|
||||
BOOST_STATIC_CONSTANT(bool, value=true);
|
||||
};
|
||||
typedef mpl::bool_<false> is_loading;
|
||||
typedef mpl::bool_<true> is_saving;
|
||||
|
||||
// return a pointer to the most derived class
|
||||
Archive * This(){
|
||||
@@ -57,7 +50,7 @@ public:
|
||||
}
|
||||
|
||||
template<class T>
|
||||
const basic_pointer_oserializer * register_type(const T * t = NULL){
|
||||
const basic_pointer_oserializer * register_type(const T * = NULL){
|
||||
const basic_pointer_oserializer & bpos =
|
||||
instantiate_pointer_oserializer(
|
||||
static_cast<Archive *>(NULL),
|
||||
@@ -69,16 +62,16 @@ public:
|
||||
|
||||
void lookup_helper(
|
||||
const boost::serialization::extended_type_info * const eti,
|
||||
shared_ptr<void> & sph
|
||||
boost::shared_ptr<void> & sph
|
||||
){
|
||||
this->This()->basic_oarchive::lookup_basic_helper(eti, sph);
|
||||
this->This()->lookup_basic_helper(eti, sph);
|
||||
}
|
||||
|
||||
void insert_helper(
|
||||
const boost::serialization::extended_type_info * const eti,
|
||||
shared_ptr<void> & sph
|
||||
){
|
||||
this->This()->basic_oarchive::insert_basic_helper(eti, sph);
|
||||
this->This()->insert_basic_helper(eti, sph);
|
||||
}
|
||||
template<class T>
|
||||
Archive & operator<<(T & t){
|
||||
|
||||
@@ -76,6 +76,7 @@ namespace std{
|
||||
#include <boost/serialization/type_info_implementation.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
#include <boost/serialization/binary_object.hpp>
|
||||
#include <boost/serialization/void_cast.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
@@ -122,8 +123,8 @@ public:
|
||||
>= boost::serialization::object_class_info;
|
||||
}
|
||||
virtual bool tracking(const unsigned int flags) const {
|
||||
if(0 != (flags & no_tracking))
|
||||
return false;
|
||||
// if(0 != (flags & no_tracking))
|
||||
// return false;
|
||||
return boost::serialization::tracking_level<T>::value
|
||||
== boost::serialization::track_always
|
||||
|| boost::serialization::tracking_level<T>::value
|
||||
@@ -354,11 +355,11 @@ struct load_non_pointer_type {
|
||||
// and serialization level to the archive
|
||||
struct load_standard {
|
||||
static void invoke(Archive &ar, T &t){
|
||||
//BOOST_STATIC_ASSERT(! boost::is_const<T>::value);
|
||||
// borland - for some reason T is const here - even though
|
||||
// its not called that way - so fix it her
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::remove_const<T>::type typex;
|
||||
void * x = & const_cast<typex &>(t);
|
||||
//BOOST_STATIC_ASSERT(! boost::is_const<T>::value);
|
||||
// borland - for some reason T is const here - even though
|
||||
// its not called that way - so fix it her
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::remove_const<T>::type typex;
|
||||
void * x = & const_cast<typex &>(t);
|
||||
ar.load_object(x, iserializer<Archive, T>::instantiate());
|
||||
}
|
||||
};
|
||||
@@ -445,7 +446,7 @@ struct load_pointer_type {
|
||||
// virtual serialize functions used for plug-ins
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
mpl::eval_if<
|
||||
is_abstract<T>,
|
||||
serialization::is_abstract<T>,
|
||||
mpl::identity<abstract<T> >,
|
||||
mpl::identity<non_abstract<T> >
|
||||
>::type typex;
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
#include <boost/serialization/tracking.hpp>
|
||||
#include <boost/serialization/type_info_implementation.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
#include <boost/serialization/void_cast.hpp>
|
||||
|
||||
#include <boost/archive/archive_exception.hpp>
|
||||
|
||||
@@ -115,8 +116,8 @@ public:
|
||||
>= boost::serialization::object_class_info;
|
||||
}
|
||||
virtual bool tracking(const unsigned int flags) const {
|
||||
if(0 != (flags & no_tracking))
|
||||
return false;
|
||||
// if(0 != (flags & no_tracking))
|
||||
// return false;
|
||||
return boost::serialization::tracking_level<T>::value == boost::serialization::track_always
|
||||
|| boost::serialization::tracking_level<T>::value == boost::serialization::track_selectivly
|
||||
&& serialized_as_pointer();
|
||||
@@ -328,10 +329,10 @@ struct save_pointer_type {
|
||||
struct abstract
|
||||
{
|
||||
static const basic_pointer_oserializer * register_type(Archive & /* ar */){
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::serialization::type_info_implementation<T>::type::is_polymorphic typex;
|
||||
// it has? to be polymorphic
|
||||
BOOST_STATIC_ASSERT(typex::value);
|
||||
BOOST_STATIC_ASSERT(
|
||||
boost::serialization::type_info_implementation<T>::type::is_polymorphic::value
|
||||
);
|
||||
return static_cast<const basic_pointer_oserializer *>(NULL);
|
||||
}
|
||||
};
|
||||
@@ -352,7 +353,7 @@ struct save_pointer_type {
|
||||
// virtual serialize functions used for plug-ins
|
||||
typedef
|
||||
BOOST_DEDUCED_TYPENAME mpl::eval_if<
|
||||
is_abstract<T>,
|
||||
serialization::is_abstract<T>,
|
||||
mpl::identity<abstract<T> >,
|
||||
mpl::identity<non_abstract<T> >
|
||||
>::type typex;
|
||||
|
||||
@@ -33,6 +33,11 @@ namespace std{
|
||||
#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
|
||||
|
||||
namespace boost {
|
||||
template<class T>
|
||||
class shared_ptr;
|
||||
namespace serialization {
|
||||
class extended_type_info;
|
||||
} // namespace serialization
|
||||
namespace archive {
|
||||
namespace detail{
|
||||
|
||||
@@ -64,8 +69,8 @@ private:
|
||||
){
|
||||
return ArchiveImplementation::load_pointer(t, bpis_ptr, finder);
|
||||
}
|
||||
virtual void delete_created_pointers(){
|
||||
ArchiveImplementation::delete_created_pointers();
|
||||
virtual void set_library_version(unsigned int archive_library_version){
|
||||
ArchiveImplementation::set_library_version(archive_library_version);
|
||||
}
|
||||
virtual unsigned int get_library_version() const{
|
||||
return ArchiveImplementation::get_library_version();
|
||||
@@ -73,6 +78,9 @@ private:
|
||||
virtual unsigned int get_flags() const {
|
||||
return ArchiveImplementation::get_flags();
|
||||
}
|
||||
virtual void delete_created_pointers(){
|
||||
ArchiveImplementation::delete_created_pointers();
|
||||
}
|
||||
virtual void load_binary(void * t, std::size_t size){
|
||||
ArchiveImplementation::load_binary(t, size);
|
||||
}
|
||||
@@ -147,6 +155,18 @@ private:
|
||||
virtual void register_basic_serializer(const basic_iserializer & bis){
|
||||
ArchiveImplementation::register_basic_serializer(bis);
|
||||
}
|
||||
virtual void lookup_basic_helper(
|
||||
const boost::serialization::extended_type_info * const eti,
|
||||
boost::shared_ptr<void> & sph
|
||||
){
|
||||
ArchiveImplementation::lookup_basic_helper(eti, sph);
|
||||
}
|
||||
virtual void insert_basic_helper(
|
||||
const boost::serialization::extended_type_info * const eti,
|
||||
boost::shared_ptr<void> & sph
|
||||
){
|
||||
ArchiveImplementation::insert_basic_helper(eti, sph);
|
||||
}
|
||||
public:
|
||||
// the >> operator
|
||||
template<class T>
|
||||
|
||||
@@ -33,6 +33,11 @@ namespace std{
|
||||
#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
|
||||
|
||||
namespace boost {
|
||||
template<class T>
|
||||
class shared_ptr;
|
||||
namespace serialization {
|
||||
class extended_type_info;
|
||||
} // namespace serialization
|
||||
namespace archive {
|
||||
namespace detail{
|
||||
|
||||
@@ -146,6 +151,18 @@ private:
|
||||
virtual void register_basic_serializer(const detail::basic_oserializer & bos){
|
||||
ArchiveImplementation::register_basic_serializer(bos);
|
||||
}
|
||||
virtual void lookup_basic_helper(
|
||||
const boost::serialization::extended_type_info * const eti,
|
||||
shared_ptr<void> & sph
|
||||
){
|
||||
ArchiveImplementation::lookup_basic_helper(eti, sph);
|
||||
}
|
||||
virtual void insert_basic_helper(
|
||||
const boost::serialization::extended_type_info * const eti,
|
||||
shared_ptr<void> & sph
|
||||
){
|
||||
ArchiveImplementation::insert_basic_helper(eti, sph);
|
||||
}
|
||||
public:
|
||||
// the << operator
|
||||
template<class T>
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <boost/config.hpp> // msvc 6.0 needs this for warning suppression
|
||||
|
||||
#include <boost/archive/detail/basic_serializer_map.hpp>
|
||||
@@ -18,9 +20,11 @@ namespace archive {
|
||||
namespace detail {
|
||||
|
||||
template<class Archive>
|
||||
basic_serializer_map & iserializer_map(){
|
||||
static basic_serializer_map map;
|
||||
return map;
|
||||
basic_serializer_map *
|
||||
iserializer_map(){
|
||||
static bool deleted = false;
|
||||
static basic_serializer_map map(deleted);
|
||||
return deleted ? NULL : & map;
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
@@ -30,7 +34,9 @@ archive_pointer_iserializer<Archive>::archive_pointer_iserializer(
|
||||
) :
|
||||
basic_pointer_iserializer(eti)
|
||||
{
|
||||
iserializer_map<Archive>().insert(this);
|
||||
basic_serializer_map *mp = iserializer_map<Archive>();
|
||||
assert(NULL != mp);
|
||||
mp->insert(this);
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
@@ -38,9 +44,20 @@ BOOST_ARCHIVE_OR_WARCHIVE_DECL(const basic_pointer_iserializer *)
|
||||
archive_pointer_iserializer<Archive>::find(
|
||||
const boost::serialization::extended_type_info & eti
|
||||
){
|
||||
return static_cast<const basic_pointer_iserializer *>(
|
||||
iserializer_map<Archive>().tfind(eti)
|
||||
);
|
||||
basic_serializer_map *mp = iserializer_map<Archive>();
|
||||
assert(NULL != mp);
|
||||
return static_cast<const basic_pointer_iserializer *>(mp->tfind(eti));
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
archive_pointer_iserializer<Archive>::~archive_pointer_iserializer(){
|
||||
// note: we need to check that the map still exists as we can't depend
|
||||
// on static variables being constructed in a specific sequence
|
||||
basic_serializer_map *mp = iserializer_map<Archive>();
|
||||
if(NULL == mp)
|
||||
return;
|
||||
mp->erase(this);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -18,10 +18,11 @@ namespace archive {
|
||||
namespace detail {
|
||||
|
||||
template<class Archive>
|
||||
basic_serializer_map &
|
||||
basic_serializer_map *
|
||||
oserializer_map(){
|
||||
static basic_serializer_map map;
|
||||
return map;
|
||||
static bool deleted = false;
|
||||
static basic_serializer_map map(deleted);
|
||||
return deleted ? NULL : & map;
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
@@ -29,9 +30,11 @@ BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
archive_pointer_oserializer<Archive>::archive_pointer_oserializer(
|
||||
const boost::serialization::extended_type_info & eti
|
||||
) :
|
||||
basic_pointer_oserializer(eti)
|
||||
basic_pointer_oserializer(eti)
|
||||
{
|
||||
oserializer_map<Archive>().insert(this);
|
||||
basic_serializer_map *mp = oserializer_map<Archive>();
|
||||
assert(NULL != mp);
|
||||
mp->insert(this);
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
@@ -39,9 +42,20 @@ BOOST_ARCHIVE_OR_WARCHIVE_DECL(const basic_pointer_oserializer *)
|
||||
archive_pointer_oserializer<Archive>::find(
|
||||
const boost::serialization::extended_type_info & eti
|
||||
){
|
||||
return static_cast<const basic_pointer_oserializer *>(
|
||||
oserializer_map<Archive>().tfind(eti)
|
||||
);
|
||||
basic_serializer_map *mp = oserializer_map<Archive>();
|
||||
assert(NULL != mp);
|
||||
return static_cast<const basic_pointer_oserializer *>(mp->tfind(eti));
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
archive_pointer_oserializer<Archive>::~archive_pointer_oserializer(){
|
||||
// note: we need to check that the map still exists as we can't depend
|
||||
// on static variables being constructed in a specific sequence
|
||||
basic_serializer_map *mp = oserializer_map<Archive>();
|
||||
if(NULL == mp)
|
||||
return;
|
||||
mp->erase(this);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace std{
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#include <boost/archive/basic_binary_iarchive.hpp>
|
||||
#include <boost/serialization/extended_type_info.hpp>
|
||||
//#include <boost/serialization/extended_type_info.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace archive {
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace std{
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#include <boost/archive/basic_text_iarchive.hpp>
|
||||
#include <boost/serialization/extended_type_info.hpp>
|
||||
//#include <boost/serialization/extended_type_info.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace archive {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#include <boost/archive/basic_xml_iarchive.hpp>
|
||||
#include <boost/serialization/tracking.hpp>
|
||||
#include <boost/serialization/extended_type_info.hpp>
|
||||
//#include <boost/serialization/extended_type_info.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace archive {
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#if defined(BOOST_NO_STDC_NAMESPACE) && ! defined(__LIBCOMO__)
|
||||
namespace std{
|
||||
using ::strlen;
|
||||
namespace std{
|
||||
using ::strlen;
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
@@ -26,12 +26,11 @@ namespace archive {
|
||||
namespace detail {
|
||||
template<class CharType>
|
||||
struct XML_name {
|
||||
typedef bool result_type;
|
||||
void operator()(CharType t) const{
|
||||
unsigned char lookup_table[] = {
|
||||
const unsigned char lookup_table[] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0, // -.
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0, // -.
|
||||
1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, // 0-9
|
||||
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // A-
|
||||
1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1, // -Z _
|
||||
@@ -59,7 +58,7 @@ struct XML_name {
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
|
||||
basic_xml_oarchive<Archive>::write_attribute(
|
||||
const char *attribute_name,
|
||||
const char *attribute_name,
|
||||
int t,
|
||||
const char *conjunction
|
||||
){
|
||||
@@ -69,11 +68,11 @@ basic_xml_oarchive<Archive>::write_attribute(
|
||||
this->This()->save(t);
|
||||
this->This()->put('"');
|
||||
}
|
||||
|
||||
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
|
||||
basic_xml_oarchive<Archive>::write_attribute(
|
||||
const char *attribute_name,
|
||||
const char *attribute_name,
|
||||
const char *key
|
||||
){
|
||||
this->This()->put(' ');
|
||||
@@ -82,7 +81,7 @@ basic_xml_oarchive<Archive>::write_attribute(
|
||||
this->This()->put(key);
|
||||
this->This()->put('"');
|
||||
}
|
||||
|
||||
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
|
||||
basic_xml_oarchive<Archive>::indent(){
|
||||
@@ -97,7 +96,7 @@ basic_xml_oarchive<Archive>::save_start(const char *name)
|
||||
{
|
||||
if(NULL == name)
|
||||
return;
|
||||
|
||||
|
||||
// be sure name has no invalid characters
|
||||
std::for_each(name, name + std::strlen(name), detail::XML_name<const char>());
|
||||
|
||||
@@ -119,7 +118,7 @@ basic_xml_oarchive<Archive>::save_end(const char *name)
|
||||
{
|
||||
if(NULL == name)
|
||||
return;
|
||||
|
||||
|
||||
// be sure name has no invalid characters
|
||||
std::for_each(name, name + std::strlen(name), detail::XML_name<const char>());
|
||||
|
||||
@@ -151,7 +150,7 @@ BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
|
||||
basic_xml_oarchive<Archive>::save_override(const object_id_type & t, int)
|
||||
{
|
||||
int i = t.t; // extra .t is for borland
|
||||
write_attribute(OBJECT_ID(), i, "=\"_");
|
||||
write_attribute(OBJECT_ID(), i, "=\"_");
|
||||
}
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
|
||||
@@ -160,20 +159,20 @@ basic_xml_oarchive<Archive>::save_override(
|
||||
int
|
||||
){
|
||||
int i = t.t; // extra .t is for borland
|
||||
write_attribute(OBJECT_REFERENCE(), i, "=\"_");
|
||||
write_attribute(OBJECT_REFERENCE(), i, "=\"_");
|
||||
}
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
|
||||
basic_xml_oarchive<Archive>::save_override(const version_type & t, int)
|
||||
{
|
||||
int i = t.t; // extra .t is for borland
|
||||
write_attribute(VERSION(), i);
|
||||
write_attribute(VERSION(), i);
|
||||
}
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
|
||||
basic_xml_oarchive<Archive>::save_override(const class_id_type & t, int)
|
||||
{
|
||||
write_attribute(CLASS_ID(), t);
|
||||
write_attribute(CLASS_ID(), t);
|
||||
}
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
|
||||
@@ -181,7 +180,7 @@ basic_xml_oarchive<Archive>::save_override(
|
||||
const class_id_reference_type & t,
|
||||
int
|
||||
){
|
||||
write_attribute(CLASS_ID_REFERENCE(), t);
|
||||
write_attribute(CLASS_ID_REFERENCE(), t);
|
||||
}
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
|
||||
@@ -189,7 +188,7 @@ basic_xml_oarchive<Archive>::save_override(
|
||||
const class_id_optional_type & t,
|
||||
int
|
||||
){
|
||||
write_attribute(CLASS_ID(), t);
|
||||
write_attribute(CLASS_ID(), t);
|
||||
}
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
|
||||
@@ -198,13 +197,13 @@ basic_xml_oarchive<Archive>::save_override(const class_name_type & t, int)
|
||||
const char * key = t;
|
||||
if(NULL == key)
|
||||
return;
|
||||
write_attribute(CLASS_NAME(), key);
|
||||
write_attribute(CLASS_NAME(), key);
|
||||
}
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
|
||||
basic_xml_oarchive<Archive>::save_override(const tracking_type & t, int)
|
||||
{
|
||||
write_attribute(TRACKING(), t.t); // extra .t is for borland
|
||||
write_attribute(TRACKING(), t.t); // extra .t is for borland
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
@@ -215,12 +214,12 @@ basic_xml_oarchive<Archive>::init(){
|
||||
this->This()->put("<!DOCTYPE boost_serialization>\n");
|
||||
// xml document wrapper - outer root
|
||||
this->This()->put("<boost_serialization");
|
||||
write_attribute("signature", ARCHIVE_SIGNATURE());
|
||||
write_attribute("version", ARCHIVE_VERSION());
|
||||
write_attribute("signature", ARCHIVE_SIGNATURE());
|
||||
write_attribute("version", ARCHIVE_VERSION());
|
||||
this->This()->put(">\n");
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
basic_xml_oarchive<Archive>::basic_xml_oarchive(unsigned int flags) :
|
||||
detail::common_oarchive<Archive>(flags),
|
||||
@@ -230,16 +229,16 @@ basic_xml_oarchive<Archive>::basic_xml_oarchive(unsigned int flags) :
|
||||
{
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
basic_xml_oarchive<Archive>::~basic_xml_oarchive(){
|
||||
if(0 == (this->get_flags() & no_header)){
|
||||
BOOST_TRY{
|
||||
this->This()->put("</boost_serialization>\n");
|
||||
}
|
||||
BOOST_CATCH(...){}
|
||||
BOOST_CATCH_END
|
||||
this->This()->put("</boost_serialization>\n");
|
||||
}
|
||||
BOOST_CATCH(...){}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace archive
|
||||
|
||||
@@ -91,6 +91,18 @@ text_iarchive_impl<Archive>::load(std::wstring &ws)
|
||||
#endif // BOOST_NO_STD_WSTRING
|
||||
#endif // BOOST_NO_CWCHAR
|
||||
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_DECL(void)
|
||||
text_iarchive_impl<Archive>::load_override(class_name_type & t, int){
|
||||
basic_text_iarchive<Archive>::load_override(t, 0);
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_DECL(void)
|
||||
text_iarchive_impl<Archive>::init(){
|
||||
basic_text_iarchive<Archive>::init();
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
text_iarchive_impl<Archive>::text_iarchive_impl(
|
||||
|
||||
@@ -168,20 +168,30 @@ xml_iarchive_impl<Archive>::xml_iarchive_impl(
|
||||
basic_xml_iarchive<Archive>(flags),
|
||||
gimpl(new xml_grammar())
|
||||
{
|
||||
if(0 == (flags & no_header))
|
||||
init();
|
||||
if(0 == (flags & no_header)){
|
||||
BOOST_TRY{
|
||||
init();
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
delete gimpl;
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
throw; // re-throw
|
||||
#endif
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
xml_iarchive_impl<Archive>::~xml_iarchive_impl(){
|
||||
if(0 == (this->get_flags() & no_header)){
|
||||
BOOST_TRY{
|
||||
gimpl->windup(is);
|
||||
}
|
||||
BOOST_CATCH(...){}
|
||||
BOOST_CATCH_END
|
||||
BOOST_TRY{
|
||||
gimpl->windup(is);
|
||||
}
|
||||
BOOST_CATCH(...){}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
delete gimpl;
|
||||
}
|
||||
} // namespace archive
|
||||
|
||||
@@ -168,20 +168,30 @@ xml_wiarchive_impl<Archive>::xml_wiarchive_impl(
|
||||
);
|
||||
is.imbue(* archive_locale);
|
||||
}
|
||||
if(0 == (flags & no_header))
|
||||
this->init();
|
||||
if(0 == (flags & no_header)){
|
||||
BOOST_TRY{
|
||||
this->init();
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
delete gimpl;
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
throw; // re-throw
|
||||
#endif
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
xml_wiarchive_impl<Archive>::~xml_wiarchive_impl(){
|
||||
if(0 == (this->get_flags() & no_header)){
|
||||
BOOST_TRY{
|
||||
gimpl->windup(is);
|
||||
}
|
||||
BOOST_CATCH(...){}
|
||||
BOOST_CATCH_END
|
||||
BOOST_TRY{
|
||||
gimpl->windup(is);
|
||||
}
|
||||
BOOST_CATCH(...){}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
delete gimpl;
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,11 @@ class mb_from_wchar
|
||||
|
||||
void fill(){
|
||||
wchar_t value = * this->base_reference();
|
||||
#if (defined(__MINGW32__) && ((__MINGW32_MAJOR_VERSION > 3) || ((__MINGW32_MAJOR_VERSION == 3) && (__MINGW32_MINOR_VERSION >= 8))))
|
||||
m_bend = std::wcrtomb(m_buffer, value, 0);
|
||||
#else
|
||||
m_bend = std::wctomb(m_buffer, value);
|
||||
#endif
|
||||
assert(-1 != m_bend);
|
||||
assert((std::size_t)m_bend <= sizeof(m_buffer));
|
||||
assert(m_bend > 0);
|
||||
|
||||
@@ -42,7 +42,12 @@ namespace std{
|
||||
# define BOOST_NO_INTRINSIC_INT64_T
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace boost {
|
||||
template<class T>
|
||||
class shared_ptr;
|
||||
namespace serialization {
|
||||
class extended_type_info;
|
||||
} // namespace serialization
|
||||
namespace archive {
|
||||
namespace detail {
|
||||
class basic_iarchive;
|
||||
@@ -93,8 +98,14 @@ public:
|
||||
virtual void load_start(const char * name) = 0;
|
||||
virtual void load_end(const char * name) = 0;
|
||||
virtual void register_basic_serializer(const detail::basic_iserializer & bis) = 0;
|
||||
|
||||
virtual void delete_created_pointers() = 0;
|
||||
virtual void lookup_basic_helper(
|
||||
const boost::serialization::extended_type_info * const eti,
|
||||
boost::shared_ptr<void> & sph
|
||||
) = 0;
|
||||
virtual void insert_basic_helper(
|
||||
const boost::serialization::extended_type_info * const eti,
|
||||
boost::shared_ptr<void> & sph
|
||||
) = 0;
|
||||
|
||||
// msvc and borland won't automatically pass these to the base class so
|
||||
// make it explicit here
|
||||
@@ -118,8 +129,10 @@ public:
|
||||
}
|
||||
public:
|
||||
// utility function implemented by all legal archives
|
||||
virtual void set_library_version(unsigned int archive_library_version) = 0;
|
||||
virtual unsigned int get_library_version() const = 0;
|
||||
virtual unsigned int get_flags() const = 0;
|
||||
virtual void delete_created_pointers() = 0;
|
||||
|
||||
virtual void load_binary(void * t, std::size_t size) = 0;
|
||||
|
||||
|
||||
@@ -42,6 +42,11 @@ namespace std{
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
template<class T>
|
||||
class shared_ptr;
|
||||
namespace serialization {
|
||||
class extended_type_info;
|
||||
} // namespace serialization
|
||||
namespace archive {
|
||||
namespace detail {
|
||||
class basic_oarchive;
|
||||
@@ -92,6 +97,14 @@ public:
|
||||
virtual void save_start(const char * name) = 0;
|
||||
virtual void save_end(const char * name) = 0;
|
||||
virtual void register_basic_serializer(const detail::basic_oserializer & bos) = 0;
|
||||
virtual void lookup_basic_helper(
|
||||
const boost::serialization::extended_type_info * const eti,
|
||||
boost::shared_ptr<void> & sph
|
||||
) = 0;
|
||||
virtual void insert_basic_helper(
|
||||
const boost::serialization::extended_type_info * const eti,
|
||||
shared_ptr<void> & sph
|
||||
) = 0;
|
||||
|
||||
virtual unsigned int get_library_version() const = 0;
|
||||
virtual void end_preamble() = 0;
|
||||
|
||||
@@ -63,6 +63,10 @@ protected:
|
||||
void load_override(T & t, BOOST_PFTO int){
|
||||
basic_text_iarchive<Archive>::load_override(t, 0);
|
||||
}
|
||||
BOOST_ARCHIVE_DECL(void)
|
||||
load_override(class_name_type & t, int);
|
||||
BOOST_ARCHIVE_DECL(void)
|
||||
init();
|
||||
BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
text_iarchive_impl(std::istream & is, unsigned int flags);
|
||||
BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
|
||||
@@ -65,7 +65,6 @@ protected:
|
||||
BOOST_ARCHIVE_DECL(void)
|
||||
save(const std::wstring &ws);
|
||||
#endif
|
||||
protected:
|
||||
BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
text_oarchive_impl(std::ostream & os, unsigned int flags);
|
||||
BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
|
||||
@@ -31,28 +31,8 @@
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/serialization/type_info_implementation.hpp>
|
||||
|
||||
// if no archive headers have been included
|
||||
// skip inclusion of void_cast.hpp . This is to avoid auto-link when
|
||||
// a module doesn't doesn't actually invoke serializaton but rather
|
||||
// just declares it.
|
||||
|
||||
#if ! defined(BOOST_ARCHIVE_BASIC_ARCHIVE_HPP)
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
namespace void_cast_detail{
|
||||
class void_caster;
|
||||
} // namespace void_cast_detail
|
||||
template<class Derived, class Base>
|
||||
const void_cast_detail::void_caster & void_cast_register(
|
||||
const Derived * /* dnull = NULL */,
|
||||
const Base * /* bnull = NULL */
|
||||
);
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
#else
|
||||
#include <boost/serialization/void_cast.hpp>
|
||||
#endif
|
||||
#include <boost/serialization/force_include.hpp>
|
||||
#include <boost/serialization/void_cast_fwd.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
@@ -126,7 +106,7 @@ namespace detail {
|
||||
static_cast<const Base *>(NULL)
|
||||
);
|
||||
}
|
||||
} m_reg;
|
||||
};
|
||||
static void invoke(){
|
||||
typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
|
||||
BOOST_DEDUCED_TYPENAME type_info_implementation<Base>::type::is_polymorphic,
|
||||
|
||||
@@ -25,13 +25,13 @@
|
||||
#include <cassert>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/archive/basic_archive.hpp>
|
||||
|
||||
#include <boost/aligned_storage.hpp>
|
||||
|
||||
#include <boost/serialization/access.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
#include <boost/serialization/serialization.hpp>
|
||||
#include <boost/serialization/detail/stack_constructor.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace serialization {
|
||||
@@ -41,50 +41,13 @@ namespace stl {
|
||||
// implementation of serialization for STL containers
|
||||
//
|
||||
|
||||
// reserve space on stack for an object of type T without actually
|
||||
// construction such an object
|
||||
template<typename T >
|
||||
struct stack_allocate
|
||||
{
|
||||
T * address() {
|
||||
return static_cast<T*>(storage_.address());
|
||||
}
|
||||
T & reference() {
|
||||
return * address();
|
||||
}
|
||||
private:
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::aligned_storage<
|
||||
sizeof(T),
|
||||
#if BOOST_WORKAROUND(__BORLANDC__,BOOST_TESTED_AT(0x560))
|
||||
8
|
||||
#else
|
||||
boost::alignment_of<T>::value
|
||||
#endif
|
||||
> type;
|
||||
type storage_;
|
||||
};
|
||||
|
||||
// construct element on the stack
|
||||
template<class Archive, class T>
|
||||
struct stack_construct : public stack_allocate<T>
|
||||
{
|
||||
stack_construct(Archive & ar){
|
||||
// note borland emits a no-op without the explicit namespace
|
||||
boost::serialization::load_construct_data_adl(ar, this->address(), 0U);
|
||||
}
|
||||
~stack_construct(){
|
||||
this->address()->~T(); // undo load_construct_data above
|
||||
}
|
||||
};
|
||||
|
||||
// sequential container input
|
||||
template<class Archive, class Container>
|
||||
struct archive_input_seq
|
||||
{
|
||||
inline void operator()(Archive &ar, Container &s)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Container::value_type type;
|
||||
stack_construct<Archive, type> t(ar);
|
||||
detail::stack_construct<Archive, BOOST_DEDUCED_TYPENAME Container::value_type> t(ar);
|
||||
// borland fails silently w/o full namespace
|
||||
ar >> boost::serialization::make_nvp("item", t.reference());
|
||||
s.push_back(t.reference());
|
||||
@@ -98,24 +61,13 @@ struct archive_input_map
|
||||
{
|
||||
inline void operator()(Archive &ar, Container &s)
|
||||
{
|
||||
#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
|
||||
typedef BOOST_DEDUCED_TYPENAME std::pair<
|
||||
BOOST_DEDUCED_TYPENAME Container::key_type,
|
||||
BOOST_DEDUCED_TYPENAME Container::referent_type
|
||||
> type;
|
||||
#else
|
||||
typedef BOOST_DEDUCED_TYPENAME std::pair<
|
||||
BOOST_DEDUCED_TYPENAME Container::key_type,
|
||||
BOOST_DEDUCED_TYPENAME Container::mapped_type
|
||||
> type;
|
||||
#endif
|
||||
stack_construct<Archive, type> t(ar);
|
||||
detail::stack_construct<Archive, BOOST_DEDUCED_TYPENAME Container::value_type> t(ar);
|
||||
// borland fails silently w/o full namespace
|
||||
ar >> boost::serialization::make_nvp("item", t.reference());
|
||||
std::pair<BOOST_DEDUCED_TYPENAME Container::const_iterator, bool> result =
|
||||
s.insert(t.reference());
|
||||
assert(result.second); // make sure we inserted a new element
|
||||
ar.reset_object_address(& (* result.first), & t);
|
||||
ar.reset_object_address(& (* result.first), & t.reference());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -126,13 +78,13 @@ struct archive_input_set
|
||||
inline void operator()(Archive &ar, Container &s)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Container::value_type type;
|
||||
stack_construct<Archive, type> t(ar);
|
||||
detail::stack_construct<Archive, type> t(ar);
|
||||
// borland fails silently w/o full namespace
|
||||
ar >> boost::serialization::make_nvp("item", t.reference());
|
||||
std::pair<BOOST_DEDUCED_TYPENAME Container::const_iterator, bool> result =
|
||||
s.insert(t.reference());
|
||||
assert(result.second); // make sure we inserted a new element
|
||||
ar.reset_object_address(& (* result.first), & t);
|
||||
ar.reset_object_address(& (* result.first), & t.reference());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -142,23 +94,12 @@ struct archive_input_multimap
|
||||
{
|
||||
inline void operator()(Archive &ar, Container &s)
|
||||
{
|
||||
#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
|
||||
typedef BOOST_DEDUCED_TYPENAME std::pair<
|
||||
BOOST_DEDUCED_TYPENAME Container::key_type,
|
||||
BOOST_DEDUCED_TYPENAME Container::referent_type
|
||||
> type;
|
||||
#else
|
||||
typedef BOOST_DEDUCED_TYPENAME std::pair<
|
||||
BOOST_DEDUCED_TYPENAME Container::key_type,
|
||||
BOOST_DEDUCED_TYPENAME Container::mapped_type
|
||||
> type;
|
||||
#endif
|
||||
stack_construct<Archive, type> t(ar);
|
||||
detail::stack_construct<Archive, BOOST_DEDUCED_TYPENAME Container::value_type> t(ar);
|
||||
// borland fails silently w/o full namespace
|
||||
ar >> boost::serialization::make_nvp("item", t.reference());
|
||||
BOOST_DEDUCED_TYPENAME Container::const_iterator result
|
||||
= s.insert(t.reference());
|
||||
ar.reset_object_address(& (* result), & t);
|
||||
ar.reset_object_address(& (* result), & t.reference());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -169,12 +110,12 @@ struct archive_input_multiset
|
||||
inline void operator()(Archive &ar, Container &s)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Container::value_type type;
|
||||
stack_construct<Archive, type> t(ar);
|
||||
detail::stack_construct<Archive, type> t(ar);
|
||||
// borland fails silently w/o full namespace
|
||||
ar >> boost::serialization::make_nvp("item", t.reference());
|
||||
BOOST_DEDUCED_TYPENAME Container::const_iterator result
|
||||
= s.insert(t.reference());
|
||||
ar.reset_object_address(& (* result), & t);
|
||||
ar.reset_object_address(& (* result), & t.reference());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
|
||||
// helper function templates for serialization of collections
|
||||
|
||||
#include <boost/archive/basic_archive.hpp>
|
||||
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
#include <boost/serialization/serialization.hpp>
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#ifndef BOOST_SERIALIZATION_DETAIL_STACH_CONSTRUCTOR_HPP
|
||||
#define BOOST_SERIALIZATION_DETAIL_STACH_CONSTRUCTOR_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER <= 1020)
|
||||
# pragma warning (disable : 4786) // too long name, harmless warning
|
||||
#endif
|
||||
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// collections_load_imp.hpp: serialization for loading stl collections
|
||||
|
||||
// (C) Copyright 2002 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.
|
||||
|
||||
#include <boost/aligned_storage.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace serialization {
|
||||
namespace detail {
|
||||
|
||||
// reserve space on stack for an object of type T without actually
|
||||
// construction such an object
|
||||
template<typename T >
|
||||
struct stack_allocate
|
||||
{
|
||||
T * address() {
|
||||
return static_cast<T*>(storage_.address());
|
||||
}
|
||||
T & reference() {
|
||||
return * address();
|
||||
}
|
||||
private:
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::aligned_storage<
|
||||
sizeof(T),
|
||||
#if BOOST_WORKAROUND(__BORLANDC__,BOOST_TESTED_AT(0x560))
|
||||
8
|
||||
#else
|
||||
boost::alignment_of<T>::value
|
||||
#endif
|
||||
> type;
|
||||
type storage_;
|
||||
};
|
||||
|
||||
// construct element on the stack
|
||||
template<class Archive, class T>
|
||||
struct stack_construct : public stack_allocate<T>
|
||||
{
|
||||
stack_construct(Archive & ar){
|
||||
// note borland emits a no-op without the explicit namespace
|
||||
boost::serialization::load_construct_data_adl(ar, this->address(), 0U);
|
||||
}
|
||||
~stack_construct(){
|
||||
this->address()->~T(); // undo load_construct_data above
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // serializaition
|
||||
} // boost
|
||||
|
||||
#endif // BOOST_SERIALIZATION_DETAIL_STACH_CONSTRUCTOR_HPP
|
||||
@@ -9,7 +9,7 @@
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// export.hpp: set traits of classes to be serialized
|
||||
|
||||
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
// (C) Copyright 2002 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)
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// if no archive headers have been included this is a no op
|
||||
// this is to permit BOOST_EXPORT etc to be included in a
|
||||
// this is to permit BOOST_EXPORT etc to be included in a
|
||||
// file declaration header
|
||||
#if ! defined(BOOST_ARCHIVE_BASIC_ARCHIVE_HPP)
|
||||
#define BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST(T, K, ASEQ)
|
||||
@@ -44,7 +44,7 @@
|
||||
#include <boost/archive/detail/known_archive_types.hpp>
|
||||
#include <boost/serialization/force_include.hpp>
|
||||
#include <boost/serialization/type_info_implementation.hpp>
|
||||
#include <boost/serialization/extended_type_info.hpp>
|
||||
#include <boost/serialization/is_abstract.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
@@ -62,7 +62,6 @@ template<class Archive, class T>
|
||||
BOOST_DLLEXPORT const basic_pointer_oserializer &
|
||||
instantiate_pointer_oserializer(Archive * ar, T *) BOOST_USED;
|
||||
|
||||
|
||||
namespace export_impl
|
||||
{
|
||||
struct nothing{
|
||||
@@ -136,7 +135,7 @@ struct export_generator {
|
||||
};
|
||||
|
||||
template<class T, class ASeq>
|
||||
const export_generator<T, ASeq>
|
||||
const export_generator<T, ASeq>
|
||||
export_generator<T, ASeq>::instance;
|
||||
|
||||
// instantiation of this template creates a static object.
|
||||
@@ -147,12 +146,12 @@ struct guid_initializer {
|
||||
eti_type::export_register(key);
|
||||
}
|
||||
static const guid_initializer instance;
|
||||
guid_initializer(const char *key = NULL) BOOST_USED ;
|
||||
guid_initializer(const char *key = 0) BOOST_USED ;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
guid_initializer<T>::guid_initializer(const char *key){
|
||||
if(NULL != key)
|
||||
if(0 != key)
|
||||
export_register(key);
|
||||
}
|
||||
|
||||
@@ -167,56 +166,63 @@ const guid_initializer<T> guid_initializer<T>::instance;
|
||||
template<class T, class ASeq>
|
||||
struct export_instance {
|
||||
struct abstract {
|
||||
static const void *
|
||||
static const export_generator<T, ASeq> *
|
||||
invoke(){
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
struct not_abstract {
|
||||
static const void *
|
||||
static const export_generator<T, ASeq> *
|
||||
invoke(){
|
||||
return & export_generator<T, ASeq>::instance;
|
||||
}
|
||||
};
|
||||
static BOOST_DLLEXPORT std::pair<const void *, const void *>
|
||||
#if ! (defined(BOOST_MSVC) && (_MSC_VER <= 1300))
|
||||
invoke() BOOST_USED;
|
||||
#else
|
||||
invoke() {
|
||||
typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
|
||||
is_abstract<T>,
|
||||
mpl::identity<abstract>,
|
||||
mpl::identity<not_abstract>
|
||||
>::type typex;
|
||||
return std::pair<const void *, const void *>(
|
||||
typex::invoke(),
|
||||
& guid_initializer<T>::instance
|
||||
);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#if ! (defined(BOOST_MSVC) && (_MSC_VER <= 1300))
|
||||
template<class T, class ASeq>
|
||||
BOOST_DLLEXPORT
|
||||
std::pair<const void *, const void *>
|
||||
export_instance<T, ASeq>::invoke() {
|
||||
typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
|
||||
is_abstract<T>,
|
||||
mpl::identity<abstract>,
|
||||
mpl::identity<not_abstract>
|
||||
>::type type;
|
||||
return std::pair<const void *, const void *>(
|
||||
type::invoke(),
|
||||
& guid_initializer<T>::instance
|
||||
);
|
||||
}
|
||||
#endif
|
||||
template<class T, class ASeq>
|
||||
BOOST_DLLEXPORT
|
||||
std::pair<const export_generator<T, ASeq> *, const guid_initializer<T> *>
|
||||
export_instance_invoke() {
|
||||
typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
|
||||
serialization::is_abstract<T>,
|
||||
mpl::identity<BOOST_DEDUCED_TYPENAME export_instance<T, ASeq>::abstract>,
|
||||
mpl::identity<BOOST_DEDUCED_TYPENAME export_instance<T, ASeq>::not_abstract>
|
||||
>::type typex;
|
||||
return std::pair<const export_generator<T, ASeq> *, const guid_initializer<T> *>(
|
||||
typex::invoke(),
|
||||
& guid_initializer<T>::instance
|
||||
);
|
||||
}
|
||||
|
||||
template<class T, class ASeq>
|
||||
std::pair<const void *, const void *>
|
||||
export_instantiate(T &, ASeq &){
|
||||
return export_instance<T, ASeq>::invoke();
|
||||
struct export_archives {
|
||||
struct empty_archive_list {
|
||||
static BOOST_DLLEXPORT
|
||||
std::pair<const export_generator<T, ASeq> *, const guid_initializer<T> *>
|
||||
invoke(){
|
||||
return std::pair<const export_generator<T, ASeq> *,
|
||||
const guid_initializer<T> *>(0, 0);
|
||||
}
|
||||
};
|
||||
struct non_empty_archive_list {
|
||||
static BOOST_DLLEXPORT
|
||||
std::pair<const export_generator<T, ASeq> *, const guid_initializer<T> *>
|
||||
invoke(){
|
||||
return export_instance_invoke<T, ASeq>();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<class T, class ASeq>
|
||||
BOOST_DLLEXPORT
|
||||
std::pair<const export_generator<T, ASeq> *, const guid_initializer<T> *>
|
||||
export_archives_invoke(T &, ASeq &){
|
||||
typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
|
||||
mpl::empty<ASeq>,
|
||||
mpl::identity<BOOST_DEDUCED_TYPENAME export_archives<T, ASeq>::empty_archive_list>,
|
||||
mpl::identity<BOOST_DEDUCED_TYPENAME export_archives<T, ASeq>::non_empty_archive_list>
|
||||
>::type typex;
|
||||
return typex::invoke();
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
@@ -231,14 +237,15 @@ export_instantiate(T &, ASeq &){
|
||||
const guid_initializer< T > \
|
||||
guid_initializer< T >::instance(K); \
|
||||
template \
|
||||
BOOST_DLLEXPORT std::pair<const void *, const void *> \
|
||||
export_instantiate(T &, ASEQ &); \
|
||||
BOOST_DLLEXPORT \
|
||||
std::pair<const export_generator<T, ASEQ> *, const guid_initializer<T> *> \
|
||||
export_archives_invoke<T, ASEQ>(T &, ASEQ &); \
|
||||
} } } \
|
||||
/**/
|
||||
|
||||
#endif
|
||||
|
||||
// check for unnecessary export. T isn't polymorphic so there is no
|
||||
// check for unnecessary export. T isn't polymorphic so there is no
|
||||
// need to export it.
|
||||
#define BOOST_CLASS_EXPORT_CHECK(T) \
|
||||
BOOST_STATIC_WARNING( \
|
||||
@@ -257,7 +264,7 @@ export_instantiate(T &, ASeq &){
|
||||
/**/
|
||||
|
||||
// the default exportable class identifier is the class name
|
||||
#define BOOST_CLASS_EXPORT_ARCHIVE_LIST(T, ASEQ) \
|
||||
#define BOOST_CLASS_EXPORT_ARCHIVE_LIST(T, ASEQ) \
|
||||
BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST(T, BOOST_PP_STRINGIZE(T), A)
|
||||
|
||||
// the default exportable class identifier is the class name
|
||||
|
||||
@@ -38,18 +38,31 @@ class BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) extended_type_info :
|
||||
private:
|
||||
virtual bool
|
||||
less_than(const extended_type_info &rhs) const = 0;
|
||||
int type_info_key_cmp(const extended_type_info & rhs) const;
|
||||
|
||||
// used to uniquely identify the type of class derived from this one
|
||||
// so that different derivations of this class can be simultaneously
|
||||
// included in implementation of sets and maps.
|
||||
const char * type_info_key;
|
||||
int type_info_key_cmp(const extended_type_info & rhs) const;
|
||||
const char * m_type_info_key;
|
||||
// flag to indicate wheter its been registered by type;
|
||||
bool m_self_registered;
|
||||
// flag to indicate wheter its been registered by type;
|
||||
bool m_key_registered;
|
||||
// flag indicating that no virtual function should be called here
|
||||
// this is necessary since it seems that at least one compiler (borland
|
||||
// and one version of gcc call less_than above when erasing even
|
||||
// when given an iterator argument.
|
||||
bool m_is_destructing;
|
||||
protected:
|
||||
const char * key;
|
||||
extended_type_info(const char * type_info_key_);
|
||||
virtual ~extended_type_info() = 0;
|
||||
const char * m_key;
|
||||
extended_type_info(const char * type_info_key);
|
||||
~extended_type_info();
|
||||
public:
|
||||
void self_register();
|
||||
void key_register(const char *key);
|
||||
bool is_destructing() const {
|
||||
return m_is_destructing;
|
||||
}
|
||||
bool operator<(const extended_type_info &rhs) const;
|
||||
bool operator==(const extended_type_info &rhs) const {
|
||||
return this == & rhs;
|
||||
@@ -58,7 +71,7 @@ public:
|
||||
return this != & rhs;
|
||||
}
|
||||
const char * get_key() const {
|
||||
return key;
|
||||
return m_key;
|
||||
}
|
||||
static const extended_type_info * find(const char *key);
|
||||
static const extended_type_info * find(const extended_type_info * t);
|
||||
|
||||
@@ -42,9 +42,9 @@ namespace detail {
|
||||
class BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) extended_type_info_no_rtti_0 :
|
||||
public extended_type_info
|
||||
{
|
||||
protected:
|
||||
virtual bool
|
||||
less_than(const boost::serialization::extended_type_info &rhs) const ;
|
||||
protected:
|
||||
extended_type_info_no_rtti_0();
|
||||
~extended_type_info_no_rtti_0();
|
||||
public:
|
||||
@@ -59,11 +59,11 @@ template<class T>
|
||||
class extended_type_info_no_rtti_1 :
|
||||
public extended_type_info_no_rtti_0
|
||||
{
|
||||
private:
|
||||
// private constructor to inhibit any existence other than the
|
||||
// static one
|
||||
protected:
|
||||
extended_type_info_no_rtti_1(){}
|
||||
public:
|
||||
// note borland complains at making this destructor protected
|
||||
~extended_type_info_no_rtti_1(){};
|
||||
static const boost::serialization::extended_type_info *
|
||||
get_derived_extended_type_info(const T & t){
|
||||
// find the type that corresponds to the most derived type.
|
||||
@@ -93,7 +93,12 @@ public:
|
||||
template<class T>
|
||||
class extended_type_info_no_rtti :
|
||||
public detail::extended_type_info_no_rtti_1<const T>
|
||||
{};
|
||||
{
|
||||
// private constructor to inhibit any existence other than the
|
||||
// static one
|
||||
extended_type_info_no_rtti(){}
|
||||
~extended_type_info_no_rtti(){};
|
||||
};
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
@@ -18,31 +18,35 @@
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/type_traits/is_abstract.hpp>
|
||||
|
||||
#ifndef BOOST_NO_IS_ABSTRACT
|
||||
#include <boost/type_traits/is_abstract.hpp>
|
||||
#else
|
||||
// default to false if not supported
|
||||
// supplant boost/type_traits/is_abstract.hpp
|
||||
# define BOOST_TT_IS_ABSTRACT_CLASS_HPP
|
||||
namespace boost {
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
template<class T>
|
||||
struct is_abstract {
|
||||
typedef mpl::bool_<false> type;
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
// default to false if not supported
|
||||
#ifdef BOOST_NO_IS_ABSTRACT
|
||||
typedef BOOST_DEDUCED_TYPENAME mpl::bool_<false> type;
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
#else
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::is_abstract<T>::type type;
|
||||
BOOST_STATIC_CONSTANT(bool, value = type::value);
|
||||
#endif
|
||||
};
|
||||
} // namespace boost
|
||||
#endif
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
// define a macro to make explicit designation of this more transparent
|
||||
#define BOOST_IS_ABSTRACT(T) \
|
||||
namespace boost { \
|
||||
namespace serialization { \
|
||||
template<> \
|
||||
struct is_abstract< T > { \
|
||||
typedef mpl::bool_<true> type; \
|
||||
BOOST_STATIC_CONSTANT(bool, value = true); \
|
||||
}; \
|
||||
} // namespace boost
|
||||
} \
|
||||
} \
|
||||
/**/
|
||||
|
||||
#endif //BOOST_SERIALIZATION_IS_ABSTRACT_CLASS_HPP
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <boost/mpl/integral_c.hpp>
|
||||
#include <boost/mpl/integral_c_tag.hpp>
|
||||
|
||||
#include <boost/serialization/traits.hpp>
|
||||
//#include <boost/serialization/traits.hpp>
|
||||
#include <boost/serialization/level.hpp>
|
||||
#include <boost/serialization/tracking.hpp>
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
|
||||
@@ -16,88 +16,86 @@
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/mpl/integral_c.hpp>
|
||||
#include <boost/mpl/integral_c_tag.hpp>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/serialization/split_free.hpp>
|
||||
#include <boost/serialization/level.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/serialization/detail/stack_constructor.hpp>
|
||||
|
||||
// function specializations must be defined in the appropriate
|
||||
// namespace - boost::serialization
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
template<class Archive, class T>
|
||||
void save(
|
||||
Archive & ar,
|
||||
const boost::optional<T> & t,
|
||||
const unsigned int /*version*/
|
||||
){
|
||||
const bool tflag = t;
|
||||
ar << boost::serialization::make_nvp("initialized", tflag);
|
||||
if (tflag)
|
||||
ar << boost::serialization::make_nvp("value", *t);
|
||||
namespace serialization {
|
||||
|
||||
template<class Archive, class T>
|
||||
void save(
|
||||
Archive & ar,
|
||||
const boost::optional<T> & t,
|
||||
const unsigned int /*version*/
|
||||
){
|
||||
const bool tflag = t;
|
||||
ar << boost::serialization::make_nvp("initialized", tflag);
|
||||
if (tflag)
|
||||
ar << boost::serialization::make_nvp("value", *t);
|
||||
}
|
||||
|
||||
template<class Archive, class T>
|
||||
void load(
|
||||
Archive & ar,
|
||||
boost::optional<T> & t,
|
||||
const unsigned int /*version*/
|
||||
){
|
||||
bool tflag;
|
||||
ar >> boost::serialization::make_nvp("initialized", tflag);
|
||||
if (tflag){
|
||||
detail::stack_construct<Archive, T> aux(ar);
|
||||
ar >> boost::serialization::make_nvp("value", aux.reference());
|
||||
t.reset(aux.reference());
|
||||
}
|
||||
|
||||
template<class Archive, class T>
|
||||
void load(
|
||||
Archive & ar,
|
||||
boost::optional<T> & t,
|
||||
const unsigned int /*version*/
|
||||
){
|
||||
bool tflag;
|
||||
ar >> boost::serialization::make_nvp("initialized", tflag);
|
||||
if (tflag){
|
||||
T aux;
|
||||
ar >> boost::serialization::make_nvp("value", aux);
|
||||
t.reset(aux);
|
||||
}
|
||||
else {
|
||||
t.reset();
|
||||
}
|
||||
else {
|
||||
t.reset();
|
||||
}
|
||||
}
|
||||
|
||||
template<class Archive, class T>
|
||||
void serialize(
|
||||
Archive & ar,
|
||||
boost::optional<T> & t,
|
||||
const unsigned int version
|
||||
){
|
||||
boost::serialization::split_free(ar, t, version);
|
||||
}
|
||||
template<class Archive, class T>
|
||||
void serialize(
|
||||
Archive & ar,
|
||||
boost::optional<T> & t,
|
||||
const unsigned int version
|
||||
){
|
||||
boost::serialization::split_free(ar, t, version);
|
||||
}
|
||||
|
||||
// the following would be slightly more efficient. But it
|
||||
// would mean that archives created with programs that support
|
||||
// TPS wouldn't be readable by programs that don't support TPS.
|
||||
// Hence we decline to support this otherwise convenient optimization.
|
||||
//#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#if 0
|
||||
// the following would be slightly more efficient. But it
|
||||
// would mean that archives created with programs that support
|
||||
// TPS wouldn't be readable by programs that don't support TPS.
|
||||
// Hence we decline to support this otherwise convenient optimization.
|
||||
//#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#if 0
|
||||
|
||||
template <class T>
|
||||
struct implementation_level<optional<T> >
|
||||
{
|
||||
typedef mpl::integral_c_tag tag;
|
||||
typedef mpl::int_<boost::serialization::object_serializable> type;
|
||||
BOOST_STATIC_CONSTANT(
|
||||
int ,
|
||||
value = boost::serialization::implementation_level::type::value
|
||||
);
|
||||
};
|
||||
template <class T>
|
||||
struct implementation_level<optional<T> >
|
||||
{
|
||||
typedef mpl::integral_c_tag tag;
|
||||
typedef mpl::int_<boost::serialization::object_serializable> type;
|
||||
BOOST_STATIC_CONSTANT(
|
||||
int ,
|
||||
value = boost::serialization::implementation_level::type::value
|
||||
);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct tracking_level<optional<T> >
|
||||
{
|
||||
typedef mpl::integral_c_tag tag;
|
||||
typedef mpl::int_<boost::serialization::track_never> type;
|
||||
BOOST_STATIC_CONSTANT(
|
||||
int ,
|
||||
value = boost::serialization::tracking_level::type::value
|
||||
);
|
||||
};
|
||||
template<class T>
|
||||
struct tracking_level<optional<T> >
|
||||
{
|
||||
typedef mpl::integral_c_tag tag;
|
||||
typedef mpl::int_<boost::serialization::track_never> type;
|
||||
BOOST_STATIC_CONSTANT(
|
||||
int ,
|
||||
value = boost::serialization::tracking_level::type::value
|
||||
);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} // serialization
|
||||
} // namespace boost
|
||||
|
||||
@@ -28,15 +28,18 @@
|
||||
|
||||
#include <boost/archive/archive_exception.hpp>
|
||||
|
||||
// no extended type info system has been selected, use the typeid based one
|
||||
#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
|
||||
#include <boost/serialization/extended_type_info_typeid.hpp>
|
||||
#endif
|
||||
#include <boost/serialization/type_info_implementation.hpp>
|
||||
#include <boost/serialization/split_free.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
#include <boost/serialization/version.hpp>
|
||||
#include <boost/serialization/tracking.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include <boost/serialization/extended_type_info.hpp>
|
||||
#include <boost/serialization/type_info_implementation.hpp>
|
||||
#include <boost/serialization/void_cast.hpp>
|
||||
#include <boost/serialization/void_cast_fwd.hpp>
|
||||
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// shared_ptr serialization traits
|
||||
@@ -47,17 +50,33 @@
|
||||
namespace boost {
|
||||
namespace serialization{
|
||||
template<class T>
|
||||
struct version< ::boost::shared_ptr<T> > { \
|
||||
struct version< ::boost::shared_ptr<T> > {
|
||||
typedef mpl::integral_c_tag tag;
|
||||
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
|
||||
typedef BOOST_DEDUCED_TYPENAME mpl::int_<1> type;
|
||||
#else
|
||||
typedef mpl::int_<1> type;
|
||||
#endif
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570))
|
||||
BOOST_STATIC_CONSTANT(unsigned int, value = 1);
|
||||
#else
|
||||
BOOST_STATIC_CONSTANT(unsigned int, value = type::value);
|
||||
#endif
|
||||
};
|
||||
// don't track shared pointers
|
||||
template<class T>
|
||||
struct tracking_level< ::boost::shared_ptr<T> > {
|
||||
typedef mpl::integral_c_tag tag;
|
||||
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
|
||||
typedef BOOST_DEDUCED_TYPENAME mpl::int_< ::boost::serialization::track_never> type;
|
||||
#else
|
||||
typedef mpl::int_< ::boost::serialization::track_never> type;
|
||||
#endif
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570))
|
||||
BOOST_STATIC_CONSTANT(int, value = ::boost::serialization::track_never);
|
||||
#else
|
||||
BOOST_STATIC_CONSTANT(int, value = type::value);
|
||||
#endif
|
||||
};
|
||||
}}
|
||||
#define BOOST_SERIALIZATION_SHARED_PTR(T)
|
||||
@@ -77,6 +96,9 @@
|
||||
|
||||
namespace boost {
|
||||
namespace serialization{
|
||||
|
||||
class extended_type_info;
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct null_deleter {
|
||||
@@ -141,32 +163,18 @@ public:
|
||||
// utility function for creating/getting a helper - could be useful in general
|
||||
// but shared_ptr is the only class (so far that needs it) and I don't have a
|
||||
// convenient header to place it into.
|
||||
template<class Archive, class T>
|
||||
T &
|
||||
get_helper(Archive & ar){
|
||||
extended_type_info * eti = type_info_implementation<T>::type::get_instance();
|
||||
shared_ptr<void> sph;
|
||||
ar.lookup_helper(eti, sph);
|
||||
if(NULL == sph.get()){
|
||||
sph = shared_ptr<T>(new T);
|
||||
ar.insert_helper(eti, sph);
|
||||
}
|
||||
return * static_cast<T *>(sph.get());
|
||||
}
|
||||
|
||||
#if 0
|
||||
template<class Archive, class H>
|
||||
H &
|
||||
get_helper(Archive & ar){
|
||||
shared_ptr<H> sph;
|
||||
ar.lookup_helper(sph);
|
||||
extended_type_info * eti = type_info_implementation<H>::type::get_instance();
|
||||
shared_ptr<void> sph;
|
||||
ar.lookup_helper(eti, sph);
|
||||
if(NULL == sph.get()){
|
||||
sph = shared_ptr<H>(new H);
|
||||
ar.insert_helper(sph);
|
||||
ar.insert_helper(eti, sph);
|
||||
}
|
||||
return * static_cast<T *>(sph.get());
|
||||
return * static_cast<H *>(sph.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// serialization for shared_ptr
|
||||
@@ -182,7 +190,7 @@ inline void save(
|
||||
// is never tracked by default. Wrap int in a trackable type
|
||||
BOOST_STATIC_ASSERT((tracking_level<T>::value != track_never));
|
||||
const T * t_ptr = t.get();
|
||||
ar << boost::serialization::make_nvp("px", t_ptr);
|
||||
ar << boost::serialization::make_nvp("px", t_ptr);
|
||||
}
|
||||
|
||||
template<class Archive, class T>
|
||||
@@ -195,7 +203,7 @@ inline void load(
|
||||
// something like shared_ptr<int>. This occurs because int
|
||||
// is never tracked by default. Wrap int in a trackable type
|
||||
BOOST_STATIC_ASSERT((tracking_level<T>::value != track_never));
|
||||
T* r;
|
||||
T* r;
|
||||
#ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP
|
||||
if(file_version < 1){
|
||||
ar.register_type(static_cast<
|
||||
@@ -211,7 +219,7 @@ inline void load(
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ar >> boost::serialization::make_nvp("px", r);
|
||||
ar >> boost::serialization::make_nvp("px", r);
|
||||
}
|
||||
get_helper<Archive, detail::shared_ptr_helper >(ar).reset(t,r);
|
||||
}
|
||||
|
||||
@@ -60,16 +60,16 @@ inline void load(
|
||||
if(0 == count)
|
||||
return;
|
||||
|
||||
boost::serialization::stl::stack_construct<Archive, U> u(ar);
|
||||
boost::serialization::detail::stack_construct<Archive, U> u(ar);
|
||||
ar >> boost::serialization::make_nvp("item", u.reference());
|
||||
t.push_front(u.reference());
|
||||
BOOST_DEDUCED_TYPENAME BOOST_STD_EXTENSION_NAMESPACE::slist<U, Allocator>::iterator last;
|
||||
last = t.begin();
|
||||
while(--count > 0){
|
||||
boost::serialization::stl::stack_construct<Archive, U> u(ar);
|
||||
boost::serialization::detail::stack_construct<Archive, U> u(ar);
|
||||
ar >> boost::serialization::make_nvp("item", u.reference());
|
||||
last = t.insert_after(last, u.reference());
|
||||
ar.reset_object_address(& (*last), & u);
|
||||
ar.reset_object_address(& (*last), & u.reference());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <boost/mpl/integral_c_tag.hpp>
|
||||
|
||||
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/serialization/traits.hpp>
|
||||
#include <boost/serialization/level.hpp>
|
||||
#include <boost/serialization/tracking_enum.hpp>
|
||||
|
||||
@@ -20,10 +20,6 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// If no other implementation has been designated as default,
|
||||
// use extended_type_info_typeid.hpp
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
template<class T>
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <utility>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
|
||||
// function specializations must be defined in the appropriate
|
||||
@@ -40,7 +41,11 @@ inline void serialize(
|
||||
STD::pair<F, S> & p,
|
||||
const unsigned int /* file_version */
|
||||
){
|
||||
ar & boost::serialization::make_nvp("first", p.first);
|
||||
// note: we remove any const-ness on the first argument. The reason is that
|
||||
// for stl maps, the type saved is pair<const key, T). We remove
|
||||
// the const-ness in order to be able to load it.
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::remove_const<F>::type typef;
|
||||
ar & boost::serialization::make_nvp("first", const_cast<typef &>(p.first));
|
||||
ar & boost::serialization::make_nvp("second", p.second);
|
||||
}
|
||||
|
||||
|
||||
@@ -98,10 +98,11 @@ struct variant_impl {
|
||||
// necessary has to copy the value. This wouldn't be necessary
|
||||
// with an implementation that de-serialized to the address of the
|
||||
// aligned storage included in the variant.
|
||||
BOOST_DEDUCED_TYPENAME mpl::front<S>::type value;
|
||||
typedef BOOST_DEDUCED_TYPENAME mpl::front<S>::type head_type;
|
||||
head_type value;
|
||||
ar >> BOOST_SERIALIZATION_NVP(value);
|
||||
v = value;
|
||||
ar.reset_object_address(& v, & value);
|
||||
ar.reset_object_address(& boost::get<head_type>(v), & value);
|
||||
return;
|
||||
}
|
||||
typedef BOOST_DEDUCED_TYPENAME mpl::pop_front<S>::type type;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef BOOST_SERIALIZATION_VOID_CAST_FWD_HPP
|
||||
#define BOOST_SERIALIZATION_VOID_CAST_FWD_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// void_cast_fwd.hpp: interface for run-time casting of void pointers.
|
||||
|
||||
// (C) Copyright 2005 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)
|
||||
// gennadiy.rozental@tfn.com
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
namespace void_cast_detail{
|
||||
class void_caster;
|
||||
} // namespace void_cast_detail
|
||||
template<class Derived, class Base>
|
||||
BOOST_DLLEXPORT
|
||||
inline const void_cast_detail::void_caster & void_cast_register(
|
||||
const Derived * /* dnull = NULL */,
|
||||
const Base * /* bnull = NULL */
|
||||
) BOOST_USED;
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_SERIALIZATION_VOID_CAST_HPP
|
||||
+72
-51
@@ -80,8 +80,9 @@ class basic_iarchive_impl :
|
||||
// list of objects which might be moved. We use a vector for implemenation
|
||||
// in the hope the the truncation operation will be faster than either
|
||||
// with a list or stack adaptor
|
||||
std::vector<std::size_t> moveable_object_stack;
|
||||
std::size_t moveable_object_position;
|
||||
object_id_type moveable_objects_start;
|
||||
object_id_type moveable_objects_end;
|
||||
object_id_type moveable_objects_recent;
|
||||
|
||||
void reset_object_address(
|
||||
const void * new_address,
|
||||
@@ -95,7 +96,7 @@ class basic_iarchive_impl :
|
||||
const basic_iserializer * bis;
|
||||
const class_id_type class_id;
|
||||
cobject_type(
|
||||
std::size_t class_id_,
|
||||
class_id_type class_id_,
|
||||
const basic_iserializer & bis_
|
||||
) :
|
||||
bis(& bis_),
|
||||
@@ -196,7 +197,8 @@ class basic_iarchive_impl :
|
||||
basic_iarchive_impl(unsigned int flags) :
|
||||
m_archive_library_version(ARCHIVE_VERSION()),
|
||||
m_flags(flags),
|
||||
moveable_object_position(0),
|
||||
moveable_objects_start(0),
|
||||
moveable_objects_end(0),
|
||||
pending_object(NULL),
|
||||
pending_bis(NULL),
|
||||
pending_version(0)
|
||||
@@ -254,24 +256,44 @@ basic_iarchive_impl::reset_object_address(
|
||||
const void * new_address,
|
||||
const void *old_address
|
||||
){
|
||||
// if the this object wasn't tracked
|
||||
std::size_t i = moveable_object_position;
|
||||
if(i >= moveable_object_stack.size())
|
||||
return;
|
||||
if(old_address != object_id_vector[i].address)
|
||||
// skip to any lower level ones
|
||||
++i;
|
||||
while(i < moveable_object_stack.size()){
|
||||
object_id_type i;
|
||||
// this code handles a couple of situations.
|
||||
// a) where reset_object_address is applied to an untracked object.
|
||||
// In such a case the call is really superfluous and its really an
|
||||
// an error. But we don't have access to the types here so we can't
|
||||
// know that. However, this code will effectively turn this situation
|
||||
// into a no-op and every thing will work fine - albeat with a small
|
||||
// execution time penalty.
|
||||
// b) where the call to reset_object_address doesn't immediatly follow
|
||||
// the << operator to which it corresponds. This would be a bad idea
|
||||
// but the code may work anyway. Naturally, a bad practice on the part
|
||||
// of the programmer but we can't detect it - as above. So maybe we
|
||||
// can save a few more people from themselves as above.
|
||||
for(i = moveable_objects_recent; i < moveable_objects_end; ++i){
|
||||
if(old_address == object_id_vector[i].address)
|
||||
break;
|
||||
}
|
||||
for(; i < moveable_objects_end; ++i){
|
||||
|
||||
// calculate displacement from this level
|
||||
assert(object_id_vector[i].address >= old_address);
|
||||
// warning - pointer arithmetic on void * is in herently non-portable
|
||||
// but expected to work on all platforms in current usage
|
||||
std::size_t member_displacement
|
||||
= reinterpret_cast<std::size_t>(object_id_vector[i].address)
|
||||
- reinterpret_cast<std::size_t>(old_address);
|
||||
object_id_vector[i].address = reinterpret_cast<void *>(
|
||||
reinterpret_cast<std::size_t>(new_address) + member_displacement
|
||||
);
|
||||
if(object_id_vector[i].address > old_address){
|
||||
std::size_t member_displacement
|
||||
= reinterpret_cast<std::size_t>(object_id_vector[i].address)
|
||||
- reinterpret_cast<std::size_t>(old_address);
|
||||
object_id_vector[i].address = reinterpret_cast<void *>(
|
||||
reinterpret_cast<std::size_t>(new_address) + member_displacement
|
||||
);
|
||||
}
|
||||
else{
|
||||
std::size_t member_displacement
|
||||
= reinterpret_cast<std::size_t>(old_address)
|
||||
- reinterpret_cast<std::size_t>(object_id_vector[i].address);
|
||||
object_id_vector[i].address = reinterpret_cast<void *>(
|
||||
reinterpret_cast<std::size_t>(new_address) - member_displacement
|
||||
);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
@@ -297,7 +319,8 @@ inline class_id_type
|
||||
basic_iarchive_impl::register_type(
|
||||
const basic_iserializer & bis
|
||||
){
|
||||
cobject_type co(cobject_info_set.size(), bis);
|
||||
class_id_type id(static_cast<int>(cobject_info_set.size()));
|
||||
cobject_type co(id, bis);
|
||||
std::pair<cobject_info_set_type::const_iterator, bool>
|
||||
result = cobject_info_set.insert(co);
|
||||
|
||||
@@ -305,10 +328,12 @@ basic_iarchive_impl::register_type(
|
||||
cobject_id_vector.push_back(cobject_id(bis));
|
||||
assert(cobject_info_set.size() == cobject_id_vector.size());
|
||||
}
|
||||
const int id = result.first->class_id;
|
||||
cobject_id & coid = cobject_id_vector[id];
|
||||
id = result.first->class_id;
|
||||
// borland complains without this minor hack
|
||||
const int tid = id;
|
||||
cobject_id & coid = cobject_id_vector[tid];
|
||||
coid.bpis_ptr = bis.get_bpis_ptr();
|
||||
return result.first->class_id;
|
||||
return id;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -370,34 +395,31 @@ basic_iarchive_impl::load_object(
|
||||
cobject_id & co = cobject_id_vector[id];
|
||||
|
||||
load_preamble(ar, co);
|
||||
|
||||
// save the current move stack position in case we want to truncate it
|
||||
boost::state_saver<object_id_type> w(moveable_objects_start);
|
||||
|
||||
// note: extra line used to evade borland issue
|
||||
const bool tracking = co.tracking_level;
|
||||
// if we didn't track this object when the archive was saved
|
||||
if(! tracking){
|
||||
// all we need to do is read the data
|
||||
(bis.load_object_data)(ar, t, co.file_version);
|
||||
return;
|
||||
|
||||
object_id_type this_id;
|
||||
moveable_objects_start =
|
||||
this_id = object_id_vector.size();
|
||||
|
||||
// if we tracked this object when the archive was saved
|
||||
if(tracking){
|
||||
// if it was already read
|
||||
if(!track(ar, t))
|
||||
// we're done
|
||||
return;
|
||||
// add a new enty into the tracking list
|
||||
object_id_vector.push_back(aobject(t, cid));
|
||||
// and add an entry for this object
|
||||
moveable_objects_end = object_id_vector.size();
|
||||
}
|
||||
|
||||
// we're tracking the object
|
||||
// if it was already read
|
||||
if(! track(ar, t))
|
||||
// we're done
|
||||
return;
|
||||
|
||||
std::size_t tracking_list_position = object_id_vector.size();
|
||||
// add a new enty into the tracking list
|
||||
object_id_vector.push_back(aobject(t, cid));
|
||||
// save the current move stack position in case we want to truncate it
|
||||
std::size_t next_moveable_object_position = moveable_object_stack.size();
|
||||
// and add an entry for this object
|
||||
moveable_object_stack.push_back(tracking_list_position);
|
||||
|
||||
// read data
|
||||
(bis.load_object_data)(ar, t, co.file_version);
|
||||
|
||||
// last object created
|
||||
moveable_object_position = next_moveable_object_position;
|
||||
moveable_objects_recent = this_id;
|
||||
}
|
||||
|
||||
inline const basic_pointer_iserializer *
|
||||
@@ -457,8 +479,7 @@ basic_iarchive_impl::load_pointer(
|
||||
return bpis_ptr;
|
||||
|
||||
// save state
|
||||
std::size_t original_moveable_stack_size(moveable_object_stack.size());
|
||||
state_saver<std::size_t> w(moveable_object_position);
|
||||
state_saver<object_id_type> w(moveable_objects_start);
|
||||
|
||||
if(! tracking){
|
||||
bpis_ptr->load_object_ptr(ar, t, co.file_version);
|
||||
@@ -474,11 +495,14 @@ basic_iarchive_impl::load_pointer(
|
||||
// predict next object id to be created
|
||||
const unsigned int ui = object_id_vector.size();
|
||||
|
||||
state_saver<object_id_type> w(moveable_objects_end);
|
||||
|
||||
// because the following operation could move the items
|
||||
// don't use co after this
|
||||
// add to list of serialized objects so that we can properly handle
|
||||
// cyclic strucures
|
||||
object_id_vector.push_back(aobject(t, cid));
|
||||
|
||||
bpis_ptr->load_object_ptr(
|
||||
ar,
|
||||
object_id_vector[ui].address,
|
||||
@@ -490,9 +514,6 @@ basic_iarchive_impl::load_pointer(
|
||||
// and add to list of created pointers
|
||||
created_pointers.push_back(created_pointer_type(cid, t));
|
||||
}
|
||||
// anything pointed to is never moved
|
||||
// so truncate the stack of moveable objects
|
||||
moveable_object_stack.resize(original_moveable_stack_size);
|
||||
|
||||
return bpis_ptr;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace detail {
|
||||
|
||||
BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
basic_iserializer::basic_iserializer(
|
||||
const boost::serialization::extended_type_info & eti
|
||||
const boost::serialization::extended_type_info & eti
|
||||
) :
|
||||
basic_serializer(eti),
|
||||
bpis(NULL)
|
||||
|
||||
@@ -25,19 +25,33 @@ namespace boost {
|
||||
namespace archive {
|
||||
namespace detail {
|
||||
|
||||
bool type_info_pointer_compare::operator()(
|
||||
BOOST_ARCHIVE_DECL(bool)
|
||||
type_info_pointer_compare::operator()(
|
||||
const basic_serializer * lhs, const basic_serializer * rhs
|
||||
) const {
|
||||
) const {
|
||||
return *lhs < *rhs;
|
||||
}
|
||||
|
||||
BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
basic_serializer_map::basic_serializer_map(){
|
||||
basic_serializer_map::basic_serializer_map(bool & deleted) :
|
||||
m_deleted(deleted)
|
||||
{
|
||||
m_deleted = false;
|
||||
}
|
||||
|
||||
BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
basic_serializer_map::~basic_serializer_map(){
|
||||
m_deleted = true;
|
||||
}
|
||||
|
||||
BOOST_ARCHIVE_DECL(bool)
|
||||
basic_serializer_map::insert(const basic_serializer * bs){
|
||||
return map.insert(bs).second;
|
||||
return m_map.insert(bs).second;
|
||||
}
|
||||
|
||||
BOOST_ARCHIVE_DECL(void)
|
||||
basic_serializer_map::erase(basic_serializer * bs){
|
||||
m_map.erase(bs);
|
||||
}
|
||||
|
||||
class basic_serializer_arg : public basic_serializer {
|
||||
@@ -53,8 +67,8 @@ basic_serializer_map::tfind(
|
||||
) const {
|
||||
const basic_serializer_arg bs(eti);
|
||||
map_type::const_iterator it;
|
||||
it = map.find(& bs);
|
||||
if(it == map.end())
|
||||
it = m_map.find(& bs);
|
||||
if(it == m_map.end())
|
||||
return NULL;
|
||||
return *it;
|
||||
}
|
||||
|
||||
+95
-42
@@ -43,13 +43,20 @@ class tkmap {
|
||||
bool
|
||||
operator()(const extended_type_info * lhs, const extended_type_info * rhs) const
|
||||
{
|
||||
assert(! lhs->is_destructing());
|
||||
assert(! rhs->is_destructing());
|
||||
return *lhs < *rhs;
|
||||
}
|
||||
};
|
||||
typedef std::multiset<const extended_type_info *, type_info_compare> type;
|
||||
tkmap(){}
|
||||
// typedef std::multiset<const extended_type_info *, type_info_compare> type;
|
||||
typedef std::set<const extended_type_info *, type_info_compare> type;
|
||||
type m_map;
|
||||
static tkmap * m_self;
|
||||
tkmap(){}
|
||||
static tkmap::type::iterator
|
||||
lookup(const extended_type_info * eti){
|
||||
return m_self->m_map.find(eti);
|
||||
}
|
||||
public:
|
||||
~tkmap(){
|
||||
m_self = NULL;
|
||||
@@ -60,14 +67,16 @@ public:
|
||||
static tkmap instance;
|
||||
m_self = & instance;
|
||||
}
|
||||
// make sure that attempt at registration is done only once
|
||||
assert(lookup(eti) == m_self->m_map.end());
|
||||
m_self->m_map.insert(eti);
|
||||
}
|
||||
static const extended_type_info *
|
||||
find(const extended_type_info * t){
|
||||
find(const extended_type_info * eti){
|
||||
if(NULL == m_self)
|
||||
return NULL;
|
||||
tkmap::type::const_iterator it;
|
||||
it = m_self->m_map.find(t);
|
||||
it = m_self->m_map.find(eti);
|
||||
if(it == m_self->m_map.end())
|
||||
return NULL;
|
||||
return *it;
|
||||
@@ -76,6 +85,19 @@ public:
|
||||
purge(const extended_type_info * eti){
|
||||
if(NULL == m_self)
|
||||
return;
|
||||
// note: the following can't be used as this function
|
||||
// is called from a destructor of extended_type_info.
|
||||
// This will generate an error on some machines - which
|
||||
// makes sense be cause by this time the derived class data
|
||||
// might be gone. Leave this in as a reminder not to do this
|
||||
#if 0
|
||||
tkmap::type::iterator it;
|
||||
it = lookup(eti);
|
||||
// it should be in there
|
||||
assert(it != m_self->m_map.end());
|
||||
m_self->m_map.erase(it);
|
||||
#endif
|
||||
|
||||
tkmap::type::iterator i = m_self->m_map.begin();
|
||||
tkmap::type::iterator k = m_self->m_map.end();
|
||||
while(i != k){
|
||||
@@ -106,10 +128,32 @@ class ktmap {
|
||||
return std::strcmp(lhs->get_key(), rhs->get_key()) < 0;
|
||||
}
|
||||
};
|
||||
typedef std::multiset<const extended_type_info *, key_compare> type;
|
||||
// typedef std::multiset<const extended_type_info *, key_compare> type;
|
||||
typedef std::set<const extended_type_info *, key_compare> type;
|
||||
type m_map;
|
||||
static ktmap * m_self;
|
||||
ktmap(){}
|
||||
class extended_type_info_arg : public extended_type_info
|
||||
{
|
||||
public:
|
||||
extended_type_info_arg(const char * key) :
|
||||
extended_type_info(NULL)
|
||||
{
|
||||
m_key = key;
|
||||
}
|
||||
virtual bool
|
||||
less_than(const extended_type_info &rhs) const
|
||||
{
|
||||
assert(false);
|
||||
return false; // to prevent a syntax error
|
||||
}
|
||||
};
|
||||
static ktmap::type::iterator
|
||||
lookup(const char *key){
|
||||
extended_type_info_arg arg(key);
|
||||
return m_self->m_map.find(&arg);
|
||||
}
|
||||
|
||||
public:
|
||||
~ktmap(){
|
||||
m_self = NULL;
|
||||
@@ -120,36 +164,10 @@ public:
|
||||
static ktmap instance;
|
||||
m_self = & instance;
|
||||
}
|
||||
// make sure that all GUIDs are unique
|
||||
assert(lookup(eti->get_key()) == m_self->m_map.end());
|
||||
m_self->m_map.insert(eti);
|
||||
}
|
||||
static void
|
||||
purge(const extended_type_info * eti){
|
||||
if(NULL == m_self)
|
||||
return;
|
||||
ktmap::type::iterator i = m_self->m_map.begin();
|
||||
ktmap::type::iterator k = m_self->m_map.end();
|
||||
while(i == k){
|
||||
// note that the erase might invalidate i so save it here
|
||||
ktmap::type::iterator j = i++;
|
||||
if(*j == eti)
|
||||
m_self->m_map.erase(j);
|
||||
}
|
||||
}
|
||||
class extended_type_info_arg : public extended_type_info
|
||||
{
|
||||
public:
|
||||
extended_type_info_arg(const char * search_key_)
|
||||
: extended_type_info(NULL)
|
||||
{
|
||||
key = search_key_;
|
||||
}
|
||||
virtual bool
|
||||
less_than(const extended_type_info &rhs) const
|
||||
{
|
||||
assert(false);
|
||||
return false; // to prevent a syntax error
|
||||
}
|
||||
};
|
||||
static const extended_type_info *
|
||||
find(const char *key)
|
||||
{
|
||||
@@ -162,7 +180,32 @@ public:
|
||||
return NULL;
|
||||
return *it;
|
||||
}
|
||||
static void
|
||||
purge(const extended_type_info * eti){
|
||||
if(NULL == m_self)
|
||||
return;
|
||||
// note: the following can't be used as this function
|
||||
// is called from a destructor of extended_type_info.
|
||||
// This will generate an error on some machines - which
|
||||
// makes sense be cause by this time the derived class data
|
||||
// might be gone. Leave this in as a reminder not to do this
|
||||
#if 0
|
||||
ktmap::type::iterator it;
|
||||
it = lookup(eti->get_key());
|
||||
// expect it to be in there !
|
||||
assert(it != m_self->m_map.end());
|
||||
m_self->m_map.erase(it);
|
||||
#endif
|
||||
|
||||
ktmap::type::iterator i = m_self->m_map.begin();
|
||||
ktmap::type::iterator k = m_self->m_map.end();
|
||||
while(i != k){
|
||||
// note that the erase might invalidate i so save it here
|
||||
ktmap::type::iterator j = i++;
|
||||
if(*j == eti)
|
||||
m_self->m_map.erase(j);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ktmap * ktmap::m_self = NULL;
|
||||
@@ -179,43 +222,51 @@ BOOST_SERIALIZATION_DECL(void)
|
||||
extended_type_info::self_register()
|
||||
{
|
||||
detail::tkmap::insert(this);
|
||||
m_self_registered = true;
|
||||
}
|
||||
|
||||
BOOST_SERIALIZATION_DECL(void)
|
||||
extended_type_info::key_register(const char *key_) {
|
||||
if(NULL == key_)
|
||||
return;
|
||||
key = key_;
|
||||
m_key = key_;
|
||||
detail::ktmap::insert(this);
|
||||
m_key_registered = true;
|
||||
}
|
||||
|
||||
BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
|
||||
extended_type_info::extended_type_info(const char * type_info_key_) :
|
||||
type_info_key(type_info_key_),
|
||||
key(NULL)
|
||||
extended_type_info::extended_type_info(
|
||||
const char * type_info_key
|
||||
) :
|
||||
m_type_info_key(type_info_key),
|
||||
m_self_registered(false),
|
||||
m_key_registered(false),
|
||||
m_is_destructing(false)
|
||||
{}
|
||||
|
||||
BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
|
||||
extended_type_info::~extended_type_info(){
|
||||
// remove entries in maps which correspond to this type
|
||||
m_is_destructing = true;
|
||||
BOOST_TRY{
|
||||
detail::tkmap::purge(this);
|
||||
detail::ktmap::purge(this);
|
||||
if(m_self_registered)
|
||||
detail::tkmap::purge(this);
|
||||
if(m_key_registered)
|
||||
detail::ktmap::purge(this);
|
||||
unregister_void_casts(this);
|
||||
}
|
||||
BOOST_CATCH(...){}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
|
||||
BOOST_SERIALIZATION_DECL(int)
|
||||
extended_type_info::type_info_key_cmp(const extended_type_info & rhs) const {
|
||||
if(type_info_key == rhs.type_info_key)
|
||||
if(m_type_info_key == rhs.m_type_info_key)
|
||||
return 0;
|
||||
//return strcmp(lhs.type_info_key, rhs.type_info_key);
|
||||
// all we require is that the type_info_key be unique
|
||||
// so just compare the addresses
|
||||
return type_info_key < rhs.type_info_key ? -1 : 1;
|
||||
return m_type_info_key < rhs.m_type_info_key ? -1 : 1;
|
||||
}
|
||||
|
||||
BOOST_SERIALIZATION_DECL(const extended_type_info *)
|
||||
@@ -231,6 +282,8 @@ extended_type_info::operator<(const extended_type_info &rhs) const {
|
||||
return true;
|
||||
if(i > 0)
|
||||
return false;
|
||||
assert(! is_destructing());
|
||||
assert(! rhs.is_destructing());
|
||||
return less_than(rhs);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ BOOST_SERIALIZATION_DECL(bool)
|
||||
extended_type_info_no_rtti_0::less_than(
|
||||
const boost::serialization::extended_type_info &rhs) const
|
||||
{
|
||||
return std::strcmp(key, rhs.get_key()) < 0;
|
||||
return std::strcmp(m_key, rhs.get_key()) < 0;
|
||||
}
|
||||
|
||||
BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
|
||||
|
||||
@@ -111,6 +111,8 @@ void_caster_registry * void_caster_registry::m_self = NULL;
|
||||
|
||||
void
|
||||
void_caster_registry::purge(const extended_type_info * eti){
|
||||
if(NULL == m_self)
|
||||
return;
|
||||
if(! empty()){
|
||||
iterator i = m_self->m_set.begin();
|
||||
while(i != m_self->m_set.end()){
|
||||
|
||||
+17
-17
@@ -5,7 +5,6 @@
|
||||
# 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/libs/test for the library home page.
|
||||
|
||||
subproject libs/serialization/test ;
|
||||
|
||||
@@ -46,7 +45,8 @@ rule run-template ( test-name : sources * : requirements * ) {
|
||||
: # requirements
|
||||
std::locale-support
|
||||
toolset::require-boost-spirit-support
|
||||
<borland*><*><cxxflags>"-w-8080 -w-8071 -w-8057 -w-8062 -w-8008 -w-0018 -w-8066"
|
||||
toolset::suppress-warnings
|
||||
toolset::optimizations
|
||||
$(requirements)
|
||||
: # test name
|
||||
$(test-name)
|
||||
@@ -69,7 +69,6 @@ rule run-invoke ( test-name : sources * : defns * )
|
||||
# msvc stlport 4.5.3 only works with static lib
|
||||
<msvc-stlport><*><runtime-link>static
|
||||
<vc-6_5-stlport><*><runtime-link>static
|
||||
<como><*><linkflags>"-force:multiple"
|
||||
<define>$(defns)
|
||||
<define>BOOST_LIB_DIAGNOSTIC=1
|
||||
] ;
|
||||
@@ -245,19 +244,6 @@ test-suite "serialization" :
|
||||
[ test-bsl-run_polymorphic_archive test_polymorphic : test_polymorphic_A ]
|
||||
;
|
||||
|
||||
# This last DEPENDS makes the directory for the part 2 depend on the
|
||||
# completion of part 1. You may ask why the directory and not the test
|
||||
# itself? Strangely it's because to properly chain the tests you need to
|
||||
# make the earliest step of the second test depend on the latest part of
|
||||
# the next test. And directories are the only sure thing that you can know
|
||||
# a test needs first.
|
||||
|
||||
DEPENDS test_class_info_load_text_archive.run : test_class_info_save_text_archive.run ;
|
||||
DEPENDS test_class_info_load_text_warchive.run : test_class_info_save_text_warchive.run ;
|
||||
DEPENDS test_class_info_load_xml_archive.run : test_class_info_save_xml_archive.run ;
|
||||
DEPENDS test_class_info_load_xml_archive.run : test_class_info_save_xml_warchive.run ;
|
||||
DEPENDS test_class_info_load_binary_archive.run : test_class_info_save_binary_archive.run ;
|
||||
|
||||
if $(BOOST_SERIALIZATION_TEST) {
|
||||
test-suite "serialization" :
|
||||
[ test-bsl-run-no-lib test_iterators ]
|
||||
@@ -307,7 +293,21 @@ if $(BOOST_SERIALIZATION_TEST) {
|
||||
[ compile test_const_pass.cpp : std::locale-support ]
|
||||
;
|
||||
|
||||
DEPENDS test_demo_xml_load.run : test_demo_xml_save.run ;
|
||||
}
|
||||
|
||||
saving-tests = [ test-bsl-run_files test_class_info_save ]
|
||||
[ test-bsl-run test_demo_xml_save ] ;
|
||||
loading-tests = [ test-bsl-run_files test_class_info_load ]
|
||||
[ test-bsl-run test_demo_xml_load ] ;
|
||||
|
||||
## This makes each individual load test depend on the run of the
|
||||
## corresponding save test. It is important to do this one at a
|
||||
## time because $(saving-tests) and $(loading-tests) can contain
|
||||
## the targets for multiple toolsets.
|
||||
for local save-test-i in $(saving-tests)
|
||||
{
|
||||
DEPENDS $(loading-tests[1]:S=.run) : $(save-test-i:S=.run) ;
|
||||
loading-tests = $(loading-tests[2-]) ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_NO_STD_WSTREAMBUF
|
||||
#error "wide char i/o not supported on this platform"
|
||||
#else
|
||||
#include <boost/archive/polymorphic_text_woarchive.hpp>
|
||||
typedef boost::archive::polymorphic_text_woarchive test_oarchive;
|
||||
typedef std::wofstream test_ostream;
|
||||
@@ -11,3 +15,4 @@ typedef std::wofstream test_ostream;
|
||||
typedef boost::archive::polymorphic_text_wiarchive test_iarchive;
|
||||
typedef std::wifstream test_istream;
|
||||
#define TEST_STREAM_FLAGS (std::ios_base::openmode)0
|
||||
#endif
|
||||
@@ -10,4 +10,4 @@
|
||||
|
||||
#define main test_main
|
||||
|
||||
#include "../example/demo.cpp"
|
||||
#include "../example/demo_xml_load.cpp"
|
||||
|
||||
@@ -10,4 +10,4 @@
|
||||
|
||||
#define main test_main
|
||||
|
||||
#include "../example/demo.cpp"
|
||||
#include "../example/demo_xml_save.cpp"
|
||||
|
||||
@@ -186,19 +186,19 @@ test_main( int /* argc */, char* /* argv */[] )
|
||||
{
|
||||
test_ostream ofs(testfile);
|
||||
test_oarchive oa(ofs);
|
||||
oa << boost::serialization::make_nvp("bp", bp);
|
||||
oa << BOOST_SERIALIZATION_NVP(bp);
|
||||
}
|
||||
|
||||
base* bp2;
|
||||
{
|
||||
test_istream ifs(testfile);
|
||||
test_iarchive ia(ifs);
|
||||
ia >> boost::serialization::make_nvp("bp2", bp2);
|
||||
ia >> BOOST_SERIALIZATION_NVP(bp2);
|
||||
}
|
||||
|
||||
BOOST_ASSERT(1 == save_count);
|
||||
BOOST_ASSERT(1 == load_count);
|
||||
BOOST_ASSERT(*bp2 == *bp);
|
||||
BOOST_CHECK(1 == save_count);
|
||||
BOOST_CHECK(1 == load_count);
|
||||
BOOST_CHECK(*bp2 == *bp);
|
||||
std::remove(testfile);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
+71
-5
@@ -61,6 +61,8 @@ struct random_key {
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(random_key)
|
||||
|
||||
#if defined(__LIBCOMO__) || (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION))
|
||||
|
||||
namespace std {
|
||||
@@ -83,8 +85,8 @@ namespace BOOST_STD_EXTENSION_NAMESPACE {
|
||||
|
||||
#endif
|
||||
|
||||
int test_main( int /* argc */, char* /* argv */[] )
|
||||
{
|
||||
void
|
||||
test_map(){
|
||||
const char * testfile = boost::archive::tmpnam(NULL);
|
||||
BOOST_REQUIRE(NULL != testfile);
|
||||
|
||||
@@ -105,6 +107,45 @@ int test_main( int /* argc */, char* /* argv */[] )
|
||||
ia >> boost::serialization::make_nvp("amap", amap1);
|
||||
}
|
||||
BOOST_CHECK(amap == amap1);
|
||||
std::remove(testfile);
|
||||
}
|
||||
|
||||
void
|
||||
test_map_2(){
|
||||
const char * testfile = boost::archive::tmpnam(NULL);
|
||||
BOOST_REQUIRE(NULL != testfile);
|
||||
|
||||
BOOST_CHECKPOINT("map_2");
|
||||
std::pair<int, int> a(11, 22);
|
||||
std::map<int, int> b;
|
||||
b[0] = 0;
|
||||
b[-1] = -1;
|
||||
b[1] = 1;
|
||||
{
|
||||
test_ostream os(testfile, TEST_STREAM_FLAGS);
|
||||
std::pair<int, int> * const pa = &a;
|
||||
std::map<int, int> * const pb = &b;
|
||||
test_oarchive oa(os);
|
||||
oa << BOOST_SERIALIZATION_NVP(pb);
|
||||
oa << BOOST_SERIALIZATION_NVP(pa);
|
||||
}
|
||||
{
|
||||
test_istream is(testfile, TEST_STREAM_FLAGS);
|
||||
std::pair<int, int> *pa = 0;
|
||||
std::map<int, int> *pb = 0;
|
||||
test_iarchive ia(is);
|
||||
ia >> BOOST_SERIALIZATION_NVP(pb);
|
||||
ia >> BOOST_SERIALIZATION_NVP(pa);
|
||||
delete pa;
|
||||
delete pb;
|
||||
}
|
||||
std::remove(testfile);
|
||||
}
|
||||
|
||||
void
|
||||
test_multimap(){
|
||||
const char * testfile = boost::archive::tmpnam(NULL);
|
||||
BOOST_REQUIRE(NULL != testfile);
|
||||
|
||||
BOOST_CHECKPOINT("multimap");
|
||||
std::multimap<random_key, A> amultimap;
|
||||
@@ -122,8 +163,15 @@ int test_main( int /* argc */, char* /* argv */[] )
|
||||
ia >> boost::serialization::make_nvp("amultimap", amultimap1);
|
||||
}
|
||||
BOOST_CHECK(amultimap == amultimap1);
|
||||
std::remove(testfile);
|
||||
}
|
||||
|
||||
void
|
||||
test_hash_map(){
|
||||
#ifdef BOOST_HAS_HASH
|
||||
const char * testfile = boost::archive::tmpnam(NULL);
|
||||
BOOST_REQUIRE(NULL != testfile);
|
||||
|
||||
BOOST_CHECKPOINT("hash_map");
|
||||
// test hash_map of objects
|
||||
BOOST_STD_EXTENSION_NAMESPACE::hash_map<random_key, A> ahash_map;
|
||||
@@ -150,7 +198,16 @@ int test_main( int /* argc */, char* /* argv */[] )
|
||||
std::copy(ahash_map1.begin(), ahash_map1.end(), std::back_inserter(tvec1));
|
||||
std::sort(tvec1.begin(), tvec1.end());
|
||||
BOOST_CHECK(tvec == tvec1);
|
||||
|
||||
std::remove(testfile);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
test_hash_multimap(){
|
||||
#ifdef BOOST_HAS_HASH
|
||||
const char * testfile = boost::archive::tmpnam(NULL);
|
||||
BOOST_REQUIRE(NULL != testfile);
|
||||
|
||||
BOOST_CHECKPOINT("hash_multimap");
|
||||
BOOST_STD_EXTENSION_NAMESPACE::hash_multimap<random_key, A> ahash_multimap;
|
||||
ahash_multimap.insert(std::make_pair(random_key(), A()));
|
||||
@@ -170,6 +227,7 @@ int test_main( int /* argc */, char* /* argv */[] )
|
||||
// to implement the == operator for hash collections - but goes ahead
|
||||
// does it anyway even though it doesn't seem to work. So sort into
|
||||
// vectors and then compare.
|
||||
std::vector< std::pair<random_key, A> > tvec, tvec1;
|
||||
tvec.clear();
|
||||
tvec1.clear();
|
||||
std::copy(ahash_multimap.begin(), ahash_multimap.end(), std::back_inserter(tvec));
|
||||
@@ -177,8 +235,16 @@ int test_main( int /* argc */, char* /* argv */[] )
|
||||
std::copy(ahash_multimap1.begin(), ahash_multimap1.end(), std::back_inserter(tvec1));
|
||||
std::sort(tvec1.begin(), tvec1.end());
|
||||
BOOST_CHECK(tvec == tvec1);
|
||||
#endif
|
||||
|
||||
std::remove(testfile);
|
||||
#endif
|
||||
}
|
||||
|
||||
int test_main( int /* argc */, char* /* argv */[] )
|
||||
{
|
||||
test_map();
|
||||
test_map_2();
|
||||
test_multimap();
|
||||
test_hash_map();
|
||||
test_hash_multimap();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace std{
|
||||
#include <boost/archive/text_oarchive.hpp>
|
||||
|
||||
#include <boost/serialization/access.hpp>
|
||||
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
|
||||
// Someday, maybe all tests will be converted to the unit test framework.
|
||||
// but for now use the text execution monitor to be consistent with all
|
||||
@@ -161,7 +161,7 @@ public:
|
||||
};
|
||||
BOOST_TEST_DONT_PRINT_LOG_VALUE( E )
|
||||
|
||||
// check that moves don't move stuff pointed too
|
||||
// check that moves don't move stuff pointed to
|
||||
class F {
|
||||
friend class boost::serialization::access;
|
||||
E * m_eptr;
|
||||
@@ -208,11 +208,155 @@ void test4(){
|
||||
BOOST_CHECK_EQUAL(f, f1);
|
||||
}
|
||||
|
||||
// check that multiple moves keep track of the correct target
|
||||
class G {
|
||||
friend class boost::serialization::access;
|
||||
A m_a1;
|
||||
A m_a2;
|
||||
A *m_pa2;
|
||||
template<class Archive>
|
||||
void save(Archive &ar, const unsigned int file_version) const {
|
||||
ar << m_a1;
|
||||
ar << m_a2;
|
||||
ar << m_pa2;
|
||||
}
|
||||
template<class Archive>
|
||||
void load(Archive &ar, const unsigned int file_version){
|
||||
A a; // temporary A
|
||||
ar >> a;
|
||||
m_a1 = a;
|
||||
ar.reset_object_address(& m_a1, & a);
|
||||
ar >> a;
|
||||
m_a2 = a;
|
||||
ar.reset_object_address(& m_a2, & a);
|
||||
ar & m_pa2;
|
||||
}
|
||||
BOOST_SERIALIZATION_SPLIT_MEMBER()
|
||||
public:
|
||||
bool operator==(const G &rhs) const {
|
||||
return
|
||||
m_a1 == rhs.m_a1
|
||||
&& m_a2 == rhs.m_a2
|
||||
&& *m_pa2 == *rhs.m_pa2;
|
||||
}
|
||||
G & operator=(const G & rhs) {
|
||||
m_a1 = rhs.m_a1;
|
||||
m_a2 = rhs.m_a2;
|
||||
m_pa2 = & m_a2;
|
||||
return *this;
|
||||
}
|
||||
G(){
|
||||
m_pa2 = & m_a2;
|
||||
}
|
||||
G(const G & rhs){
|
||||
*this = rhs;
|
||||
}
|
||||
~G(){}
|
||||
};
|
||||
|
||||
BOOST_TEST_DONT_PRINT_LOG_VALUE( G )
|
||||
|
||||
void test5(){
|
||||
std::stringstream ss;
|
||||
const G g;
|
||||
{
|
||||
boost::archive::text_oarchive oa(ss);
|
||||
oa << g;
|
||||
}
|
||||
G g1;
|
||||
{
|
||||
boost::archive::text_iarchive ia(ss);
|
||||
ia >> g1;
|
||||
}
|
||||
BOOST_CHECK_EQUAL(g, g1);
|
||||
}
|
||||
|
||||
// joaquin's test - this tests the case where rest_object_address
|
||||
// is applied to an item which in fact is not tracked so that
|
||||
// the call is in fact superfluous.
|
||||
struct foo
|
||||
{
|
||||
int x;
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive &,const unsigned int)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct bar
|
||||
{
|
||||
foo f[2];
|
||||
foo* pf[2];
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
BOOST_SERIALIZATION_SPLIT_MEMBER()
|
||||
|
||||
template<class Archive>
|
||||
void save(Archive& ar,const unsigned int)const
|
||||
{
|
||||
for(int i=0;i<2;++i){
|
||||
ar<<f[i].x;
|
||||
ar<<f[i];
|
||||
}
|
||||
for(int j=0;j<2;++j){
|
||||
ar<<pf[j];
|
||||
}
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
void load(Archive& ar,const unsigned int)
|
||||
{
|
||||
for(int i=0;i<2;++i){
|
||||
int x;
|
||||
ar>>x;
|
||||
f[i].x=x;
|
||||
ar.reset_object_address(&f[i].x,&x);
|
||||
ar>>f[i];
|
||||
}
|
||||
for(int j=0;j<2;++j){
|
||||
ar>>pf[j];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int test6()
|
||||
{
|
||||
bar b;
|
||||
b.f[0].x=0;
|
||||
b.f[1].x=1;
|
||||
b.pf[0]=&b.f[0];
|
||||
b.pf[1]=&b.f[1];
|
||||
|
||||
std::ostringstream oss;
|
||||
{
|
||||
boost::archive::text_oarchive oa(oss);
|
||||
oa<<const_cast<const bar&>(b);
|
||||
}
|
||||
|
||||
bar b1;
|
||||
b1.pf[0]=0;
|
||||
b1.pf[1]=0;
|
||||
|
||||
std::istringstream iss(oss.str());
|
||||
boost::archive::text_iarchive ia(iss);
|
||||
ia>>b1;
|
||||
BOOST_CHECK(b1.pf[0]==&b1.f[0]&&b1.pf[1]==&b1.f[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_main(int /* argc */, char * /* argv */[])
|
||||
{
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
test6();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -19,13 +19,14 @@ namespace std{
|
||||
#endif
|
||||
#include <boost/type_traits/broken_compiler_spec.hpp>
|
||||
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/weak_ptr.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
|
||||
#include "test_tools.hpp"
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
#include BOOST_PP_STRINGIZE(BOOST_ARCHIVE_TEST)
|
||||
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/weak_ptr.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
#include <boost/serialization/export.hpp>
|
||||
|
||||
// This is a simple class. It contains a counter of the number
|
||||
@@ -48,7 +49,7 @@ public:
|
||||
virtual ~A(){--count;} // default destructor
|
||||
};
|
||||
|
||||
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(A)
|
||||
//BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(A)
|
||||
BOOST_SERIALIZATION_SHARED_PTR(A)
|
||||
|
||||
// B is a subclass of A
|
||||
|
||||
@@ -82,8 +82,8 @@ public:
|
||||
};
|
||||
|
||||
// B needs to be exported because its serialized via a base class pointer
|
||||
//BOOST_CLASS_EXPORT(B)
|
||||
BOOST_SHARED_POINTER_EXPORT(B)
|
||||
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(B)
|
||||
BOOST_SERIALIZATION_SHARED_PTR(B)
|
||||
|
||||
int A::count = 0;
|
||||
|
||||
@@ -91,4 +91,14 @@ namespace archive {
|
||||
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
// the following is to ensure that when one of the libraries changes
|
||||
// BJAM rebuilds and relinks the test.
|
||||
/*
|
||||
#include "text_archive.hpp"
|
||||
#include "text_warchive.hpp"
|
||||
#include "binary_archive.hpp"
|
||||
#include "xml_archive.hpp"
|
||||
#include "xml_warchive.hpp"
|
||||
*/
|
||||
|
||||
#endif // BOOST_SERIALIZATION_TEST_TOOLS_HPP
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+12
-6
@@ -43,7 +43,7 @@
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/libboost_serialization-vc71-mt-gd-1_33.lib"/>
|
||||
OutputFile="$(OutDir)/libboost_serialization-vc71-mt-gd-1_33_1.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
@@ -96,7 +96,7 @@
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/libboost_serialization.lib"/>
|
||||
OutputFile="$(OutDir)/libboost_serialization-vc71-mt-1_33_1.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
@@ -147,7 +147,7 @@
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/libboost_serialization.lib"/>
|
||||
OutputFile="$(OutDir)/libboost_serialization-vc71-s-gd-1_33_1.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
@@ -198,7 +198,7 @@
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/libboost_serialization.lib"/>
|
||||
OutputFile="$(OutDir)/libboost_serialization-vc71-mt-s-gd-1_33_1.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
@@ -251,7 +251,7 @@
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/libboost_serialization.lib"/>
|
||||
OutputFile="$(OutDir)/libboost_serialization-vc71-s-1_33_1.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
@@ -304,7 +304,7 @@
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/libboost_serialization.lib"/>
|
||||
OutputFile="$(OutDir)/libboost_serialization-vc71-mt-s-1_33_1.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
@@ -446,6 +446,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\boost\serialization\detail\shared_ptr_132.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\boost\serialization\detail\stack_constructor.hpp">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
@@ -615,6 +618,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\boost\serialization\void_cast.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\boost\serialization\void_cast_fwd.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\boost\archive\wcslen.hpp">
|
||||
</File>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/libboost_wserialization-vc71-mt-gd-1_32.lib"/>
|
||||
OutputFile="$(OutDir)/libboost_wserialization-vc71-mt-gd-1_33_1.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
@@ -96,7 +96,7 @@
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/libboost_wserialization.lib"/>
|
||||
OutputFile="$(OutDir)/libboost_wserialization-vc71-mt-1_33_1.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
@@ -147,7 +147,7 @@
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/libboost_wserialization.lib"/>
|
||||
OutputFile="$(OutDir)/libboost_wserialization-vc71-mt-s-gd-1_33_1.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
@@ -199,7 +199,7 @@
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/libboost_wserialization.lib"/>
|
||||
OutputFile="$(OutDir)/libboost_wserialization-vc71-s-1_33_1.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
@@ -252,7 +252,7 @@
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/libboost_wserialization.lib"/>
|
||||
OutputFile="$(OutDir)/libboost_wserialization-vc71-mt-s-1_33_1.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
@@ -303,7 +303,7 @@
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/libboost_wserialization.lib"/>
|
||||
OutputFile="$(OutDir)/libboost_wserialization-vc71-s-gd-1_33_1.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
|
||||
Reference in New Issue
Block a user