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