cereal
A C++11 library for serialization
cereal.hpp
Go to the documentation of this file.
1 
3 /*
4  Copyright (c) 2014, Randolph Voorhies, Shane Grant
5  All rights reserved.
6 
7  Redistribution and use in source and binary forms, with or without
8  modification, are permitted provided that the following conditions are met:
9  * Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11  * Redistributions in binary form must reproduce the above copyright
12  notice, this list of conditions and the following disclaimer in the
13  documentation and/or other materials provided with the distribution.
14  * Neither the name of the copyright holder nor the
15  names of its contributors may be used to endorse or promote products
16  derived from this software without specific prior written permission.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
22  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 #ifndef CEREAL_CEREAL_HPP_
30 #define CEREAL_CEREAL_HPP_
31 
32 #include <type_traits>
33 #include <string>
34 #include <memory>
35 #include <functional>
36 #include <unordered_map>
37 #include <unordered_set>
38 #include <vector>
39 #include <cstddef>
40 #include <cstdint>
41 #include <functional>
42 
43 #include "cereal/macros.hpp"
47 
48 namespace cereal
49 {
50  // ######################################################################
52 
54  template <class T> inline
55  NameValuePair<T> make_nvp( std::string const & name, T && value )
56  {
57  return {name.c_str(), std::forward<T>(value)};
58  }
59 
61 
63  template <class T> inline
64  NameValuePair<T> make_nvp( const char * name, T && value )
65  {
66  return {name, std::forward<T>(value)};
67  }
68 
70 
72  #define CEREAL_NVP(T) ::cereal::make_nvp(#T, T)
73 
74  // ######################################################################
76 
80  template <class T> inline
81  BinaryData<T> binary_data( T && data, size_t size )
82  {
83  return {std::forward<T>(data), size};
84  }
85 
86  // ######################################################################
88 
95  template <class T> inline
97  {
98  return {std::forward<T>(sz)};
99  }
100 
101  // ######################################################################
103 
148  template <class T> inline
149  DeferredData<T> defer( T && value )
150  {
151  return {std::forward<T>(value)};
152  }
153 
154  // ######################################################################
157 
161  template <class Archive, class T> inline
162  void prologue( Archive & /* archive */, T const & /* data */)
163  { }
164 
167 
168  template <class Archive, class T> inline
169  void epilogue( Archive & /* archive */, T const & /* data */)
170  { }
171 
172  // ######################################################################
174 
185  enum Flags { AllowEmptyClassElision = 1 };
186 
187  // ######################################################################
189 
195  #define CEREAL_REGISTER_ARCHIVE(Archive) \
196  namespace cereal { namespace detail { \
197  template <class T, class BindingTag> \
198  typename polymorphic_serialization_support<Archive, T>::type \
199  instantiate_polymorphic_binding( T*, Archive*, BindingTag, adl_tag ); \
200  } } /* end namespaces */
201 
203  #if defined(__GNUC__)
204  // GCC / clang don't want the function
205  #define CEREAL_UNUSED_FUNCTION
206  #else
207  #define CEREAL_UNUSED_FUNCTION static void unused() { (void)version; }
208  #endif
209 
210  // ######################################################################
212 
262  #ifdef CEREAL_HAS_CPP17
266  #define CEREAL_CLASS_VERSION(TYPE, VERSION_NUMBER) \
267  namespace cereal { namespace detail { \
268  template <> struct Version<TYPE> \
269  { \
270  static std::uint32_t registerVersion() \
271  { \
272  ::cereal::detail::StaticObject<Versions>::getInstance().mapping.emplace( \
273  std::type_index(typeid(TYPE)).hash_code(), VERSION_NUMBER ); \
274  return VERSION_NUMBER; \
275  } \
276  static inline const std::uint32_t version = registerVersion(); \
277  CEREAL_UNUSED_FUNCTION \
278  }; /* end Version */ \
279  } } // end namespaces
280  #else
281  #define CEREAL_CLASS_VERSION(TYPE, VERSION_NUMBER) \
282  namespace cereal { namespace detail { \
283  template <> struct Version<TYPE> \
284  { \
285  static const std::uint32_t version; \
286  static std::uint32_t registerVersion() \
287  { \
288  ::cereal::detail::StaticObject<Versions>::getInstance().mapping.emplace( \
289  std::type_index(typeid(TYPE)).hash_code(), VERSION_NUMBER ); \
290  return VERSION_NUMBER; \
291  } \
292  CEREAL_UNUSED_FUNCTION \
293  }; /* end Version */ \
294  const std::uint32_t Version<TYPE>::version = \
295  Version<TYPE>::registerVersion(); \
296  } } // end namespaces
297 
298  #endif
299 
300  // ######################################################################
302 
317  template<class ArchiveType, std::uint32_t Flags = 0>
319  {
320  public:
322 
323  OutputArchive(ArchiveType * const derived) : self(derived), itsCurrentPointerId(1), itsCurrentPolymorphicTypeId(1)
324  { }
325 
326  OutputArchive & operator=( OutputArchive const & ) = delete;
327 
329 
330  template <class ... Types> inline
331  ArchiveType & operator()( Types && ... args )
332  {
333  self->process( std::forward<Types>( args )... );
334  return *self;
335  }
336 
338 
340  {
341  for( auto & deferment : itsDeferments )
342  deferment();
343  }
344 
348 
351 
355  using is_loading = std::false_type;
356 
358 
362  using is_saving = std::true_type;
363 
365 
368  template <class T> inline
369  ArchiveType & operator&( T && arg )
370  {
371  self->process( std::forward<T>( arg ) );
372  return *self;
373  }
374 
376 
379  template <class T> inline
380  ArchiveType & operator<<( T && arg )
381  {
382  self->process( std::forward<T>( arg ) );
383  return *self;
384  }
385 
387 
389 
398  inline std::uint32_t registerSharedPointer(const std::shared_ptr<const void>& sharedPointer)
399  {
400  void const * addr = sharedPointer.get();
401 
402  // Handle null pointers by just returning 0
403  if(addr == 0) return 0;
404  itsSharedPointerStorage.push_back(sharedPointer);
405 
406  auto id = itsSharedPointerMap.find( addr );
407  if( id == itsSharedPointerMap.end() )
408  {
409  auto ptrId = itsCurrentPointerId++;
410  itsSharedPointerMap.insert( {addr, ptrId} );
411  return ptrId | detail::msb_32bit; // mask MSB to be 1
412  }
413  else
414  return id->second;
415  }
416 
418 
425  inline std::uint32_t registerPolymorphicType( char const * name )
426  {
427  auto id = itsPolymorphicTypeMap.find( name );
428  if( id == itsPolymorphicTypeMap.end() )
429  {
430  auto polyId = itsCurrentPolymorphicTypeId++;
431  itsPolymorphicTypeMap.insert( {name, polyId} );
432  return polyId | detail::msb_32bit; // mask MSB to be 1
433  }
434  else
435  return id->second;
436  }
437 
438  private:
440  template <class T> inline
441  void process( T && head )
442  {
443  prologue( *self, head );
444  self->processImpl( head );
445  epilogue( *self, head );
446  }
447 
449  template <class T, class ... Other> inline
450  void process( T && head, Other && ... tail )
451  {
452  self->process( std::forward<T>( head ) );
453  self->process( std::forward<Other>( tail )... );
454  }
455 
457 
458  template <class T> inline
459  ArchiveType & processImpl(virtual_base_class<T> const & b)
460  {
461  traits::detail::base_class_id id(b.base_ptr);
462  if(itsBaseClassSet.count(id) == 0)
463  {
464  itsBaseClassSet.insert(id);
465  self->processImpl( *b.base_ptr );
466  }
467  return *self;
468  }
469 
471 
472  template <class T> inline
473  ArchiveType & processImpl(base_class<T> const & b)
474  {
475  self->processImpl( *b.base_ptr );
476  return *self;
477  }
478 
479  std::vector<std::function<void(void)>> itsDeferments;
480 
481  template <class T> inline
482  ArchiveType & processImpl(DeferredData<T> const & d)
483  {
484  std::function<void(void)> deferment( [this, d](){ self->process( d.value ); } );
485  itsDeferments.emplace_back( std::move(deferment) );
486 
487  return *self;
488  }
489 
491 
497  #define PROCESS_IF(name) \
498  traits::EnableIf<traits::has_##name<T, ArchiveType>::value, \
499  !traits::has_invalid_output_versioning<T, ArchiveType>::value, \
500  (traits::is_output_serializable<T, ArchiveType>::value && \
501  (traits::is_specialized_##name<T, ArchiveType>::value || \
502  !traits::is_specialized<T, ArchiveType>::value))> = traits::sfinae
503 
505  template <class T, PROCESS_IF(member_serialize)> inline
506  ArchiveType & processImpl(T const & t)
507  {
508  access::member_serialize(*self, const_cast<T &>(t));
509  return *self;
510  }
511 
513  template <class T, PROCESS_IF(non_member_serialize)> inline
514  ArchiveType & processImpl(T const & t)
515  {
516  CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast<T &>(t));
517  return *self;
518  }
519 
521  template <class T, PROCESS_IF(member_save)> inline
522  ArchiveType & processImpl(T const & t)
523  {
524  access::member_save(*self, t);
525  return *self;
526  }
527 
529  template <class T, PROCESS_IF(non_member_save)> inline
530  ArchiveType & processImpl(T const & t)
531  {
532  CEREAL_SAVE_FUNCTION_NAME(*self, t);
533  return *self;
534  }
535 
537  template <class T, PROCESS_IF(member_save_minimal)> inline
538  ArchiveType & processImpl(T const & t)
539  {
540  self->process( access::member_save_minimal(*self, t) );
541  return *self;
542  }
543 
545  template <class T, PROCESS_IF(non_member_save_minimal)> inline
546  ArchiveType & processImpl(T const & t)
547  {
548  self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t) );
549  return *self;
550  }
551 
553  template <class T, traits::EnableIf<(Flags & AllowEmptyClassElision),
554  !traits::is_output_serializable<T, ArchiveType>::value,
555  std::is_empty<T>::value> = traits::sfinae> inline
556  ArchiveType & processImpl(T const &)
557  {
558  return *self;
559  }
560 
562 
565  template <class T, traits::EnableIf<traits::has_invalid_output_versioning<T, ArchiveType>::value ||
566  (!traits::is_output_serializable<T, ArchiveType>::value &&
567  (!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae> inline
568  ArchiveType & processImpl(T const &)
569  {
570  static_assert(traits::detail::count_output_serializers<T, ArchiveType>::value != 0,
571  "cereal could not find any output serialization functions for the provided type and archive combination. \n\n "
572  "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
573  "Serialize functions generally have the following signature: \n\n "
574  "template<class Archive> \n "
575  " void serialize(Archive & ar) \n "
576  " { \n "
577  " ar( member1, member2, member3 ); \n "
578  " } \n\n " );
579 
580  static_assert(traits::detail::count_output_serializers<T, ArchiveType>::value < 2,
581  "cereal found more than one compatible output serialization function for the provided type and archive combination. \n\n "
582  "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
583  "Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n "
584  "Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n "
585  "In addition, you may not mix versioned with non-versioned serialization functions. \n\n ");
586 
587  return *self;
588  }
589 
591 
595  template <class T> inline
596  std::uint32_t registerClassVersion()
597  {
598  static const auto hash = std::type_index(typeid(T)).hash_code();
599  const auto insertResult = itsVersionedTypes.insert( hash );
601  const auto version =
602  detail::StaticObject<detail::Versions>::getInstance().find( hash, detail::Version<T>::version );
603 
604  if( insertResult.second ) // insertion took place, serialize the version number
605  process( make_nvp<ArchiveType>("cereal_class_version", version) );
606 
607  return version;
608  }
609 
611 
612  template <class T, PROCESS_IF(member_versioned_serialize)> inline
613  ArchiveType & processImpl(T const & t)
614  {
615  access::member_serialize(*self, const_cast<T &>(t), registerClassVersion<T>());
616  return *self;
617  }
618 
620 
621  template <class T, PROCESS_IF(non_member_versioned_serialize)> inline
622  ArchiveType & processImpl(T const & t)
623  {
624  CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast<T &>(t), registerClassVersion<T>());
625  return *self;
626  }
627 
629 
630  template <class T, PROCESS_IF(member_versioned_save)> inline
631  ArchiveType & processImpl(T const & t)
632  {
633  access::member_save(*self, t, registerClassVersion<T>());
634  return *self;
635  }
636 
638 
639  template <class T, PROCESS_IF(non_member_versioned_save)> inline
640  ArchiveType & processImpl(T const & t)
641  {
642  CEREAL_SAVE_FUNCTION_NAME(*self, t, registerClassVersion<T>());
643  return *self;
644  }
645 
647 
648  template <class T, PROCESS_IF(member_versioned_save_minimal)> inline
649  ArchiveType & processImpl(T const & t)
650  {
651  self->process( access::member_save_minimal(*self, t, registerClassVersion<T>()) );
652  return *self;
653  }
654 
656 
657  template <class T, PROCESS_IF(non_member_versioned_save_minimal)> inline
658  ArchiveType & processImpl(T const & t)
659  {
660  self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t, registerClassVersion<T>()) );
661  return *self;
662  }
663 
664  #undef PROCESS_IF
665 
666  private:
667  ArchiveType * const self;
668 
670  std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
671 
673  std::unordered_map<void const *, std::uint32_t> itsSharedPointerMap;
674 
676  // during lifetime of itsSharedPointerMap to prevent CVE-2020-11105.
677  std::vector<std::shared_ptr<const void>> itsSharedPointerStorage;
678 
680  std::uint32_t itsCurrentPointerId;
681 
683  std::unordered_map<char const *, std::uint32_t> itsPolymorphicTypeMap;
684 
686  std::uint32_t itsCurrentPolymorphicTypeId;
687 
689  std::unordered_set<size_type> itsVersionedTypes;
690  }; // class OutputArchive
691 
692  // ######################################################################
694 
709  template<class ArchiveType, std::uint32_t Flags = 0>
711  {
712  public:
714 
715  InputArchive(ArchiveType * const derived) :
716  self(derived),
717  itsBaseClassSet(),
718  itsSharedPointerMap(),
719  itsPolymorphicTypeMap(),
720  itsVersionedTypes()
721  { }
722 
723  InputArchive & operator=( InputArchive const & ) = delete;
724 
726 
727  template <class ... Types> inline
728  ArchiveType & operator()( Types && ... args )
729  {
730  process( std::forward<Types>( args )... );
731  return *self;
732  }
733 
735 
737  {
738  for( auto & deferment : itsDeferments )
739  deferment();
740  }
741 
745 
748 
752  using is_loading = std::true_type;
753 
755 
759  using is_saving = std::false_type;
760 
762 
765  template <class T> inline
766  ArchiveType & operator&( T && arg )
767  {
768  self->process( std::forward<T>( arg ) );
769  return *self;
770  }
771 
773 
776  template <class T> inline
777  ArchiveType & operator>>( T && arg )
778  {
779  self->process( std::forward<T>( arg ) );
780  return *self;
781  }
782 
784 
786 
793  inline std::shared_ptr<void> getSharedPointer(std::uint32_t const id)
794  {
795  if(id == 0) return std::shared_ptr<void>(nullptr);
796 
797  auto iter = itsSharedPointerMap.find( id );
798  if(iter == itsSharedPointerMap.end())
799  throw Exception("Error while trying to deserialize a smart pointer. Could not find id " + std::to_string(id));
800 
801  return iter->second;
802  }
803 
805 
811  inline void registerSharedPointer(std::uint32_t const id, std::shared_ptr<void> ptr)
812  {
813  std::uint32_t const stripped_id = id & ~detail::msb_32bit;
814  itsSharedPointerMap[stripped_id] = ptr;
815  }
816 
818 
824  inline std::string getPolymorphicName(std::uint32_t const id)
825  {
826  auto name = itsPolymorphicTypeMap.find( id );
827  if(name == itsPolymorphicTypeMap.end())
828  {
829  throw Exception("Error while trying to deserialize a polymorphic pointer. Could not find type id " + std::to_string(id));
830  }
831  return name->second;
832  }
833 
835 
841  inline void registerPolymorphicName(std::uint32_t const id, std::string const & name)
842  {
843  std::uint32_t const stripped_id = id & ~detail::msb_32bit;
844  itsPolymorphicTypeMap.insert( {stripped_id, name} );
845  }
846 
847  private:
849  template <class T> inline
850  void process( T && head )
851  {
852  prologue( *self, head );
853  self->processImpl( head );
854  epilogue( *self, head );
855  }
856 
858  template <class T, class ... Other> inline
859  void process( T && head, Other && ... tail )
860  {
861  process( std::forward<T>( head ) );
862  process( std::forward<Other>( tail )... );
863  }
864 
866 
867  template <class T> inline
868  ArchiveType & processImpl(virtual_base_class<T> & b)
869  {
870  traits::detail::base_class_id id(b.base_ptr);
871  if(itsBaseClassSet.count(id) == 0)
872  {
873  itsBaseClassSet.insert(id);
874  self->processImpl( *b.base_ptr );
875  }
876  return *self;
877  }
878 
880 
881  template <class T> inline
882  ArchiveType & processImpl(base_class<T> & b)
883  {
884  self->processImpl( *b.base_ptr );
885  return *self;
886  }
887 
888  std::vector<std::function<void(void)>> itsDeferments;
889 
890  template <class T> inline
891  ArchiveType & processImpl(DeferredData<T> const & d)
892  {
893  std::function<void(void)> deferment( [this, d](){ self->process( d.value ); } );
894  itsDeferments.emplace_back( std::move(deferment) );
895 
896  return *self;
897  }
898 
900 
906  #define PROCESS_IF(name) \
907  traits::EnableIf<traits::has_##name<T, ArchiveType>::value, \
908  !traits::has_invalid_input_versioning<T, ArchiveType>::value, \
909  (traits::is_input_serializable<T, ArchiveType>::value && \
910  (traits::is_specialized_##name<T, ArchiveType>::value || \
911  !traits::is_specialized<T, ArchiveType>::value))> = traits::sfinae
912 
914  template <class T, PROCESS_IF(member_serialize)> inline
915  ArchiveType & processImpl(T & t)
916  {
917  access::member_serialize(*self, t);
918  return *self;
919  }
920 
922  template <class T, PROCESS_IF(non_member_serialize)> inline
923  ArchiveType & processImpl(T & t)
924  {
926  return *self;
927  }
928 
930  template <class T, PROCESS_IF(member_load)> inline
931  ArchiveType & processImpl(T & t)
932  {
933  access::member_load(*self, t);
934  return *self;
935  }
936 
938  template <class T, PROCESS_IF(non_member_load)> inline
939  ArchiveType & processImpl(T & t)
940  {
941  CEREAL_LOAD_FUNCTION_NAME(*self, t);
942  return *self;
943  }
944 
946  template <class T, PROCESS_IF(member_load_minimal)> inline
947  ArchiveType & processImpl(T & t)
948  {
949  using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
950  typename traits::has_member_save_minimal<T, OutArchiveType>::type value;
951  self->process( value );
952  access::member_load_minimal(*self, t, value);
953  return *self;
954  }
955 
957  template <class T, PROCESS_IF(non_member_load_minimal)> inline
958  ArchiveType & processImpl(T & t)
959  {
960  using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
961  typename traits::has_non_member_save_minimal<T, OutArchiveType>::type value;
962  self->process( value );
963  CEREAL_LOAD_MINIMAL_FUNCTION_NAME(*self, t, value);
964  return *self;
965  }
966 
968  template <class T, traits::EnableIf<(Flags & AllowEmptyClassElision),
969  !traits::is_input_serializable<T, ArchiveType>::value,
970  std::is_empty<T>::value> = traits::sfinae> inline
971  ArchiveType & processImpl(T const &)
972  {
973  return *self;
974  }
975 
977 
980  template <class T, traits::EnableIf<traits::has_invalid_input_versioning<T, ArchiveType>::value ||
981  (!traits::is_input_serializable<T, ArchiveType>::value &&
982  (!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae> inline
983  ArchiveType & processImpl(T const &)
984  {
985  static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value != 0,
986  "cereal could not find any input serialization functions for the provided type and archive combination. \n\n "
987  "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
988  "Serialize functions generally have the following signature: \n\n "
989  "template<class Archive> \n "
990  " void serialize(Archive & ar) \n "
991  " { \n "
992  " ar( member1, member2, member3 ); \n "
993  " } \n\n " );
994 
995  static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value < 2,
996  "cereal found more than one compatible input serialization function for the provided type and archive combination. \n\n "
997  "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
998  "Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n "
999  "Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n "
1000  "In addition, you may not mix versioned with non-versioned serialization functions. \n\n ");
1001 
1002  return *self;
1003  }
1004 
1006  template <class A, class B, bool C, bool D, bool E, bool F> friend struct detail::Construct;
1007 
1009 
1013  template <class T> inline
1014  std::uint32_t loadClassVersion()
1015  {
1016  static const auto hash = std::type_index(typeid(T)).hash_code();
1017  auto lookupResult = itsVersionedTypes.find( hash );
1018 
1019  if( lookupResult != itsVersionedTypes.end() ) // already exists
1020  return lookupResult->second;
1021  else // need to load
1022  {
1023  std::uint32_t version;
1024 
1025  process( make_nvp<ArchiveType>("cereal_class_version", version) );
1026  itsVersionedTypes.emplace_hint( lookupResult, hash, version );
1027 
1028  return version;
1029  }
1030  }
1031 
1033 
1034  template <class T, PROCESS_IF(member_versioned_serialize)> inline
1035  ArchiveType & processImpl(T & t)
1036  {
1037  const auto version = loadClassVersion<T>();
1038  access::member_serialize(*self, t, version);
1039  return *self;
1040  }
1041 
1043 
1044  template <class T, PROCESS_IF(non_member_versioned_serialize)> inline
1045  ArchiveType & processImpl(T & t)
1046  {
1047  const auto version = loadClassVersion<T>();
1048  CEREAL_SERIALIZE_FUNCTION_NAME(*self, t, version);
1049  return *self;
1050  }
1051 
1053 
1054  template <class T, PROCESS_IF(member_versioned_load)> inline
1055  ArchiveType & processImpl(T & t)
1056  {
1057  const auto version = loadClassVersion<T>();
1058  access::member_load(*self, t, version);
1059  return *self;
1060  }
1061 
1063 
1064  template <class T, PROCESS_IF(non_member_versioned_load)> inline
1065  ArchiveType & processImpl(T & t)
1066  {
1067  const auto version = loadClassVersion<T>();
1068  CEREAL_LOAD_FUNCTION_NAME(*self, t, version);
1069  return *self;
1070  }
1071 
1073 
1074  template <class T, PROCESS_IF(member_versioned_load_minimal)> inline
1075  ArchiveType & processImpl(T & t)
1076  {
1077  using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
1078  const auto version = loadClassVersion<T>();
1079  typename traits::has_member_versioned_save_minimal<T, OutArchiveType>::type value;
1080  self->process(value);
1081  access::member_load_minimal(*self, t, value, version);
1082  return *self;
1083  }
1084 
1086 
1087  template <class T, PROCESS_IF(non_member_versioned_load_minimal)> inline
1088  ArchiveType & processImpl(T & t)
1089  {
1090  using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
1091  const auto version = loadClassVersion<T>();
1092  typename traits::has_non_member_versioned_save_minimal<T, OutArchiveType>::type value;
1093  self->process(value);
1094  CEREAL_LOAD_MINIMAL_FUNCTION_NAME(*self, t, value, version);
1095  return *self;
1096  }
1097 
1098  #undef PROCESS_IF
1099 
1100  private:
1101  ArchiveType * const self;
1102 
1104  std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
1105 
1107  std::unordered_map<std::uint32_t, std::shared_ptr<void>> itsSharedPointerMap;
1108 
1110  std::unordered_map<std::uint32_t, std::string> itsPolymorphicTypeMap;
1111 
1113  std::unordered_map<std::size_t, std::uint32_t> itsVersionedTypes;
1114  }; // class InputArchive
1115 } // namespace cereal
1116 
1117 // This include needs to come after things such as binary_data, make_nvp, etc
1118 #include "cereal/types/common.hpp"
1119 
1120 #endif // CEREAL_CEREAL_HPP_
cereal::InputArchive
The base input archive class.
Definition: cereal.hpp:710
cereal::epilogue
void epilogue(Archive &, T const &)
Definition: cereal.hpp:169
cereal::InputArchive::getSharedPointer
std::shared_ptr< void > getSharedPointer(std::uint32_t const id)
Retrieves a shared pointer given a unique key for it.
Definition: cereal.hpp:793
cereal::OutputArchive< JSONOutputArchive >::is_saving
std::true_type is_saving
Indicates this archive is intended for saving.
Definition: cereal.hpp:362
cereal::detail::OutputArchiveBase
Definition: helpers.hpp:269
cereal::InputArchive::operator()
ArchiveType & operator()(Types &&... args)
Serializes all passed in data.
Definition: cereal.hpp:728
cereal::InputArchive::InputArchive
InputArchive(ArchiveType *const derived)
Construct the output archive.
Definition: cereal.hpp:715
cereal::InputArchive::serializeDeferments
void serializeDeferments()
Serializes any data marked for deferment using defer.
Definition: cereal.hpp:736
common.hpp
Support common types - always included automatically.
cereal::OutputArchive< JSONOutputArchive >::is_loading
std::false_type is_loading
Indicates this archive is not intended for loading.
Definition: cereal.hpp:355
helpers.hpp
Internal helper functionality.
cereal::InputArchive::getPolymorphicName
std::string getPolymorphicName(std::uint32_t const id)
Retrieves the string for a polymorphic type given a unique key for it.
Definition: cereal.hpp:824
cereal::OutputArchive::serializeDeferments
void serializeDeferments()
Serializes any data marked for deferment using defer.
Definition: cereal.hpp:339
CEREAL_SERIALIZE_FUNCTION_NAME
#define CEREAL_SERIALIZE_FUNCTION_NAME
The serialization/deserialization function name to search for.
Definition: macros.hpp:78
cereal::prologue
void prologue(Archive &, T const &)
Definition: cereal.hpp:162
cereal::OutputArchive::operator&
ArchiveType & operator&(T &&arg)
Serializes passed in data.
Definition: cereal.hpp:369
CEREAL_SAVE_MINIMAL_FUNCTION_NAME
#define CEREAL_SAVE_MINIMAL_FUNCTION_NAME
The serialization (save_minimal) function name to search for.
Definition: macros.hpp:106
cereal::NameValuePair::make_nvp
NameValuePair< T > make_nvp(const char *name, T &&value)
Creates a name value pair.
Definition: cereal.hpp:64
cereal::OutputArchive::registerPolymorphicType
std::uint32_t registerPolymorphicType(char const *name)
Registers a polymorphic type name with the archive.
Definition: cereal.hpp:425
macros.hpp
Preprocessor macros that can customise the cereal library.
CEREAL_LOAD_FUNCTION_NAME
#define CEREAL_LOAD_FUNCTION_NAME
The deserialization (load) function name to search for.
Definition: macros.hpp:85
cereal::detail::Construct
Definition: traits.hpp:1338
cereal::Flags
Flags
Special flags for archives.
Definition: cereal.hpp:185
cereal::detail::StaticObject::lock
static LockGuard lock()
Attempts to lock this static object for the current scope.
Definition: static_object.hpp:110
cereal::NameValuePair
For holding name value pairs.
Definition: helpers.hpp:139
cereal::DeferredData::defer
DeferredData< T > defer(T &&value)
Marks data for deferred serialization.
Definition: cereal.hpp:149
cereal::InputArchive< PortableBinaryInputArchive, AllowEmptyClassElision >::is_loading
std::true_type is_loading
Indicates this archive is intended for loading.
Definition: cereal.hpp:752
base_class.hpp
Support for base classes (virtual and non-virtual)
cereal::OutputArchive
The base output archive class.
Definition: cereal.hpp:318
cereal::InputArchive::registerSharedPointer
void registerSharedPointer(std::uint32_t const id, std::shared_ptr< void > ptr)
Registers a shared pointer to its unique identifier.
Definition: cereal.hpp:811
CEREAL_SAVE_FUNCTION_NAME
#define CEREAL_SAVE_FUNCTION_NAME
The serialization (save) function name to search for.
Definition: macros.hpp:92
cereal::SizeTag::make_size_tag
SizeTag< T > make_size_tag(T &&sz)
Creates a size tag from some variable.
Definition: cereal.hpp:96
cereal::BinaryData
A wrapper around data that can be serialized in a binary fashion.
Definition: helpers.hpp:211
cereal::OutputArchive::registerSharedPointer
std::uint32_t registerSharedPointer(const std::shared_ptr< const void > &sharedPointer)
Registers a shared pointer with the archive.
Definition: cereal.hpp:398
cereal::OutputArchive::operator<<
ArchiveType & operator<<(T &&arg)
Serializes passed in data.
Definition: cereal.hpp:380
EnableIf
typename detail::EnableIfHelper< Conditions... >::type EnableIf
Provides a way to enable a function if conditions are met.
Definition: traits.hpp:116
cereal::OutputArchive::OutputArchive
OutputArchive(ArchiveType *const derived)
Construct the output archive.
Definition: cereal.hpp:323
cereal::SizeTag
A wrapper around size metadata.
Definition: helpers.hpp:312
cereal::Exception
An exception class thrown when things go wrong at runtime.
Definition: helpers.hpp:48
CEREAL_LOAD_MINIMAL_FUNCTION_NAME
#define CEREAL_LOAD_MINIMAL_FUNCTION_NAME
The deserialization (load_minimal) function name to search for.
Definition: macros.hpp:99
cereal::DeferredData
A wrapper around data that should be serialized after all non-deferred data.
Definition: helpers.hpp:232
cereal::InputArchive::operator&
ArchiveType & operator&(T &&arg)
Serializes passed in data.
Definition: cereal.hpp:766
cereal::detail::InputArchiveBase
Definition: helpers.hpp:281
cereal::NameValuePair::make_nvp
NameValuePair< T > make_nvp(std::string const &name, T &&value)
Creates a name value pair.
Definition: cereal.hpp:55
traits.hpp
Internal type trait support.
cereal::OutputArchive::operator()
ArchiveType & operator()(Types &&... args)
Serializes all passed in data.
Definition: cereal.hpp:331
cereal::BinaryData::binary_data
BinaryData< T > binary_data(T &&data, size_t size)
Convenience function to create binary data for both const and non const pointers.
Definition: cereal.hpp:81
cereal::InputArchive::registerPolymorphicName
void registerPolymorphicName(std::uint32_t const id, std::string const &name)
Registers a polymorphic name string to its unique identifier.
Definition: cereal.hpp:841
cereal::InputArchive::operator>>
ArchiveType & operator>>(T &&arg)
Serializes passed in data.
Definition: cereal.hpp:777
cereal::InputArchive< PortableBinaryInputArchive, AllowEmptyClassElision >::is_saving
std::false_type is_saving
Indicates this archive is not intended for saving.
Definition: cereal.hpp:759