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