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