| 7a956470 |
sago007 |
2016-02-14 17:09 |
1 |
/*! \file cereal.hpp |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
2 |
\brief Main cereal functionality */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
3 |
/* |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
4 |
Copyright (c) 2014, Randolph Voorhies, Shane Grant |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
5 |
All rights reserved. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
6 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
7 |
Redistribution and use in source and binary forms, with or without |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
8 |
modification, are permitted provided that the following conditions are met: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
9 |
* Redistributions of source code must retain the above copyright |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
10 |
notice, this list of conditions and the following disclaimer. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
11 |
* Redistributions in binary form must reproduce the above copyright |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
12 |
notice, this list of conditions and the following disclaimer in the |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
13 |
documentation and/or other materials provided with the distribution. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
14 |
* Neither the name of cereal nor the |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
15 |
names of its contributors may be used to endorse or promote products |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
16 |
derived from this software without specific prior written permission. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
17 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
18 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
19 |
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
20 |
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
21 |
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
22 |
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
23 |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
24 |
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
25 |
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
26 |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
27 |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
28 |
*/ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
29 |
#ifndef CEREAL_CEREAL_HPP_ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
30 |
#define CEREAL_CEREAL_HPP_ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
31 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
32 |
#include <type_traits> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
33 |
#include <string> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
34 |
#include <memory> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
35 |
#include <unordered_map> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
36 |
#include <unordered_set> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
37 |
#include <vector> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
38 |
#include <cstddef> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
39 |
#include <cstdint> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
40 |
#include <functional> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
41 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
42 |
#include <cereal/macros.hpp> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
43 |
#include <cereal/details/traits.hpp> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
44 |
#include <cereal/details/helpers.hpp> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
45 |
#include <cereal/types/base_class.hpp> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
46 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
47 |
namespace cereal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
48 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
49 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
50 |
//! Creates a name value pair |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
51 |
/*! @relates NameValuePair |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
52 |
@ingroup Utility */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
53 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
54 |
NameValuePair<T> make_nvp( std::string const & name, T && value ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
55 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
56 |
return {name.c_str(), std::forward<T>(value)}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
57 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
58 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
59 |
//! Creates a name value pair |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
60 |
/*! @relates NameValuePair |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
61 |
@ingroup Utility */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
62 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
63 |
NameValuePair<T> make_nvp( const char * name, T && value ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
64 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
65 |
return {name, std::forward<T>(value)}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
66 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
67 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
68 |
//! Creates a name value pair for the variable T with the same name as the variable |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
69 |
/*! @relates NameValuePair |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
70 |
@ingroup Utility */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
71 |
#define CEREAL_NVP(T) ::cereal::make_nvp(#T, T) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
72 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
73 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
74 |
//! Convenience function to create binary data for both const and non const pointers |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
75 |
/*! @param data Pointer to beginning of the data |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
76 |
@param size The size in bytes of the data |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
77 |
@relates BinaryData |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
78 |
@ingroup Utility */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
79 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
80 |
BinaryData<T> binary_data( T && data, size_t size ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
81 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
82 |
return {std::forward<T>(data), size}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
83 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
84 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
85 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
86 |
//! Creates a size tag from some variable. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
87 |
/*! Will normally be used to serialize size (e.g. size()) information for |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
88 |
variable size containers. If you have a variable sized container, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
89 |
the very first thing it serializes should be its size, wrapped in |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
90 |
a SizeTag. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
91 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
92 |
@relates SizeTag |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
93 |
@ingroup Utility */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
94 |
template <class T> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
95 |
SizeTag<T> make_size_tag( T && sz ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
96 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
97 |
return {std::forward<T>(sz)}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
98 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
99 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
100 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
101 |
//! Called before a type is serialized to set up any special archive state |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
102 |
//! for processing some type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
103 |
/*! If designing a serializer that needs to set up any kind of special |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
104 |
state or output extra information for a type, specialize this function |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
105 |
for the archive type and the types that require the extra information. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
106 |
@ingroup Internal */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
107 |
template <class Archive, class T> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
108 |
void prologue( Archive & /* archive */, T const & /* data */) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
109 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
110 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
111 |
//! Called after a type is serialized to tear down any special archive state |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
112 |
//! for processing some type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
113 |
/*! @ingroup Internal */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
114 |
template <class Archive, class T> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
115 |
void epilogue( Archive & /* archive */, T const & /* data */) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
116 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
117 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
118 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
119 |
//! Special flags for archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
120 |
/*! AllowEmptyClassElision |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
121 |
This allows for empty classes to be serialized even if they do not provide |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
122 |
a serialization function. Classes with no data members are considered to be |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
123 |
empty. Be warned that if this is enabled and you attempt to serialize an |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
124 |
empty class with improperly formed serialize or load/save functions, no |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
125 |
static error will occur - the error will propogate silently and your |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
126 |
intended serialization functions may not be called. You can manually |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
127 |
ensure that your classes that have custom serialization are correct |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
128 |
by using the traits is_output_serializable and is_input_serializable |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
129 |
in cereal/details/traits.hpp. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
130 |
@ingroup Internal */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
131 |
enum Flags { AllowEmptyClassElision = 1 }; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
132 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
133 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
134 |
//! Registers a specific Archive type with cereal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
135 |
/*! This registration should be done once per archive. A good place to |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
136 |
put this is immediately following the definition of your archive. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
137 |
Archive registration is only strictly necessary if you wish to |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
138 |
support pointers to polymorphic data types. All archives that |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
139 |
come with cereal are already registered. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
140 |
@ingroup Internal */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
141 |
#define CEREAL_REGISTER_ARCHIVE(Archive) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
142 |
namespace cereal { namespace detail { \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
143 |
template <class T, class BindingTag> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
144 |
typename polymorphic_serialization_support<Archive, T>::type \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
145 |
instantiate_polymorphic_binding( T*, Archive*, BindingTag, adl_tag ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
146 |
} } /* end namespaces */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
147 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
148 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
149 |
//! Defines a class version for some type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
150 |
/*! Versioning information is optional and adds some small amount of |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
151 |
overhead to serialization. This overhead will occur both in terms of |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
152 |
space in the archive (the version information for each class will be |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
153 |
stored exactly once) as well as runtime (versioned serialization functions |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
154 |
must check to see if they need to load or store version information). |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
155 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
156 |
Versioning is useful if you plan on fundamentally changing the way some |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
157 |
type is serialized in the future. Versioned serialization functions |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
158 |
cannot be used to load non-versioned data. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
159 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
160 |
By default, all types have an assumed version value of zero. By |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
161 |
using this macro, you may change the version number associated with |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
162 |
some type. cereal will then use this value as a second parameter |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
163 |
to your serialization functions. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
164 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
165 |
The interface for the serialization functions is nearly identical |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
166 |
to non-versioned serialization with the addition of a second parameter, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
167 |
const std::uint32_t version, which will be supplied with the correct |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
168 |
version number. Serializing the version number on a save happens |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
169 |
automatically. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
170 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
171 |
Versioning cannot be mixed with non-versioned serialization functions. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
172 |
Having both types will result result in a compile time error. Data |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
173 |
serialized without versioning cannot be loaded by a serialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
174 |
function with added versioning support. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
175 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
176 |
Example interface for versioning on a non-member serialize function: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
177 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
178 |
@code{cpp} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
179 |
CEREAL_CLASS_VERSION( Mytype, 77 ); // register class version |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
180 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
181 |
template <class Archive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
182 |
void serialize( Archive & ar, Mytype & t, const std::uint32_t version ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
183 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
184 |
// When performing a load, the version associated with the class |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
185 |
// is whatever it was when that data was originally serialized |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
186 |
// |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
187 |
// When we save, we'll use the version that is defined in the macro |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
188 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
189 |
if( version >= some_number ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
190 |
// do this |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
191 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
192 |
// do that |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
193 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
194 |
@endcode |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
195 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
196 |
Interfaces for other forms of serialization functions is similar. This |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
197 |
macro should be placed at global scope. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
198 |
@ingroup Utility */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
199 |
#define CEREAL_CLASS_VERSION(TYPE, VERSION_NUMBER) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
200 |
namespace cereal { namespace detail { \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
201 |
template <> struct Version<TYPE> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
202 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
203 |
static const std::uint32_t version; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
204 |
static std::uint32_t registerVersion() \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
205 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
206 |
::cereal::detail::StaticObject<Versions>::getInstance().mapping.emplace( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
207 |
std::type_index(typeid(TYPE)).hash_code(), VERSION_NUMBER ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
208 |
return VERSION_NUMBER; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
209 |
} \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
210 |
static void unused() { (void)version; } \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
211 |
}; /* end Version */ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
212 |
const std::uint32_t Version<TYPE>::version = \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
213 |
Version<TYPE>::registerVersion(); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
214 |
} } // end namespaces |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
215 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
216 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
217 |
//! The base output archive class |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
218 |
/*! This is the base output archive for all output archives. If you create |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
219 |
a custom archive class, it should derive from this, passing itself as |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
220 |
a template parameter for the ArchiveType. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
221 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
222 |
The base class provides all of the functionality necessary to |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
223 |
properly forward data to the correct serialization functions. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
224 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
225 |
Individual archives should use a combination of prologue and |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
226 |
epilogue functions together with specializations of serialize, save, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
227 |
and load to alter the functionality of their serialization. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
228 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
229 |
@tparam ArchiveType The archive type that derives from OutputArchive |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
230 |
@tparam Flags Flags to control advanced functionality. See the Flags |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
231 |
enum for more information. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
232 |
@ingroup Internal */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
233 |
template<class ArchiveType, std::uint32_t Flags = 0> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
234 |
class OutputArchive : public detail::OutputArchiveBase |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
235 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
236 |
public: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
237 |
//! Construct the output archive |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
238 |
/*! @param derived A pointer to the derived ArchiveType (pass this from the derived archive) */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
239 |
OutputArchive(ArchiveType * const derived) : self(derived), itsCurrentPointerId(1), itsCurrentPolymorphicTypeId(1) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
240 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
241 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
242 |
OutputArchive & operator=( OutputArchive const & ) = delete; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
243 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
244 |
//! Serializes all passed in data |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
245 |
/*! This is the primary interface for serializing data with an archive */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
246 |
template <class ... Types> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
247 |
ArchiveType & operator()( Types && ... args ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
248 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
249 |
self->process( std::forward<Types>( args )... ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
250 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
251 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
252 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
253 |
/*! @name Boost Transition Layer |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
254 |
Functionality that mirrors the syntax for Boost. This is useful if you are transitioning |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
255 |
a large project from Boost to cereal. The preferred interface for cereal is using operator(). */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
256 |
//! @{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
257 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
258 |
//! Serializes passed in data |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
259 |
/*! This is a boost compatability layer and is not the preferred way of using |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
260 |
cereal. If you are transitioning from boost, use this until you can |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
261 |
transition to the operator() overload */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
262 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
263 |
ArchiveType & operator&( T && arg ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
264 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
265 |
self->process( std::forward<T>( arg ) ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
266 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
267 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
268 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
269 |
//! Serializes passed in data |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
270 |
/*! This is a boost compatability layer and is not the preferred way of using |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
271 |
cereal. If you are transitioning from boost, use this until you can |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
272 |
transition to the operator() overload */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
273 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
274 |
ArchiveType & operator<<( T && arg ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
275 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
276 |
self->process( std::forward<T>( arg ) ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
277 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
278 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
279 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
280 |
//! @} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
281 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
282 |
//! Registers a shared pointer with the archive |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
283 |
/*! This function is used to track shared pointer targets to prevent |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
284 |
unnecessary saves from taking place if multiple shared pointers |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
285 |
point to the same data. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
286 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
287 |
@internal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
288 |
@param addr The address (see shared_ptr get()) pointed to by the shared pointer |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
289 |
@return A key that uniquely identifies the pointer */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
290 |
inline std::uint32_t registerSharedPointer( void const * addr ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
291 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
292 |
// Handle null pointers by just returning 0 |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
293 |
if(addr == 0) return 0; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
294 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
295 |
auto id = itsSharedPointerMap.find( addr ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
296 |
if( id == itsSharedPointerMap.end() ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
297 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
298 |
auto ptrId = itsCurrentPointerId++; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
299 |
itsSharedPointerMap.insert( {addr, ptrId} ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
300 |
return ptrId | detail::msb_32bit; // mask MSB to be 1 |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
301 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
302 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
303 |
return id->second; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
304 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
305 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
306 |
//! Registers a polymorphic type name with the archive |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
307 |
/*! This function is used to track polymorphic types to prevent |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
308 |
unnecessary saves of identifying strings used by the polymorphic |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
309 |
support functionality. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
310 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
311 |
@internal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
312 |
@param name The name to associate with a polymorphic type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
313 |
@return A key that uniquely identifies the polymorphic type name */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
314 |
inline std::uint32_t registerPolymorphicType( char const * name ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
315 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
316 |
auto id = itsPolymorphicTypeMap.find( name ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
317 |
if( id == itsPolymorphicTypeMap.end() ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
318 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
319 |
auto polyId = itsCurrentPolymorphicTypeId++; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
320 |
itsPolymorphicTypeMap.insert( {name, polyId} ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
321 |
return polyId | detail::msb_32bit; // mask MSB to be 1 |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
322 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
323 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
324 |
return id->second; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
325 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
326 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
327 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
328 |
//! Serializes data after calling prologue, then calls epilogue |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
329 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
330 |
void process( T && head ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
331 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
332 |
prologue( *self, head ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
333 |
self->processImpl( head ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
334 |
epilogue( *self, head ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
335 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
336 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
337 |
//! Unwinds to process all data |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
338 |
template <class T, class ... Other> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
339 |
void process( T && head, Other && ... tail ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
340 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
341 |
self->process( std::forward<T>( head ) ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
342 |
self->process( std::forward<Other>( tail )... ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
343 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
344 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
345 |
//! Serialization of a virtual_base_class wrapper |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
346 |
/*! \sa virtual_base_class */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
347 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
348 |
ArchiveType & processImpl(virtual_base_class<T> const & b) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
349 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
350 |
traits::detail::base_class_id id(b.base_ptr); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
351 |
if(itsBaseClassSet.count(id) == 0) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
352 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
353 |
itsBaseClassSet.insert(id); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
354 |
self->processImpl( *b.base_ptr ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
355 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
356 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
357 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
358 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
359 |
//! Serialization of a base_class wrapper |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
360 |
/*! \sa base_class */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
361 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
362 |
ArchiveType & processImpl(base_class<T> const & b) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
363 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
364 |
self->processImpl( *b.base_ptr ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
365 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
366 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
367 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
368 |
//! Helper macro that expands the requirements for activating an overload |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
369 |
/*! Requirements: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
370 |
Has the requested serialization function |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
371 |
Does not have version and unversioned at the same time |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
372 |
Is output serializable AND |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
373 |
is specialized for this type of function OR |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
374 |
has no specialization at all */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
375 |
#define PROCESS_IF(name) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
376 |
traits::EnableIf<traits::has_##name<T, ArchiveType>::value, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
377 |
!traits::has_invalid_output_versioning<T, ArchiveType>::value, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
378 |
(traits::is_output_serializable<T, ArchiveType>::value && \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
379 |
(traits::is_specialized_##name<T, ArchiveType>::value || \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
380 |
!traits::is_specialized<T, ArchiveType>::value))> = traits::sfinae |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
381 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
382 |
//! Member serialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
383 |
template <class T, PROCESS_IF(member_serialize)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
384 |
ArchiveType & processImpl(T const & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
385 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
386 |
access::member_serialize(*self, const_cast<T &>(t)); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
387 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
388 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
389 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
390 |
//! Non member serialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
391 |
template <class T, PROCESS_IF(non_member_serialize)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
392 |
ArchiveType & processImpl(T const & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
393 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
394 |
CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast<T &>(t)); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
395 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
396 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
397 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
398 |
//! Member split (save) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
399 |
template <class T, PROCESS_IF(member_save)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
400 |
ArchiveType & processImpl(T const & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
401 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
402 |
access::member_save(*self, t); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
403 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
404 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
405 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
406 |
//! Non member split (save) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
407 |
template <class T, PROCESS_IF(non_member_save)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
408 |
ArchiveType & processImpl(T const & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
409 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
410 |
CEREAL_SAVE_FUNCTION_NAME(*self, t); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
411 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
412 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
413 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
414 |
//! Member split (save_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
415 |
template <class T, PROCESS_IF(member_save_minimal)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
416 |
ArchiveType & processImpl(T const & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
417 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
418 |
self->process( access::member_save_minimal(*self, t) ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
419 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
420 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
421 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
422 |
//! Non member split (save_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
423 |
template <class T, PROCESS_IF(non_member_save_minimal)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
424 |
ArchiveType & processImpl(T const & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
425 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
426 |
self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t) ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
427 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
428 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
429 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
430 |
//! Empty class specialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
431 |
template <class T, traits::EnableIf<(Flags & AllowEmptyClassElision), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
432 |
!traits::is_output_serializable<T, ArchiveType>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
433 |
std::is_empty<T>::value> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
434 |
ArchiveType & processImpl(T const &) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
435 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
436 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
437 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
438 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
439 |
//! No matching serialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
440 |
/*! Invalid if we have invalid output versioning or |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
441 |
we are not output serializable, and either |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
442 |
don't allow empty class ellision or allow it but are not serializing an empty class */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
443 |
template <class T, traits::EnableIf<traits::has_invalid_output_versioning<T, ArchiveType>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
444 |
(!traits::is_output_serializable<T, ArchiveType>::value && |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
445 |
(!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
446 |
ArchiveType & processImpl(T const &) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
447 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
448 |
static_assert(traits::detail::count_output_serializers<T, ArchiveType>::value != 0, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
449 |
"cereal could not find any output serialization functions for the provided type and archive combination. \n\n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
450 |
"Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
451 |
"Serialize functions generally have the following signature: \n\n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
452 |
"template<class Archive> \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
453 |
" void serialize(Archive & ar) \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
454 |
" { \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
455 |
" ar( member1, member2, member3 ); \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
456 |
" } \n\n " ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
457 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
458 |
static_assert(traits::detail::count_output_serializers<T, ArchiveType>::value < 2, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
459 |
"cereal found more than one compatible output serialization function for the provided type and archive combination. \n\n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
460 |
"Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
461 |
"Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
462 |
"Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
463 |
"In addition, you may not mix versioned with non-versioned serialization functions. \n\n "); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
464 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
465 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
466 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
467 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
468 |
//! Registers a class version with the archive and serializes it if necessary |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
469 |
/*! If this is the first time this class has been serialized, we will record its |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
470 |
version number and serialize that. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
471 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
472 |
@tparam T The type of the class being serialized |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
473 |
@param version The version number associated with it */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
474 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
475 |
std::uint32_t registerClassVersion() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
476 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
477 |
static const auto hash = std::type_index(typeid(T)).hash_code(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
478 |
const auto insertResult = itsVersionedTypes.insert( hash ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
479 |
const auto version = |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
480 |
detail::StaticObject<detail::Versions>::getInstance().find( hash, detail::Version<T>::version ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
481 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
482 |
if( insertResult.second ) // insertion took place, serialize the version number |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
483 |
process( make_nvp<ArchiveType>("cereal_class_version", version) ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
484 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
485 |
return version; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
486 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
487 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
488 |
//! Member serialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
489 |
/*! Versioning implementation */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
490 |
template <class T, PROCESS_IF(member_versioned_serialize)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
491 |
ArchiveType & processImpl(T const & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
492 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
493 |
access::member_serialize(*self, const_cast<T &>(t), registerClassVersion<T>()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
494 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
495 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
496 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
497 |
//! Non member serialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
498 |
/*! Versioning implementation */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
499 |
template <class T, PROCESS_IF(non_member_versioned_serialize)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
500 |
ArchiveType & processImpl(T const & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
501 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
502 |
CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast<T &>(t), registerClassVersion<T>()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
503 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
504 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
505 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
506 |
//! Member split (save) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
507 |
/*! Versioning implementation */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
508 |
template <class T, PROCESS_IF(member_versioned_save)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
509 |
ArchiveType & processImpl(T const & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
510 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
511 |
access::member_save(*self, t, registerClassVersion<T>()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
512 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
513 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
514 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
515 |
//! Non member split (save) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
516 |
/*! Versioning implementation */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
517 |
template <class T, PROCESS_IF(non_member_versioned_save)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
518 |
ArchiveType & processImpl(T const & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
519 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
520 |
CEREAL_SAVE_FUNCTION_NAME(*self, t, registerClassVersion<T>()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
521 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
522 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
523 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
524 |
//! Member split (save_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
525 |
/*! Versioning implementation */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
526 |
template <class T, PROCESS_IF(member_versioned_save_minimal)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
527 |
ArchiveType & processImpl(T const & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
528 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
529 |
self->process( access::member_save_minimal(*self, t, registerClassVersion<T>()) ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
530 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
531 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
532 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
533 |
//! Non member split (save_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
534 |
/*! Versioning implementation */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
535 |
template <class T, PROCESS_IF(non_member_versioned_save_minimal)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
536 |
ArchiveType & processImpl(T const & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
537 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
538 |
self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t, registerClassVersion<T>()) ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
539 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
540 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
541 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
542 |
#undef PROCESS_IF |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
543 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
544 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
545 |
ArchiveType * const self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
546 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
547 |
//! A set of all base classes that have been serialized |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
548 |
std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
549 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
550 |
//! Maps from addresses to pointer ids |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
551 |
std::unordered_map<void const *, std::uint32_t> itsSharedPointerMap; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
552 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
553 |
//! The id to be given to the next pointer |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
554 |
std::uint32_t itsCurrentPointerId; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
555 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
556 |
//! Maps from polymorphic type name strings to ids |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
557 |
std::unordered_map<char const *, std::uint32_t> itsPolymorphicTypeMap; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
558 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
559 |
//! The id to be given to the next polymorphic type name |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
560 |
std::uint32_t itsCurrentPolymorphicTypeId; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
561 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
562 |
//! Keeps track of classes that have versioning information associated with them |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
563 |
std::unordered_set<size_type> itsVersionedTypes; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
564 |
}; // class OutputArchive |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
565 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
566 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
567 |
//! The base input archive class |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
568 |
/*! This is the base input archive for all input archives. If you create |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
569 |
a custom archive class, it should derive from this, passing itself as |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
570 |
a template parameter for the ArchiveType. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
571 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
572 |
The base class provides all of the functionality necessary to |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
573 |
properly forward data to the correct serialization functions. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
574 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
575 |
Individual archives should use a combination of prologue and |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
576 |
epilogue functions together with specializations of serialize, save, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
577 |
and load to alter the functionality of their serialization. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
578 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
579 |
@tparam ArchiveType The archive type that derives from InputArchive |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
580 |
@tparam Flags Flags to control advanced functionality. See the Flags |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
581 |
enum for more information. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
582 |
@ingroup Internal */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
583 |
template<class ArchiveType, std::uint32_t Flags = 0> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
584 |
class InputArchive : public detail::InputArchiveBase |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
585 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
586 |
public: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
587 |
//! Construct the output archive |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
588 |
/*! @param derived A pointer to the derived ArchiveType (pass this from the derived archive) */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
589 |
InputArchive(ArchiveType * const derived) : |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
590 |
self(derived), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
591 |
itsBaseClassSet(), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
592 |
itsSharedPointerMap(), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
593 |
itsPolymorphicTypeMap(), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
594 |
itsVersionedTypes() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
595 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
596 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
597 |
InputArchive & operator=( InputArchive const & ) = delete; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
598 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
599 |
//! Serializes all passed in data |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
600 |
/*! This is the primary interface for serializing data with an archive */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
601 |
template <class ... Types> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
602 |
ArchiveType & operator()( Types && ... args ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
603 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
604 |
process( std::forward<Types>( args )... ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
605 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
606 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
607 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
608 |
/*! @name Boost Transition Layer |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
609 |
Functionality that mirrors the syntax for Boost. This is useful if you are transitioning |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
610 |
a large project from Boost to cereal. The preferred interface for cereal is using operator(). */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
611 |
//! @{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
612 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
613 |
//! Serializes passed in data |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
614 |
/*! This is a boost compatability layer and is not the preferred way of using |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
615 |
cereal. If you are transitioning from boost, use this until you can |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
616 |
transition to the operator() overload */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
617 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
618 |
ArchiveType & operator&( T && arg ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
619 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
620 |
self->process( std::forward<T>( arg ) ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
621 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
622 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
623 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
624 |
//! Serializes passed in data |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
625 |
/*! This is a boost compatability layer and is not the preferred way of using |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
626 |
cereal. If you are transitioning from boost, use this until you can |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
627 |
transition to the operator() overload */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
628 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
629 |
ArchiveType & operator>>( T && arg ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
630 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
631 |
self->process( std::forward<T>( arg ) ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
632 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
633 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
634 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
635 |
//! @} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
636 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
637 |
//! Retrieves a shared pointer given a unique key for it |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
638 |
/*! This is used to retrieve a previously registered shared_ptr |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
639 |
which has already been loaded. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
640 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
641 |
@param id The unique id that was serialized for the pointer |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
642 |
@return A shared pointer to the data |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
643 |
@throw Exception if the id does not exist */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
644 |
inline std::shared_ptr<void> getSharedPointer(std::uint32_t const id) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
645 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
646 |
if(id == 0) return std::shared_ptr<void>(nullptr); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
647 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
648 |
auto iter = itsSharedPointerMap.find( id ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
649 |
if(iter == itsSharedPointerMap.end()) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
650 |
throw Exception("Error while trying to deserialize a smart pointer. Could not find id " + std::to_string(id)); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
651 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
652 |
return iter->second; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
653 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
654 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
655 |
//! Registers a shared pointer to its unique identifier |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
656 |
/*! After a shared pointer has been allocated for the first time, it should |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
657 |
be registered with its loaded id for future references to it. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
658 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
659 |
@param id The unique identifier for the shared pointer |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
660 |
@param ptr The actual shared pointer */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
661 |
inline void registerSharedPointer(std::uint32_t const id, std::shared_ptr<void> ptr) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
662 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
663 |
std::uint32_t const stripped_id = id & ~detail::msb_32bit; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
664 |
itsSharedPointerMap[stripped_id] = ptr; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
665 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
666 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
667 |
//! Retrieves the string for a polymorphic type given a unique key for it |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
668 |
/*! This is used to retrieve a string previously registered during |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
669 |
a polymorphic load. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
670 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
671 |
@param id The unique id that was serialized for the polymorphic type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
672 |
@return The string identifier for the tyep */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
673 |
inline std::string getPolymorphicName(std::uint32_t const id) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
674 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
675 |
auto name = itsPolymorphicTypeMap.find( id ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
676 |
if(name == itsPolymorphicTypeMap.end()) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
677 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
678 |
throw Exception("Error while trying to deserialize a polymorphic pointer. Could not find type id " + std::to_string(id)); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
679 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
680 |
return name->second; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
681 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
682 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
683 |
//! Registers a polymorphic name string to its unique identifier |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
684 |
/*! After a polymorphic type has been loaded for the first time, it should |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
685 |
be registered with its loaded id for future references to it. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
686 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
687 |
@param id The unique identifier for the polymorphic type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
688 |
@param name The name associated with the tyep */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
689 |
inline void registerPolymorphicName(std::uint32_t const id, std::string const & name) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
690 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
691 |
std::uint32_t const stripped_id = id & ~detail::msb_32bit; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
692 |
itsPolymorphicTypeMap.insert( {stripped_id, name} ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
693 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
694 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
695 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
696 |
//! Serializes data after calling prologue, then calls epilogue |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
697 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
698 |
void process( T && head ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
699 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
700 |
prologue( *self, head ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
701 |
self->processImpl( head ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
702 |
epilogue( *self, head ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
703 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
704 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
705 |
//! Unwinds to process all data |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
706 |
template <class T, class ... Other> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
707 |
void process( T && head, Other && ... tail ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
708 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
709 |
process( std::forward<T>( head ) ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
710 |
process( std::forward<Other>( tail )... ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
711 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
712 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
713 |
//! Serialization of a virtual_base_class wrapper |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
714 |
/*! \sa virtual_base_class */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
715 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
716 |
ArchiveType & processImpl(virtual_base_class<T> & b) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
717 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
718 |
traits::detail::base_class_id id(b.base_ptr); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
719 |
if(itsBaseClassSet.count(id) == 0) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
720 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
721 |
itsBaseClassSet.insert(id); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
722 |
self->processImpl( *b.base_ptr ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
723 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
724 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
725 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
726 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
727 |
//! Serialization of a base_class wrapper |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
728 |
/*! \sa base_class */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
729 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
730 |
ArchiveType & processImpl(base_class<T> & b) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
731 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
732 |
self->processImpl( *b.base_ptr ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
733 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
734 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
735 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
736 |
//! Helper macro that expands the requirements for activating an overload |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
737 |
/*! Requirements: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
738 |
Has the requested serialization function |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
739 |
Does not have version and unversioned at the same time |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
740 |
Is input serializable AND |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
741 |
is specialized for this type of function OR |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
742 |
has no specialization at all */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
743 |
#define PROCESS_IF(name) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
744 |
traits::EnableIf<traits::has_##name<T, ArchiveType>::value, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
745 |
!traits::has_invalid_input_versioning<T, ArchiveType>::value, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
746 |
(traits::is_input_serializable<T, ArchiveType>::value && \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
747 |
(traits::is_specialized_##name<T, ArchiveType>::value || \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
748 |
!traits::is_specialized<T, ArchiveType>::value))> = traits::sfinae |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
749 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
750 |
//! Member serialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
751 |
template <class T, PROCESS_IF(member_serialize)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
752 |
ArchiveType & processImpl(T & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
753 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
754 |
access::member_serialize(*self, t); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
755 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
756 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
757 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
758 |
//! Non member serialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
759 |
template <class T, PROCESS_IF(non_member_serialize)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
760 |
ArchiveType & processImpl(T & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
761 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
762 |
CEREAL_SERIALIZE_FUNCTION_NAME(*self, t); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
763 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
764 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
765 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
766 |
//! Member split (load) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
767 |
template <class T, PROCESS_IF(member_load)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
768 |
ArchiveType & processImpl(T & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
769 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
770 |
access::member_load(*self, t); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
771 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
772 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
773 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
774 |
//! Non member split (load) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
775 |
template <class T, PROCESS_IF(non_member_load)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
776 |
ArchiveType & processImpl(T & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
777 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
778 |
CEREAL_LOAD_FUNCTION_NAME(*self, t); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
779 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
780 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
781 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
782 |
//! Member split (load_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
783 |
template <class T, PROCESS_IF(member_load_minimal)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
784 |
ArchiveType & processImpl(T & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
785 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
786 |
using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
787 |
typename traits::has_member_save_minimal<T, OutArchiveType>::type value; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
788 |
self->process( value ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
789 |
access::member_load_minimal(*self, t, value); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
790 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
791 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
792 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
793 |
//! Non member split (load_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
794 |
template <class T, PROCESS_IF(non_member_load_minimal)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
795 |
ArchiveType & processImpl(T & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
796 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
797 |
using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
798 |
typename traits::has_non_member_save_minimal<T, OutArchiveType>::type value; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
799 |
self->process( value ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
800 |
CEREAL_LOAD_MINIMAL_FUNCTION_NAME(*self, t, value); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
801 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
802 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
803 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
804 |
//! Empty class specialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
805 |
template <class T, traits::EnableIf<(Flags & AllowEmptyClassElision), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
806 |
!traits::is_input_serializable<T, ArchiveType>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
807 |
std::is_empty<T>::value> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
808 |
ArchiveType & processImpl(T const &) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
809 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
810 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
811 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
812 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
813 |
//! No matching serialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
814 |
/*! Invalid if we have invalid input versioning or |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
815 |
we are not input serializable, and either |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
816 |
don't allow empty class ellision or allow it but are not serializing an empty class */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
817 |
template <class T, traits::EnableIf<traits::has_invalid_input_versioning<T, ArchiveType>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
818 |
(!traits::is_input_serializable<T, ArchiveType>::value && |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
819 |
(!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
820 |
ArchiveType & processImpl(T const &) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
821 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
822 |
static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value != 0, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
823 |
"cereal could not find any input serialization functions for the provided type and archive combination. \n\n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
824 |
"Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
825 |
"Serialize functions generally have the following signature: \n\n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
826 |
"template<class Archive> \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
827 |
" void serialize(Archive & ar) \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
828 |
" { \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
829 |
" ar( member1, member2, member3 ); \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
830 |
" } \n\n " ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
831 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
832 |
static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value < 2, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
833 |
"cereal found more than one compatible input serialization function for the provided type and archive combination. \n\n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
834 |
"Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
835 |
"Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
836 |
"Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
837 |
"In addition, you may not mix versioned with non-versioned serialization functions. \n\n "); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
838 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
839 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
840 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
841 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
842 |
//! Registers a class version with the archive and serializes it if necessary |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
843 |
/*! If this is the first time this class has been serialized, we will record its |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
844 |
version number and serialize that. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
845 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
846 |
@tparam T The type of the class being serialized |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
847 |
@param version The version number associated with it */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
848 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
849 |
std::uint32_t loadClassVersion() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
850 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
851 |
static const auto hash = std::type_index(typeid(T)).hash_code(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
852 |
auto lookupResult = itsVersionedTypes.find( hash ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
853 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
854 |
if( lookupResult != itsVersionedTypes.end() ) // already exists |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
855 |
return lookupResult->second; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
856 |
else // need to load |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
857 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
858 |
std::uint32_t version; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
859 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
860 |
process( make_nvp<ArchiveType>("cereal_class_version", version) ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
861 |
itsVersionedTypes.emplace_hint( lookupResult, hash, version ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
862 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
863 |
return version; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
864 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
865 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
866 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
867 |
//! Member serialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
868 |
/*! Versioning implementation */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
869 |
template <class T, PROCESS_IF(member_versioned_serialize)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
870 |
ArchiveType & processImpl(T & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
871 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
872 |
const auto version = loadClassVersion<T>(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
873 |
access::member_serialize(*self, t, version); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
874 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
875 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
876 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
877 |
//! Non member serialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
878 |
/*! Versioning implementation */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
879 |
template <class T, PROCESS_IF(non_member_versioned_serialize)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
880 |
ArchiveType & processImpl(T & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
881 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
882 |
const auto version = loadClassVersion<T>(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
883 |
CEREAL_SERIALIZE_FUNCTION_NAME(*self, t, version); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
884 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
885 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
886 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
887 |
//! Member split (load) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
888 |
/*! Versioning implementation */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
889 |
template <class T, PROCESS_IF(member_versioned_load)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
890 |
ArchiveType & processImpl(T & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
891 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
892 |
const auto version = loadClassVersion<T>(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
893 |
access::member_load(*self, t, version); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
894 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
895 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
896 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
897 |
//! Non member split (load) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
898 |
/*! Versioning implementation */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
899 |
template <class T, PROCESS_IF(non_member_versioned_load)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
900 |
ArchiveType & processImpl(T & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
901 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
902 |
const auto version = loadClassVersion<T>(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
903 |
CEREAL_LOAD_FUNCTION_NAME(*self, t, version); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
904 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
905 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
906 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
907 |
//! Member split (load_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
908 |
/*! Versioning implementation */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
909 |
template <class T, PROCESS_IF(member_versioned_load_minimal)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
910 |
ArchiveType & processImpl(T & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
911 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
912 |
using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
913 |
const auto version = loadClassVersion<T>(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
914 |
typename traits::has_member_versioned_save_minimal<T, OutArchiveType>::type value; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
915 |
self->process(value); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
916 |
access::member_load_minimal(*self, t, value, version); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
917 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
918 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
919 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
920 |
//! Non member split (load_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
921 |
/*! Versioning implementation */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
922 |
template <class T, PROCESS_IF(non_member_versioned_load_minimal)> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
923 |
ArchiveType & processImpl(T & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
924 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
925 |
using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
926 |
const auto version = loadClassVersion<T>(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
927 |
typename traits::has_non_member_versioned_save_minimal<T, OutArchiveType>::type value; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
928 |
self->process(value); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
929 |
CEREAL_LOAD_MINIMAL_FUNCTION_NAME(*self, t, value, version); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
930 |
return *self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
931 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
932 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
933 |
#undef PROCESS_IF |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
934 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
935 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
936 |
ArchiveType * const self; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
937 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
938 |
//! A set of all base classes that have been serialized |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
939 |
std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
940 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
941 |
//! Maps from pointer ids to metadata |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
942 |
std::unordered_map<std::uint32_t, std::shared_ptr<void>> itsSharedPointerMap; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
943 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
944 |
//! Maps from name ids to names |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
945 |
std::unordered_map<std::uint32_t, std::string> itsPolymorphicTypeMap; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
946 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
947 |
//! Maps from type hash codes to version numbers |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
948 |
std::unordered_map<std::size_t, std::uint32_t> itsVersionedTypes; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
949 |
}; // class InputArchive |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
950 |
} // namespace cereal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
951 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
952 |
// This include needs to come after things such as binary_data, make_nvp, etc |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
953 |
#include <cereal/types/common.hpp> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
954 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
955 |
#endif // CEREAL_CEREAL_HPP_ |
|
|
1970-01-01 00:00 |
956 |
|