cereal
A C++11 library for serialization
 All Classes Files Functions Variables Typedefs Enumerations Groups
helpers.hpp
1 /*
2  Copyright (c) 2013, Randolph Voorhies, Shane Grant
3  All rights reserved.
4 
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions are met:
7  * Redistributions of source code must retain the above copyright
8  notice, this list of conditions and the following disclaimer.
9  * Redistributions in binary form must reproduce the above copyright
10  notice, this list of conditions and the following disclaimer in the
11  documentation and/or other materials provided with the distribution.
12  * Neither the name of cereal nor the
13  names of its contributors may be used to endorse or promote products
14  derived from this software without specific prior written permission.
15 
16  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #ifndef CEREAL_DETAILS_HELPERS_HPP_
28 #define CEREAL_DETAILS_HELPERS_HPP_
29 
30 #include <type_traits>
31 #include <cstdint>
32 #include <utility>
33 
34 namespace cereal
35 {
36  // forward decls
37  class BinaryOutputArchive;
38  class BinaryInputArchive;
39 
40  // ######################################################################
41  namespace detail
42  {
43  struct NameValuePairCore {};
44  }
45 
47 
109  template <class T>
111  {
112  private:
113  // If we get passed an RValue, we'll just make a local copy if it here
114  // otherwise, we store a reference
115  using DT = typename std::decay<T>::type;
116  using Type = typename std::conditional<std::is_rvalue_reference<T>::value,
117  DT,
118  typename std::add_lvalue_reference<DT>::type>::type;
119  // prevent nested nvps
120  static_assert( !std::is_base_of<detail::NameValuePairCore, T>::value,
121  "Cannot pair a name to a NameValuePair" );
122 
123  public:
125 
132  NameValuePair( char const * n, T && v ) : name(n), value(const_cast<Type>(v)) {}
133 
134  char const * name;
135  Type value;
136  };
137 
139 
141  template<class Archive, class T> inline
142  typename
143  std::enable_if<std::is_same<Archive, ::cereal::BinaryInputArchive>::value ||
144  std::is_same<Archive, ::cereal::BinaryOutputArchive>::value,
145  T && >::type
146  make_nvp( const char *, T && value )
147  {
148  return std::forward<T>(value);
149  }
150 
152 
154  template<class Archive, class T> inline
155  typename
156  std::enable_if<!std::is_same<Archive, ::cereal::BinaryInputArchive>::value &&
157  !std::is_same<Archive, ::cereal::BinaryOutputArchive>::value,
158  NameValuePair<T> >::type
159  make_nvp( const char * name, T && value)
160  {
161  return {name, std::forward<T>(value)};
162  }
163 
165 
168 #define _CEREAL_NVP(name, value) ::cereal::make_nvp<Archive>(name, value)
169 
170  // ######################################################################
172 
177  template <class T>
178  struct BinaryData
179  {
182  using PT = typename std::conditional<std::is_const<typename std::remove_pointer<T>::type>::value,
183  const void *,
184  void *>::type;
185 
186  BinaryData( T && d, uint64_t s ) : data(d), size(s) {}
187 
189  uint64_t size;
190  };
191 
192  // ######################################################################
193  namespace detail
194  {
195  // base classes for type checking
196  struct OutputArchiveBase {};
197  struct InputArchiveBase {};
198 
199  // forward decls for polymorphic support
200  template <class Archive, class T> struct polymorphic_serialization_support;
201  struct adl_tag;
202 
203  // used during saving pointers
204  static const int32_t msb_32bit = 0x80000000;
205  static const int32_t msb2_32bit = 0x40000000;
206  }
207 
208  // ######################################################################
210 
217  template <class T>
218  class SizeTag
219  {
220  private:
221  // If we get passed an RValue, we'll just make a local copy if it here
222  // otherwise, we store a reference
223  using DT = typename std::decay<T>::type;
224  using Type = typename std::conditional<std::is_rvalue_reference<T>::value,
225  DT,
226  typename std::add_lvalue_reference<DT>::type>::type;
227 
228  public:
229  SizeTag( T && sz ) : size(const_cast<Type>(sz)) {}
230 
231  Type size;
232  };
233 
234  // ######################################################################
236 
255  template <class Key, class Value>
256  struct MapItem
257  {
258  using DecayKey = typename std::decay<Key>::type;
259  using KeyType = typename std::conditional<
260  std::is_rvalue_reference<Key>::value,
261  DecayKey,
262  typename std::add_lvalue_reference<DecayKey>::type>::type;
263 
264  using DecayValue = typename std::decay<Value>::type;
265  using ValueType = typename std::conditional<
266  std::is_rvalue_reference<Value>::value,
267  DecayValue,
268  typename std::add_lvalue_reference<DecayValue>::type>::type;
269 
271 
272  MapItem( Key && key, Value && value ) : key(const_cast<KeyType>(key)), value(const_cast<ValueType>(value)) {}
273 
274  KeyType key;
275  ValueType value;
276 
278  template <class Archive> inline
279  void serialize(Archive & archive)
280  {
281  archive( make_nvp<Archive>("key", key),
282  make_nvp<Archive>("value", value) );
283  }
284  };
285 
287 
289  template <class KeyType, class ValueType> inline
290  MapItem<KeyType, ValueType> make_map_item(KeyType && key, ValueType && value)
291  {
292  return {std::forward<KeyType>(key), std::forward<ValueType>(value)};
293  }
294 } // namespace cereal
295 
296 #endif // CEREAL_DETAILS_HELPERS_HPP_