git repos / blockattack-game

blame: source/code/Libs/include/cereal/cereal.hpp

normal view · raw

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