helpers.hpp
Go to the documentation of this file.
/*
Copyright (c) 2014, Randolph Voorhies, Shane Grant
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CEREAL_DETAILS_HELPERS_HPP_
#define CEREAL_DETAILS_HELPERS_HPP_
#include <type_traits>
#include <cstdint>
#include <utility>
#include <memory>
#include <unordered_map>
#include <stdexcept>
#include "cereal/macros.hpp"
#include "cereal/details/static_object.hpp"
namespace cereal
{
// ######################################################################
struct Exception : public std::runtime_error
{
explicit Exception( const std::string & what_ ) : std::runtime_error(what_) {}
explicit Exception( const char * what_ ) : std::runtime_error(what_) {}
};
// ######################################################################
using size_type = CEREAL_SIZE_TYPE;
// forward decls
class BinaryOutputArchive;
class BinaryInputArchive;
// ######################################################################
namespace detail
{
struct NameValuePairCore {};
struct DeferredDataCore {};
}
// ######################################################################
template <class T>
class NameValuePair : detail::NameValuePairCore
{
private:
// If we get passed an array, keep the type as is, otherwise store
// a reference if we were passed an l value reference, else copy the value
using Type = typename std::conditional<std::is_array<typename std::remove_reference<T>::type>::value,
typename std::remove_cv<T>::type,
typename std::conditional<std::is_lvalue_reference<T>::value,
T,
typename std::decay<T>::type>::type>::type;
// prevent nested nvps
static_assert( !std::is_base_of<detail::NameValuePairCore, T>::value,
"Cannot pair a name to a NameValuePair" );
NameValuePair & operator=( NameValuePair const & ) = delete;
public:
NameValuePair( char const * n, T && v ) : name(n), value(std::forward<T>(v)) {}
char const * name;
Type value;
};
template<class Archive, class T> inline
typename
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 )
{
return std::forward<T>(value);
}
template<class Archive, class T> inline
typename
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)
{
return {name, std::forward<T>(value)};
}
#define CEREAL_NVP_(name, value) ::cereal::make_nvp<Archive>(name, value)
// ######################################################################
template <class T>
struct BinaryData
{
using PT = typename std::conditional<std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
const void *,
void *>::type;
BinaryData( T && d, uint64_t s ) : data(std::forward<T>(d)), size(s) {}
PT data;
uint64_t size;
};
// ######################################################################
template <class T>
class DeferredData : detail::DeferredDataCore
{
private:
// If we get passed an array, keep the type as is, otherwise store
// a reference if we were passed an l value reference, else copy the value
using Type = typename std::conditional<std::is_array<typename std::remove_reference<T>::type>::value,
typename std::remove_cv<T>::type,
typename std::conditional<std::is_lvalue_reference<T>::value,
T,
typename std::decay<T>::type>::type>::type;
// prevent nested nvps
static_assert( !std::is_base_of<detail::DeferredDataCore, T>::value,
"Cannot defer DeferredData" );
DeferredData & operator=( DeferredData const & ) = delete;
public:
DeferredData( T && v ) : value(std::forward<T>(v)) {}
Type value;
};
// ######################################################################
namespace detail
{
// base classes for type checking
/* The rtti virtual function only exists to enable an archive to
be used in a polymorphic fashion, if necessary. See the
archive adapters for an example of this */
class OutputArchiveBase
{
public:
OutputArchiveBase() = default;
OutputArchiveBase( OutputArchiveBase && ) CEREAL_NOEXCEPT {}
OutputArchiveBase & operator=( OutputArchiveBase && ) CEREAL_NOEXCEPT { return *this; }
virtual ~OutputArchiveBase() CEREAL_NOEXCEPT = default;
private:
virtual void rtti() {}
};
class InputArchiveBase
{
public:
InputArchiveBase() = default;
InputArchiveBase( InputArchiveBase && ) CEREAL_NOEXCEPT {}
InputArchiveBase & operator=( InputArchiveBase && ) CEREAL_NOEXCEPT { return *this; }
virtual ~InputArchiveBase() CEREAL_NOEXCEPT = default;
private:
virtual void rtti() {}
};
// forward decls for polymorphic support
template <class Archive, class T> struct polymorphic_serialization_support;
struct adl_tag;
// used during saving pointers
static const uint32_t msb_32bit = 0x80000000;
static const int32_t msb2_32bit = 0x40000000;
}
// ######################################################################
template <class T>
class SizeTag
{
private:
// Store a reference if passed an lvalue reference, otherwise
// make a copy of the data
using Type = typename std::conditional<std::is_lvalue_reference<T>::value,
T,
typename std::decay<T>::type>::type;
SizeTag & operator=( SizeTag const & ) = delete;
public:
SizeTag( T && sz ) : size(std::forward<T>(sz)) {}
Type size;
};
// ######################################################################
template <class Key, class Value>
struct MapItem
{
using KeyType = typename std::conditional<
std::is_lvalue_reference<Key>::value,
Key,
typename std::decay<Key>::type>::type;
using ValueType = typename std::conditional<
std::is_lvalue_reference<Value>::value,
Value,
typename std::decay<Value>::type>::type;
MapItem( Key && key_, Value && value_ ) : key(std::forward<Key>(key_)), value(std::forward<Value>(value_)) {}
MapItem & operator=( MapItem const & ) = delete;
KeyType key;
ValueType value;
template <class Archive> inline
void CEREAL_SERIALIZE_FUNCTION_NAME(Archive & archive)
{
archive( make_nvp<Archive>("key", key),
make_nvp<Archive>("value", value) );
}
};
template <class KeyType, class ValueType> inline
MapItem<KeyType, ValueType> make_map_item(KeyType && key, ValueType && value)
{
return {std::forward<KeyType>(key), std::forward<ValueType>(value)};
}
namespace detail
{
namespace{ struct version_binding_tag {}; }
// ######################################################################
template <class T, class BindingTag = version_binding_tag> struct Version
{
static const std::uint32_t version = 0;
// we don't need to explicitly register these types since they
// always get a version number of 0
};
struct Versions
{
std::unordered_map<std::size_t, std::uint32_t> mapping;
std::uint32_t find( std::size_t hash, std::uint32_t version )
{
const auto result = mapping.emplace( hash, version );
return result.first->second;
}
}; // struct Versions
} // namespace detail
} // namespace cereal
#endif // CEREAL_DETAILS_HELPERS_HPP_
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
cereal::BinaryData::data
PT data
pointer to beginning of data
Definition: helpers.hpp:221
cereal::detail::polymorphic_serialization_support
Definition: helpers.hpp:294
cereal::SizeTag
A wrapper around size metadata.
Definition: helpers.hpp:312
cereal::detail::NameValuePairCore
Traits struct for NVPs.
Definition: helpers.hpp:70
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::MapItem
A wrapper around a key and value for serializing data into maps.
Definition: helpers.hpp:351
cereal::detail::Version
Version information class.
Definition: helpers.hpp:401
CEREAL_SIZE_TYPE
#define CEREAL_SIZE_TYPE
Determines the data type used for size_type.
Definition: macros.hpp:70
std
STL namespace.
cereal::detail::DeferredDataCore
Traits struct for DeferredData.
Definition: helpers.hpp:71
cereal::NameValuePair::NameValuePair
NameValuePair(char const *n, T &&v)
Constructs a new NameValuePair.
Definition: helpers.hpp:165
cereal::BinaryInputArchive
An input archive designed to load data saved using BinaryOutputArchive.
Definition: binary.hpp:88
cereal
Definition: access.hpp:41
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::NameValuePair
For holding name value pairs.
Definition: helpers.hpp:139
cereal::detail::adl_tag
Definition: polymorphic_impl.hpp:681
macros.hpp
Preprocessor macros that can customise the cereal library.
cereal::DeferredData::DeferredData
DeferredData(T &&v)
Constructs a new NameValuePair.
Definition: helpers.hpp:257
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_NOEXCEPT
#define CEREAL_NOEXCEPT
Defines the CEREAL_NOEXCEPT macro to use instead of noexcept.
Definition: macros.hpp:130
cereal::DeferredData
A wrapper around data that should be serialized after all non-deferred data.
Definition: helpers.hpp:232
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::BinaryData
A wrapper around data that can be serialized in a binary fashion.
Definition: helpers.hpp:211
cereal::detail::OutputArchiveBase
Definition: helpers.hpp:269
cereal::size_type
CEREAL_SIZE_TYPE size_type
The size type used by cereal.
Definition: helpers.hpp:61
cereal::BinaryData::size
uint64_t size
size in bytes
Definition: helpers.hpp:222
cereal::detail::InputArchiveBase
Definition: helpers.hpp:281
cereal::detail::Versions
Holds all registered version information.
Definition: helpers.hpp:409
cereal::MapItem::MapItem
MapItem(Key &&key_, Value &&value_)
Construct a MapItem from a key and a value.
Definition: helpers.hpp:365
static_object.hpp
Internal polymorphism static object support.
cereal::Exception
An exception class thrown when things go wrong at runtime.
Definition: helpers.hpp:48
cereal::BinaryOutputArchive
An output archive designed to save data in a compact binary representation.
Definition: binary.hpp:51