isotree 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/LICENSE.txt +2 -2
  4. data/README.md +22 -1
  5. data/ext/isotree/ext.cpp +26 -0
  6. data/ext/isotree/extconf.rb +3 -3
  7. data/lib/isotree.rb +1 -0
  8. data/lib/isotree/isolation_forest.rb +86 -1
  9. data/lib/isotree/version.rb +1 -1
  10. data/vendor/cereal/LICENSE +24 -0
  11. data/vendor/cereal/README.md +85 -0
  12. data/vendor/cereal/include/cereal/access.hpp +351 -0
  13. data/vendor/cereal/include/cereal/archives/adapters.hpp +163 -0
  14. data/vendor/cereal/include/cereal/archives/binary.hpp +169 -0
  15. data/vendor/cereal/include/cereal/archives/json.hpp +1019 -0
  16. data/vendor/cereal/include/cereal/archives/portable_binary.hpp +334 -0
  17. data/vendor/cereal/include/cereal/archives/xml.hpp +956 -0
  18. data/vendor/cereal/include/cereal/cereal.hpp +1089 -0
  19. data/vendor/cereal/include/cereal/details/helpers.hpp +422 -0
  20. data/vendor/cereal/include/cereal/details/polymorphic_impl.hpp +796 -0
  21. data/vendor/cereal/include/cereal/details/polymorphic_impl_fwd.hpp +65 -0
  22. data/vendor/cereal/include/cereal/details/static_object.hpp +127 -0
  23. data/vendor/cereal/include/cereal/details/traits.hpp +1411 -0
  24. data/vendor/cereal/include/cereal/details/util.hpp +84 -0
  25. data/vendor/cereal/include/cereal/external/base64.hpp +134 -0
  26. data/vendor/cereal/include/cereal/external/rapidjson/allocators.h +284 -0
  27. data/vendor/cereal/include/cereal/external/rapidjson/cursorstreamwrapper.h +78 -0
  28. data/vendor/cereal/include/cereal/external/rapidjson/document.h +2652 -0
  29. data/vendor/cereal/include/cereal/external/rapidjson/encodedstream.h +299 -0
  30. data/vendor/cereal/include/cereal/external/rapidjson/encodings.h +716 -0
  31. data/vendor/cereal/include/cereal/external/rapidjson/error/en.h +74 -0
  32. data/vendor/cereal/include/cereal/external/rapidjson/error/error.h +161 -0
  33. data/vendor/cereal/include/cereal/external/rapidjson/filereadstream.h +99 -0
  34. data/vendor/cereal/include/cereal/external/rapidjson/filewritestream.h +104 -0
  35. data/vendor/cereal/include/cereal/external/rapidjson/fwd.h +151 -0
  36. data/vendor/cereal/include/cereal/external/rapidjson/internal/biginteger.h +290 -0
  37. data/vendor/cereal/include/cereal/external/rapidjson/internal/diyfp.h +271 -0
  38. data/vendor/cereal/include/cereal/external/rapidjson/internal/dtoa.h +245 -0
  39. data/vendor/cereal/include/cereal/external/rapidjson/internal/ieee754.h +78 -0
  40. data/vendor/cereal/include/cereal/external/rapidjson/internal/itoa.h +308 -0
  41. data/vendor/cereal/include/cereal/external/rapidjson/internal/meta.h +186 -0
  42. data/vendor/cereal/include/cereal/external/rapidjson/internal/pow10.h +55 -0
  43. data/vendor/cereal/include/cereal/external/rapidjson/internal/regex.h +740 -0
  44. data/vendor/cereal/include/cereal/external/rapidjson/internal/stack.h +232 -0
  45. data/vendor/cereal/include/cereal/external/rapidjson/internal/strfunc.h +69 -0
  46. data/vendor/cereal/include/cereal/external/rapidjson/internal/strtod.h +290 -0
  47. data/vendor/cereal/include/cereal/external/rapidjson/internal/swap.h +46 -0
  48. data/vendor/cereal/include/cereal/external/rapidjson/istreamwrapper.h +128 -0
  49. data/vendor/cereal/include/cereal/external/rapidjson/memorybuffer.h +70 -0
  50. data/vendor/cereal/include/cereal/external/rapidjson/memorystream.h +71 -0
  51. data/vendor/cereal/include/cereal/external/rapidjson/msinttypes/inttypes.h +316 -0
  52. data/vendor/cereal/include/cereal/external/rapidjson/msinttypes/stdint.h +300 -0
  53. data/vendor/cereal/include/cereal/external/rapidjson/ostreamwrapper.h +81 -0
  54. data/vendor/cereal/include/cereal/external/rapidjson/pointer.h +1414 -0
  55. data/vendor/cereal/include/cereal/external/rapidjson/prettywriter.h +277 -0
  56. data/vendor/cereal/include/cereal/external/rapidjson/rapidjson.h +656 -0
  57. data/vendor/cereal/include/cereal/external/rapidjson/reader.h +2230 -0
  58. data/vendor/cereal/include/cereal/external/rapidjson/schema.h +2497 -0
  59. data/vendor/cereal/include/cereal/external/rapidjson/stream.h +223 -0
  60. data/vendor/cereal/include/cereal/external/rapidjson/stringbuffer.h +121 -0
  61. data/vendor/cereal/include/cereal/external/rapidjson/writer.h +709 -0
  62. data/vendor/cereal/include/cereal/external/rapidxml/license.txt +52 -0
  63. data/vendor/cereal/include/cereal/external/rapidxml/manual.html +406 -0
  64. data/vendor/cereal/include/cereal/external/rapidxml/rapidxml.hpp +2624 -0
  65. data/vendor/cereal/include/cereal/external/rapidxml/rapidxml_iterators.hpp +175 -0
  66. data/vendor/cereal/include/cereal/external/rapidxml/rapidxml_print.hpp +428 -0
  67. data/vendor/cereal/include/cereal/external/rapidxml/rapidxml_utils.hpp +123 -0
  68. data/vendor/cereal/include/cereal/macros.hpp +154 -0
  69. data/vendor/cereal/include/cereal/specialize.hpp +139 -0
  70. data/vendor/cereal/include/cereal/types/array.hpp +79 -0
  71. data/vendor/cereal/include/cereal/types/atomic.hpp +55 -0
  72. data/vendor/cereal/include/cereal/types/base_class.hpp +203 -0
  73. data/vendor/cereal/include/cereal/types/bitset.hpp +176 -0
  74. data/vendor/cereal/include/cereal/types/boost_variant.hpp +164 -0
  75. data/vendor/cereal/include/cereal/types/chrono.hpp +72 -0
  76. data/vendor/cereal/include/cereal/types/common.hpp +129 -0
  77. data/vendor/cereal/include/cereal/types/complex.hpp +56 -0
  78. data/vendor/cereal/include/cereal/types/concepts/pair_associative_container.hpp +73 -0
  79. data/vendor/cereal/include/cereal/types/deque.hpp +62 -0
  80. data/vendor/cereal/include/cereal/types/forward_list.hpp +68 -0
  81. data/vendor/cereal/include/cereal/types/functional.hpp +43 -0
  82. data/vendor/cereal/include/cereal/types/list.hpp +62 -0
  83. data/vendor/cereal/include/cereal/types/map.hpp +36 -0
  84. data/vendor/cereal/include/cereal/types/memory.hpp +425 -0
  85. data/vendor/cereal/include/cereal/types/optional.hpp +66 -0
  86. data/vendor/cereal/include/cereal/types/polymorphic.hpp +483 -0
  87. data/vendor/cereal/include/cereal/types/queue.hpp +132 -0
  88. data/vendor/cereal/include/cereal/types/set.hpp +103 -0
  89. data/vendor/cereal/include/cereal/types/stack.hpp +76 -0
  90. data/vendor/cereal/include/cereal/types/string.hpp +61 -0
  91. data/vendor/cereal/include/cereal/types/tuple.hpp +123 -0
  92. data/vendor/cereal/include/cereal/types/unordered_map.hpp +36 -0
  93. data/vendor/cereal/include/cereal/types/unordered_set.hpp +99 -0
  94. data/vendor/cereal/include/cereal/types/utility.hpp +47 -0
  95. data/vendor/cereal/include/cereal/types/valarray.hpp +89 -0
  96. data/vendor/cereal/include/cereal/types/variant.hpp +109 -0
  97. data/vendor/cereal/include/cereal/types/vector.hpp +112 -0
  98. data/vendor/cereal/include/cereal/version.hpp +52 -0
  99. data/vendor/isotree/LICENSE +1 -1
  100. data/vendor/isotree/README.md +2 -1
  101. data/vendor/isotree/src/RcppExports.cpp +44 -4
  102. data/vendor/isotree/src/Rwrapper.cpp +141 -51
  103. data/vendor/isotree/src/crit.cpp +1 -1
  104. data/vendor/isotree/src/dealloc.cpp +1 -1
  105. data/vendor/isotree/src/dist.cpp +6 -6
  106. data/vendor/isotree/src/extended.cpp +5 -5
  107. data/vendor/isotree/src/fit_model.cpp +30 -19
  108. data/vendor/isotree/src/helpers_iforest.cpp +26 -11
  109. data/vendor/isotree/src/impute.cpp +7 -7
  110. data/vendor/isotree/src/isoforest.cpp +7 -7
  111. data/vendor/isotree/src/isotree.hpp +27 -5
  112. data/vendor/isotree/src/merge_models.cpp +1 -1
  113. data/vendor/isotree/src/mult.cpp +1 -1
  114. data/vendor/isotree/src/predict.cpp +20 -16
  115. data/vendor/isotree/src/serialize.cpp +1 -1
  116. data/vendor/isotree/src/sql.cpp +545 -0
  117. data/vendor/isotree/src/utils.cpp +36 -44
  118. metadata +98 -92
@@ -0,0 +1,1089 @@
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_