cereal_fwd
Fork of cereal library adding archive supporting forward compatibility
helpers.hpp
Go to the documentation of this file.
1 
4 /*
5  Copyright (c) 2014, Randolph Voorhies, Shane Grant
6  All rights reserved.
7 
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions are met:
10  * Redistributions of source code must retain the above copyright
11  notice, this list of conditions and the following disclaimer.
12  * Redistributions in binary form must reproduce the above copyright
13  notice, this list of conditions and the following disclaimer in the
14  documentation and/or other materials provided with the distribution.
15  * Neither the name of cereal nor the
16  names of its contributors may be used to endorse or promote products
17  derived from this software without specific prior written permission.
18 
19  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
23  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 #ifndef CEREAL_DETAILS_HELPERS_HPP_
31 #define CEREAL_DETAILS_HELPERS_HPP_
32 
33 #include <type_traits>
34 #include <cstdint>
35 #include <utility>
36 #include <memory>
37 #include <unordered_map>
38 #include <stdexcept>
39 
40 #include <cereal/macros.hpp>
42 
43 namespace cereal
44 {
45  // ######################################################################
47 
48  struct Exception : public std::runtime_error
49  {
50  explicit Exception( const std::string & what_ ) : std::runtime_error(what_) {}
51  explicit Exception( const char * what_ ) : std::runtime_error(what_) {}
52  };
53 
54  // ######################################################################
56 
59  using size_type = uint64_t;
60 
61  // forward decls
62  class BinaryOutputArchive;
63  class BinaryInputArchive;
64 
65  // ######################################################################
66  namespace detail
67  {
68  struct NameValuePairCore {};
69  }
70 
72 
134  template <class T>
136  {
137  private:
138  // If we get passed an array, keep the type as is, otherwise store
139  // a reference if we were passed an l value reference, else copy the value
140  using Type = typename std::conditional<std::is_array<typename std::remove_reference<T>::type>::value,
141  typename std::remove_cv<T>::type,
142  typename std::conditional<std::is_lvalue_reference<T>::value,
143  T,
144  typename std::decay<T>::type>::type>::type;
145 
146  // prevent nested nvps
147  static_assert( !std::is_base_of<detail::NameValuePairCore, T>::value,
148  "Cannot pair a name to a NameValuePair" );
149 
150  NameValuePair & operator=( NameValuePair const & ) = delete;
151 
152  public:
154 
161  NameValuePair( char const * n, T && v ) : name(n), value(std::forward<T>(v)) {}
162 
163  char const * name;
164  Type value;
165  };
166 
168 
170  template<class Archive, class T> inline
171  typename
172  std::enable_if<std::is_same<Archive, ::cereal::BinaryInputArchive>::value ||
173  std::is_same<Archive, ::cereal::BinaryOutputArchive>::value,
174  T && >::type
175  make_nvp( const char *, T && value )
176  {
177  return std::forward<T>(value);
178  }
179 
181 
183  template<class Archive, class T> inline
184  typename
185  std::enable_if<!std::is_same<Archive, ::cereal::BinaryInputArchive>::value &&
186  !std::is_same<Archive, ::cereal::BinaryOutputArchive>::value,
187  NameValuePair<T> >::type
188  make_nvp( const char * name, T && value)
189  {
190  return {name, std::forward<T>(value)};
191  }
192 
194 
197  #define CEREAL_NVP_(name, value) ::cereal::make_nvp<Archive>(name, value)
198 
199  // ######################################################################
201 
206  template <class T>
207  struct BinaryData
208  {
211  using PT = typename std::conditional<std::is_const<typename std::remove_pointer<T>::type>::value,
212  const void *,
213  void *>::type;
214 
215  BinaryData( T && d, uint64_t s ) : data(std::forward<T>(d)), size(s) {}
216 
218  uint64_t size;
219  };
220 
221  // ######################################################################
222  namespace detail
223  {
224  // base classes for type checking
225  /* The rtti virtual function only exists to enable an archive to
226  be used in a polymorphic fashion, if necessary. See the
227  archive adapters for an example of this */
229  {
230  public:
231  OutputArchiveBase() = default;
233  OutputArchiveBase & operator=( OutputArchiveBase && ) CEREAL_NOEXCEPT { return *this; }
234  virtual ~OutputArchiveBase() CEREAL_NOEXCEPT = default;
235 
236  private:
237  virtual void rtti() {}
238  };
239 
241  {
242  public:
243  InputArchiveBase() = default;
245  InputArchiveBase & operator=( InputArchiveBase && ) CEREAL_NOEXCEPT { return *this; }
246  virtual ~InputArchiveBase() CEREAL_NOEXCEPT = default;
247 
248  private:
249  virtual void rtti() {}
250  };
251 
252  // forward decls for polymorphic support
253  template <class Archive, class T> struct polymorphic_serialization_support;
254  struct adl_tag;
255 
256  // used during saving pointers
257  static const int32_t msb_32bit = 0x80000000;
258  static const int32_t msb2_32bit = 0x40000000;
259  }
260 
261  // ######################################################################
263 
270  template <class T>
271  class SizeTag
272  {
273  private:
274  // Store a reference if passed an lvalue reference, otherwise
275  // make a copy of the data
276  using Type = typename std::conditional<std::is_lvalue_reference<T>::value,
277  T,
278  typename std::decay<T>::type>::type;
279 
280  SizeTag & operator=( SizeTag const & ) = delete;
281 
282  public:
283  SizeTag( T && sz ) : size(std::forward<T>(sz)) {}
284 
285  Type size;
286  };
288 
293  { };
294 
295  // ######################################################################
297 
316  template <class Key, class Value>
317  struct MapItem
318  {
319  using KeyType = typename std::conditional<
320  std::is_lvalue_reference<Key>::value,
321  Key,
322  typename std::decay<Key>::type>::type;
323 
324  using ValueType = typename std::conditional<
325  std::is_lvalue_reference<Value>::value,
326  Value,
327  typename std::decay<Value>::type>::type;
328 
330 
331  MapItem( Key && key_, Value && value_ ) : key(std::forward<Key>(key_)), value(std::forward<Value>(value_)) {}
332 
333  MapItem & operator=( MapItem const & ) = delete;
334 
335  KeyType key;
336  ValueType value;
337 
339  template <class Archive> inline
340  void CEREAL_SERIALIZE_FUNCTION_NAME(Archive & archive)
341  {
342  archive( make_nvp<Archive>("key", key),
343  make_nvp<Archive>("value", value) );
344  }
345  };
346 
348 
350  template <class KeyType, class ValueType> inline
351  MapItem<KeyType, ValueType> make_map_item(KeyType && key, ValueType && value)
352  {
353  return {std::forward<KeyType>(key), std::forward<ValueType>(value)};
354  }
355 
356  enum class FieldSerialized
357  {
358  YES,
359  NO,
360  INTERNAL
361  };
362 
363  namespace detail
364  {
366 
368  template<class T>
370  {
371  public:
372  VersionIdTag()
373  {}
374 
375  VersionIdTag(std::uint32_t version_id_) : version_id(version_id_)
376  {}
377 
378  VersionIdTag &operator=(VersionIdTag const &) = delete;
379 
380  template<class Archive>
381  std::uint32_t save_minimal(Archive const &) const
382  {
383  return version_id;
384  }
385 
386  template<class Archive>
387  void load_minimal(Archive const &, std::uint32_t const &v)
388  {
389  version_id = v;
390  }
391 
392  std::uint32_t version_id;
393  };
394 
396 
398  template<class T>
400  {
401  private:
402  // Store a reference if passed an lvalue reference, otherwise
403  // make a copy of the data
404  using Type = typename std::conditional<std::is_lvalue_reference<T>::value,
405  T,
406  typename std::decay<T>::type>::type;
407  using SimpleType = typename std::decay<T>::type;
408 
409  PolymorphicIdTag &operator=(PolymorphicIdTag const &) = delete;
410 
411  public:
412  PolymorphicIdTag(T &&polymorphic_id_) : polymorphic_id(std::forward<T>(polymorphic_id_))
413  {}
414 
415  Type polymorphic_id;
416 
417  template<class Archive>
418  SimpleType save_minimal(Archive const &) const
419  {
420  return polymorphic_id;
421  }
422 
423  template<class Archive>
424  void load_minimal(Archive const &, SimpleType const &v)
425  {
426  polymorphic_id = v;
427  }
428  };
429 
430  template<class T>
431  inline
432  PolymorphicIdTag<T> make_polymorphic_id_tag(T &&polymorphic_id)
433  {
434  return {std::forward<T>(polymorphic_id)};
435  }
436 
438 
441  template<class T>
443  {
444  private:
445  // Store a reference if passed an lvalue reference, otherwise
446  // make a copy of the data
447  using Type = typename std::conditional<std::is_lvalue_reference<T>::value,
448  T,
449  typename std::decay<T>::type>::type;
450  using SimpleType = typename std::decay<T>::type;
451 
452  PolymorphicKeyTag &operator=(PolymorphicKeyTag const &) = delete;
453 
454  public:
455  PolymorphicKeyTag(T &&polymorphic_key_) : polymorphic_key(std::forward<T>(polymorphic_key_))
456  {}
457 
458  Type polymorphic_key;
459 
460  template<class Archive>
461  SimpleType save_minimal(Archive const &) const
462  {
463  return polymorphic_key;
464  }
465 
466  template<class Archive>
467  void load_minimal(Archive const &, SimpleType const &v)
468  {
469  polymorphic_key = v;
470  }
471  };
472 
473  template<class T>
474  inline
475  PolymorphicKeyTag<T> make_polymorphic_key_tag(T &&polymorphic_key)
476  {
477  return {std::forward<T>(polymorphic_key)};
478  }
479 
481 
484  template<class T>
486  {
487  private:
488  // Store a reference if passed an lvalue reference, otherwise
489  // make a copy of the data
490  using Type = typename std::conditional<std::is_lvalue_reference<T>::value,
491  T,
492  typename std::decay<T>::type>::type;
493  using SimpleType = typename std::decay<T>::type;
494 
495  ObjectIdTag &operator=(ObjectIdTag const &) = delete;
496 
497  public:
498  ObjectIdTag(T &&object_id_) : object_id(std::forward<T>(object_id_))
499  {}
500 
501  Type object_id;
502 
503  template<class Archive>
504  SimpleType save_minimal(Archive const &) const
505  {
506  return object_id;
507  }
508 
509  template<class Archive>
510  void load_minimal(Archive const &, SimpleType const &v)
511  {
512  object_id = v;
513  }
514  };
515 
516  template<class T>
517  inline
518  ObjectIdTag<T> make_object_id_tag(T &&object_id)
519  {
520  return {std::forward<T>(object_id)};
521  }
522 
524 
527  template<class T>
529  {
530  private:
531  // Store a reference if passed an lvalue reference, otherwise
532  // make a copy of the data
533  using Type = typename std::conditional<std::is_lvalue_reference<T>::value,
534  T,
535  typename std::decay<T>::type>::type;
536  using SimpleType = typename std::decay<T>::type;
537 
538  PointerValidityTag &operator=(PointerValidityTag const &) = delete;
539 
540  public:
541  PointerValidityTag(T &&valid_) : valid(std::forward<T>(valid_))
542  {};
543 
544  Type valid;
545 
546  template<class Archive>
547  SimpleType save_minimal(Archive const &) const
548  {
549  return valid;
550  }
551 
552  template<class Archive>
553  void load_minimal(Archive const &, SimpleType const &v)
554  {
555  valid = v;
556  }
557  };
558 
559  template<class T>
560  inline
561  PointerValidityTag<T> make_pointer_validity_tag(T &&valid)
562  {
563  return {std::forward<T>(valid)};
564  }
565 
566  } // namespace detail
567 
568 
569  namespace detail
570  {
573 
574  namespace{ struct version_binding_tag {}; }
575 
576  // ######################################################################
578 
580  template <class T, class BindingTag = version_binding_tag> struct Version
581  {
582  static const std::uint32_t version = 0;
583  // we don't need to explicitly register these types since they
584  // always get a version number of 0
585  };
586 
588  struct Versions
589  {
590  std::unordered_map<std::size_t, std::uint32_t> mapping;
591 
592  std::uint32_t find( std::size_t hash, std::uint32_t version )
593  {
594  const auto found = mapping.find(hash);
595  if (mapping.end() != found) {
596  return found->second;
597  } else {
598  return mapping.emplace( hash, version ).first->second;
599  }
600  }
601  }; // struct Versions
602  } // namespace detail
603 } // namespace cereal
604 
605 #endif // CEREAL_DETAILS_HELPERS_HPP_
std::enable_if<!std::is_same< Archive,::cereal::BinaryInputArchive >::value &&!std::is_same< Archive,::cereal::BinaryOutputArchive >::value, NameValuePair< T > >::type make_nvp(const char *name, T &&value)
A specialization of make_nvp<> that actually creates an nvp for non-binary archives.
Definition: helpers.hpp:188
PT data
pointer to beginning of data
Definition: helpers.hpp:217
A wrapper around size metadata.
Definition: helpers.hpp:271
A wrapper around object id.
Definition: helpers.hpp:485
Traits struct for NVPs.
Definition: helpers.hpp:68
MapItem< KeyType, ValueType > make_map_item(KeyType &&key, ValueType &&value)
Create a MapItem so that human readable archives will group keys and values together.
Definition: helpers.hpp:351
A wrapper around a key and value for serializing data into maps.
Definition: helpers.hpp:317
Tag used to indicate that field is ommited from the archive.
Definition: helpers.hpp:292
A wrapper around pointer validity marker.
Definition: helpers.hpp:528
Version information class.
Definition: helpers.hpp:580
typename std::conditional< std::is_const< typename std::remove_pointer< T >::type >::value, const void *, void * >::type PT
Definition: helpers.hpp:213
STL namespace.
NameValuePair(char const *n, T &&v)
Constructs a new NameValuePair.
Definition: helpers.hpp:161
A wrapper around polymorphic id.
Definition: helpers.hpp:369
An input archive designed to load data saved using BinaryOutputArchive.
Definition: binary.hpp:88
uint64_t size_type
The size type used by cereal.
Definition: helpers.hpp:59
Definition: access.hpp:40
A wrapper around polymorphic id.
Definition: helpers.hpp:399
A wrapper around polymorphic key.
Definition: helpers.hpp:442
std::enable_if< std::is_same< Archive,::cereal::BinaryInputArchive >::value||std::is_same< Archive,::cereal::BinaryOutputArchive >::value, T && >::type make_nvp(const char *, T &&value)
A specialization of make_nvp<> that simply forwards the value for binary archives.
Definition: helpers.hpp:175
For holding name value pairs.
Definition: helpers.hpp:135
Definition: polymorphic_impl.hpp:573
Preprocessor macros that can customise the cereal library.
void CEREAL_SERIALIZE_FUNCTION_NAME(Archive &archive)
Serialize the MapItem with the NVPs "key" and "value".
Definition: helpers.hpp:340
#define CEREAL_NOEXCEPT
Defines the CEREAL_NOEXCEPT macro to use instead of noexcept.
Definition: macros.hpp:116
A wrapper around data that can be serialized in a binary fashion.
Definition: helpers.hpp:207
Definition: helpers.hpp:228
uint64_t size
size in bytes
Definition: helpers.hpp:218
Definition: helpers.hpp:240
Holds all registered version information.
Definition: helpers.hpp:588
MapItem(Key &&key_, Value &&value_)
Construct a MapItem from a key and a value.
Definition: helpers.hpp:331
Internal polymorphism static object support.
An exception class thrown when things go wrong at runtime.
Definition: helpers.hpp:48
An output archive designed to save data in a compact binary representation.
Definition: binary.hpp:51