cereal
A C++11 library for serialization
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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 
62 
63  // forward decls
64  class BinaryOutputArchive;
65  class BinaryInputArchive;
66 
67  // ######################################################################
68  namespace detail
69  {
70  struct NameValuePairCore {};
71  struct DeferredDataCore {};
72  }
73 
74  // ######################################################################
76 
138  template <class T>
140  {
141  private:
142  // If we get passed an array, keep the type as is, otherwise store
143  // a reference if we were passed an l value reference, else copy the value
144  using Type = typename std::conditional<std::is_array<typename std::remove_reference<T>::type>::value,
145  typename std::remove_cv<T>::type,
146  typename std::conditional<std::is_lvalue_reference<T>::value,
147  T,
148  typename std::decay<T>::type>::type>::type;
149 
150  // prevent nested nvps
151  static_assert( !std::is_base_of<detail::NameValuePairCore, T>::value,
152  "Cannot pair a name to a NameValuePair" );
153 
154  NameValuePair & operator=( NameValuePair const & ) = delete;
155 
156  public:
158 
165  NameValuePair( char const * n, T && v ) : name(n), value(std::forward<T>(v)) {}
166 
167  char const * name;
168  Type value;
169  };
170 
172 
174  template<class Archive, class T> inline
175  typename
176  std::enable_if<std::is_same<Archive, ::cereal::BinaryInputArchive>::value ||
177  std::is_same<Archive, ::cereal::BinaryOutputArchive>::value,
178  T && >::type
179  make_nvp( const char *, T && value )
180  {
181  return std::forward<T>(value);
182  }
183 
185 
187  template<class Archive, class T> inline
188  typename
189  std::enable_if<!std::is_same<Archive, ::cereal::BinaryInputArchive>::value &&
190  !std::is_same<Archive, ::cereal::BinaryOutputArchive>::value,
191  NameValuePair<T> >::type
192  make_nvp( const char * name, T && value)
193  {
194  return {name, std::forward<T>(value)};
195  }
196 
198 
201  #define CEREAL_NVP_(name, value) ::cereal::make_nvp<Archive>(name, value)
202 
203  // ######################################################################
205 
210  template <class T>
211  struct BinaryData
212  {
215  using PT = typename std::conditional<std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
216  const void *,
217  void *>::type;
218 
219  BinaryData( T && d, uint64_t s ) : data(std::forward<T>(d)), size(s) {}
220 
222  uint64_t size;
223  };
224 
225  // ######################################################################
227 
231  template <class T>
233  {
234  private:
235  // If we get passed an array, keep the type as is, otherwise store
236  // a reference if we were passed an l value reference, else copy the value
237  using Type = typename std::conditional<std::is_array<typename std::remove_reference<T>::type>::value,
238  typename std::remove_cv<T>::type,
239  typename std::conditional<std::is_lvalue_reference<T>::value,
240  T,
241  typename std::decay<T>::type>::type>::type;
242 
243  // prevent nested nvps
244  static_assert( !std::is_base_of<detail::DeferredDataCore, T>::value,
245  "Cannot defer DeferredData" );
246 
247  DeferredData & operator=( DeferredData const & ) = delete;
248 
249  public:
251 
257  DeferredData( T && v ) : value(std::forward<T>(v)) {}
258 
259  Type value;
260  };
261 
262  // ######################################################################
263  namespace detail
264  {
265  // base classes for type checking
266  /* The rtti virtual function only exists to enable an archive to
267  be used in a polymorphic fashion, if necessary. See the
268  archive adapters for an example of this */
270  {
271  public:
272  OutputArchiveBase() = default;
274  OutputArchiveBase & operator=( OutputArchiveBase && ) CEREAL_NOEXCEPT { return *this; }
275  virtual ~OutputArchiveBase() CEREAL_NOEXCEPT = default;
276 
277  private:
278  virtual void rtti() {}
279  };
280 
282  {
283  public:
284  InputArchiveBase() = default;
286  InputArchiveBase & operator=( InputArchiveBase && ) CEREAL_NOEXCEPT { return *this; }
287  virtual ~InputArchiveBase() CEREAL_NOEXCEPT = default;
288 
289  private:
290  virtual void rtti() {}
291  };
292 
293  // forward decls for polymorphic support
294  template <class Archive, class T> struct polymorphic_serialization_support;
295  struct adl_tag;
296 
297  // used during saving pointers
298  static const uint32_t msb_32bit = 0x80000000;
299  static const int32_t msb2_32bit = 0x40000000;
300  }
301 
302  // ######################################################################
304 
311  template <class T>
312  class SizeTag
313  {
314  private:
315  // Store a reference if passed an lvalue reference, otherwise
316  // make a copy of the data
317  using Type = typename std::conditional<std::is_lvalue_reference<T>::value,
318  T,
319  typename std::decay<T>::type>::type;
320 
321  SizeTag & operator=( SizeTag const & ) = delete;
322 
323  public:
324  SizeTag( T && sz ) : size(std::forward<T>(sz)) {}
325 
326  Type size;
327  };
328 
329  // ######################################################################
331 
350  template <class Key, class Value>
351  struct MapItem
352  {
353  using KeyType = typename std::conditional<
354  std::is_lvalue_reference<Key>::value,
355  Key,
356  typename std::decay<Key>::type>::type;
357 
358  using ValueType = typename std::conditional<
359  std::is_lvalue_reference<Value>::value,
360  Value,
361  typename std::decay<Value>::type>::type;
362 
364 
365  MapItem( Key && key_, Value && value_ ) : key(std::forward<Key>(key_)), value(std::forward<Value>(value_)) {}
366 
367  MapItem & operator=( MapItem const & ) = delete;
368 
369  KeyType key;
370  ValueType value;
371 
373  template <class Archive> inline
374  void CEREAL_SERIALIZE_FUNCTION_NAME(Archive & archive)
375  {
376  archive( make_nvp<Archive>("key", key),
377  make_nvp<Archive>("value", value) );
378  }
379  };
380 
382 
384  template <class KeyType, class ValueType> inline
385  MapItem<KeyType, ValueType> make_map_item(KeyType && key, ValueType && value)
386  {
387  return {std::forward<KeyType>(key), std::forward<ValueType>(value)};
388  }
389 
390  namespace detail
391  {
394 
395  namespace{ struct version_binding_tag {}; }
396 
397  // ######################################################################
399 
401  template <class T, class BindingTag = version_binding_tag> struct Version
402  {
403  static const std::uint32_t version = 0;
404  // we don't need to explicitly register these types since they
405  // always get a version number of 0
406  };
407 
409  struct Versions
410  {
411  std::unordered_map<std::size_t, std::uint32_t> mapping;
412 
413  std::uint32_t find( std::size_t hash, std::uint32_t version )
414  {
415  const auto result = mapping.emplace( hash, version );
416  return result.first->second;
417  }
418  }; // struct Versions
419  } // namespace detail
420 } // namespace cereal
421 
422 #endif // CEREAL_DETAILS_HELPERS_HPP_
cereal::detail::Version
Version information class.
Definition: helpers.hpp:401
cereal::detail::OutputArchiveBase
Definition: helpers.hpp:269
cereal::DeferredData::DeferredData
DeferredData(T &&v)
Constructs a new NameValuePair.
Definition: helpers.hpp:257
cereal::BinaryOutputArchive
An output archive designed to save data in a compact binary representation.
Definition: binary.hpp:51
cereal::BinaryData::size
uint64_t size
size in bytes
Definition: helpers.hpp:222
cereal::NameValuePair::NameValuePair
NameValuePair(char const *n, T &&v)
Constructs a new NameValuePair.
Definition: helpers.hpp:165
cereal::detail::polymorphic_serialization_support
Definition: helpers.hpp:294
cereal::BinaryData::data
PT data
pointer to beginning of data
Definition: helpers.hpp:221
macros.hpp
Preprocessor macros that can customise the cereal library.
CEREAL_SIZE_TYPE
#define CEREAL_SIZE_TYPE
Determines the data type used for size_type.
Definition: macros.hpp:70
cereal::detail::DeferredDataCore
Definition: helpers.hpp:71
cereal::NameValuePair
For holding name value pairs.
Definition: helpers.hpp:139
cereal::BinaryInputArchive
An input archive designed to load data saved using BinaryOutputArchive.
Definition: binary.hpp:88
cereal::MapItem::MapItem
MapItem(Key &&key_, Value &&value_)
Construct a MapItem from a key and a value.
Definition: helpers.hpp:365
cereal::MapItem
A wrapper around a key and value for serializing data into maps.
Definition: helpers.hpp:351
cereal::detail::adl_tag
Definition: polymorphic_impl.hpp:696
cereal::BinaryData::PT
typename std::conditional< std::is_const< typename std::remove_pointer< typename std::remove_reference< T >::type >::type >::value, const void *, void * >::type PT
Definition: helpers.hpp:217
cereal::detail::NameValuePairCore
Definition: helpers.hpp:70
cereal::BinaryData
A wrapper around data that can be serialized in a binary fashion.
Definition: helpers.hpp:211
CEREAL_NOEXCEPT
#define CEREAL_NOEXCEPT
Defines the CEREAL_NOEXCEPT macro to use instead of noexcept.
Definition: macros.hpp:130
static_object.hpp
Internal polymorphism static object support.
cereal::MapItem::CEREAL_SERIALIZE_FUNCTION_NAME
void CEREAL_SERIALIZE_FUNCTION_NAME(Archive &archive)
Serialize the MapItem with the NVPs "key" and "value".
Definition: helpers.hpp:374
cereal::detail::Versions
Holds all registered version information.
Definition: helpers.hpp:409
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::DeferredData
A wrapper around data that should be serialized after all non-deferred data.
Definition: helpers.hpp:232
cereal::detail::InputArchiveBase
Definition: helpers.hpp:281
cereal::NameValuePair::make_nvp
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:179
cereal::make_map_item
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:385
cereal::size_type
CEREAL_SIZE_TYPE size_type
The size type used by cereal.
Definition: helpers.hpp:61
cereal::NameValuePair::make_nvp
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:192