forked from organicmaps/organicmaps
[alohalytics] Updated cereal (transport level) library to 1.1
This commit is contained in:
parent
7be9f4946a
commit
ffcc7babb6
40 changed files with 2105 additions and 1576 deletions
|
@ -1,4 +1,7 @@
|
|||
cxa_demangle.cpp was copied here to avoid compilation bug on Android, when
|
||||
compiler can't detect abi::__cxa_demangle() function from cxxabi.h include file.
|
||||
|
||||
The patch was applied to include/details.util.hpp by Alex Zolotarev
|
||||
The patch was applied to include/details.util.hpp by Alex Zolotarev (me@alex.bio)
|
||||
|
||||
Another simple patch changes includes in all headers to avoid -I compiler parameter.
|
||||
Also removed Windows-style line endings from files in external folder.
|
|
@ -1,16 +1,84 @@
|
|||
Header-only Cereal with no dependencies and no extra ```-I``` flags required.
|
||||
cereal - A C++11 library for serialization
|
||||
==========================================
|
||||
|
||||
See [examples/cereal/message.h](https://github.com/KnowSheet/3party/blob/master/examples/cereal/message.h) for example usage.
|
||||
<img src="http://uscilab.github.io/cereal/assets/img/cerealboxside.png" align="right"/><p>cereal is a header-only C++11 serialization library. cereal takes arbitrary data types and reversibly turns them into different representations, such as compact binary encodings, XML, or JSON. cereal was designed to be fast, light-weight, and easy to extend - it has no external dependencies and can be easily bundled with other code or used standalone.</p>
|
||||
|
||||
Ported by Dmitry "Dima" Korolev.
|
||||
### cereal has great documentation
|
||||
|
||||
On Linux, it took the below commands. (MacOS has different ```sed -i``` setting, tweak by changing ```-i``` into ```-i ''```).
|
||||
Looking for more information on how cereal works and its documentation? Visit [cereal's web page](http://USCiLab.github.com/cereal) to get the latest information.
|
||||
|
||||
### cereal is easy to use
|
||||
|
||||
Installation and use of of cereal is fully documented on the [main web page](http://USCiLab.github.com/cereal), but this is a quick and dirty version:
|
||||
|
||||
* Download cereal and place the headers somewhere your code can see them
|
||||
* Write serialization functions for your custom types or use the built in support for the standard library cereal provides
|
||||
* Use the serialization archives to load and save data
|
||||
|
||||
```cpp
|
||||
#include <cereal/types/unordered_map.hpp>
|
||||
#include <cereal/types/memory.hpp>
|
||||
#include <cereal/archives/binary.hpp>
|
||||
#include <fstream>
|
||||
|
||||
struct MyRecord
|
||||
{
|
||||
uint8_t x, y;
|
||||
float z;
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( x, y, z );
|
||||
}
|
||||
};
|
||||
|
||||
struct SomeData
|
||||
{
|
||||
int32_t id;
|
||||
std::shared_ptr<std::unordered_map<uint32_t, MyRecord>> data;
|
||||
|
||||
template <class Archive>
|
||||
void save( Archive & ar ) const
|
||||
{
|
||||
ar( data );
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void load( Archive & ar )
|
||||
{
|
||||
static int32_t idGen = 0;
|
||||
id = idGen++;
|
||||
ar( data );
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
std::ofstream os("out.cereal", std::ios::binary);
|
||||
cereal::BinaryOutputArchive archive( os );
|
||||
|
||||
SomeData myData;
|
||||
archive( myData );
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
wget https://github.com/USCiLab/cereal/archive/v1.0.0.tar.gz
|
||||
(tar xzf cereal-1.0.0.tar.gz; cp -r cereal-1.0.0/include/cereal include; rm -rf cereal-1.0.0)
|
||||
find include/ -mindepth 1 -maxdepth 1 -type f | xargs sed -i "s/^#include <cereal\/\(.*\)>$/#include \".\/\1\"/"
|
||||
find include/ -mindepth 2 -maxdepth 2 -type f | xargs sed -i "s/^#include <cereal\/\(.*\)>$/#include \"..\/\1\"/"
|
||||
find include/ -mindepth 3 -maxdepth 3 -type f | xargs sed -i "s/^#include <cereal\/\(.*\)>$/#include \"..\/..\/\1\"/"
|
||||
find include/ -mindepth 4 -maxdepth 4 -type f | xargs sed -i "s/^#include <cereal\/\(.*\)>$/#include \"..\/..\/..\/\1\"/"
|
||||
```
|
||||
|
||||
### cereal has a mailing list
|
||||
|
||||
Either get in touch over <a href="mailto:cerealcpp@googlegroups.com">email</a> or [on the web](https://groups.google.com/forum/#!forum/cerealcpp).
|
||||
|
||||
|
||||
|
||||
## cereal has a permissive license
|
||||
|
||||
cereal is licensed under the [BSD license](http://opensource.org/licenses/BSD-3-Clause).
|
||||
|
||||
## cereal build status
|
||||
|
||||
* develop : [](https://travis-ci.org/USCiLab/cereal)
|
||||
|
||||
---
|
||||
|
||||
Were you looking for the Haskell cereal? Go <a href="https://github.com/GaloisInc/cereal">here</a>.
|
||||
|
|
|
@ -33,7 +33,8 @@
|
|||
#include <iostream>
|
||||
#include <cstdint>
|
||||
|
||||
#include "./details/helpers.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "details/helpers.hpp"
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
|
@ -224,61 +225,61 @@ namespace cereal
|
|||
public:
|
||||
// ####### Standard Serialization ########################################
|
||||
template<class Archive, class T> inline
|
||||
static auto member_serialize(Archive & ar, T & t) -> decltype(t.serialize(ar))
|
||||
{ t.serialize(ar); }
|
||||
static auto member_serialize(Archive & ar, T & t) -> decltype(t.CEREAL_SERIALIZE_FUNCTION_NAME(ar))
|
||||
{ return t.CEREAL_SERIALIZE_FUNCTION_NAME(ar); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_save(Archive & ar, T const & t) -> decltype(t.save(ar))
|
||||
{ t.save(ar); }
|
||||
static auto member_save(Archive & ar, T const & t) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar))
|
||||
{ return t.CEREAL_SAVE_FUNCTION_NAME(ar); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_save_non_const(Archive & ar, T & t) -> decltype(t.save(ar))
|
||||
{ t.save(ar); }
|
||||
static auto member_save_non_const(Archive & ar, T & t) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar))
|
||||
{ return t.CEREAL_SAVE_FUNCTION_NAME(ar); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_load(Archive & ar, T & t) -> decltype(t.load(ar))
|
||||
{ t.load(ar); }
|
||||
static auto member_load(Archive & ar, T & t) -> decltype(t.CEREAL_LOAD_FUNCTION_NAME(ar))
|
||||
{ return t.CEREAL_LOAD_FUNCTION_NAME(ar); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_save_minimal(Archive const & ar, T const & t) -> decltype(t.save_minimal(ar))
|
||||
{ return t.save_minimal(ar); }
|
||||
static auto member_save_minimal(Archive const & ar, T const & t) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar))
|
||||
{ return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_save_minimal_non_const(Archive const & ar, T & t) -> decltype(t.save_minimal(ar))
|
||||
{ return t.save_minimal(ar); }
|
||||
static auto member_save_minimal_non_const(Archive const & ar, T & t) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar))
|
||||
{ return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar); }
|
||||
|
||||
template<class Archive, class T, class U> inline
|
||||
static auto member_load_minimal(Archive const & ar, T & t, U && u) -> decltype(t.load_minimal(ar, std::forward<U>(u)))
|
||||
{ t.load_minimal(ar, std::forward<U>(u)); }
|
||||
static auto member_load_minimal(Archive const & ar, T & t, U && u) -> decltype(t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u)))
|
||||
{ return t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u)); }
|
||||
|
||||
// ####### Versioned Serialization #######################################
|
||||
template<class Archive, class T> inline
|
||||
static auto member_serialize(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.serialize(ar, version))
|
||||
{ t.serialize(ar, version); }
|
||||
static auto member_serialize(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.CEREAL_SERIALIZE_FUNCTION_NAME(ar, version))
|
||||
{ return t.CEREAL_SERIALIZE_FUNCTION_NAME(ar, version); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_save(Archive & ar, T const & t, const std::uint32_t version ) -> decltype(t.save(ar, version))
|
||||
{ t.save(ar, version); }
|
||||
static auto member_save(Archive & ar, T const & t, const std::uint32_t version ) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar, version))
|
||||
{ return t.CEREAL_SAVE_FUNCTION_NAME(ar, version); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_save_non_const(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.save(ar, version))
|
||||
{ t.save(ar, version); }
|
||||
static auto member_save_non_const(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar, version))
|
||||
{ return t.CEREAL_SAVE_FUNCTION_NAME(ar, version); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_load(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.load(ar, version))
|
||||
{ t.load(ar, version); }
|
||||
static auto member_load(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.CEREAL_LOAD_FUNCTION_NAME(ar, version))
|
||||
{ return t.CEREAL_LOAD_FUNCTION_NAME(ar, version); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_save_minimal(Archive const & ar, T const & t, const std::uint32_t version) -> decltype(t.save_minimal(ar, version))
|
||||
{ return t.save_minimal(ar, version); }
|
||||
static auto member_save_minimal(Archive const & ar, T const & t, const std::uint32_t version) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version))
|
||||
{ return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_save_minimal_non_const(Archive const & ar, T & t, const std::uint32_t version) -> decltype(t.save_minimal(ar, version))
|
||||
{ return t.save_minimal(ar, version); }
|
||||
static auto member_save_minimal_non_const(Archive const & ar, T & t, const std::uint32_t version) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version))
|
||||
{ return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version); }
|
||||
|
||||
template<class Archive, class T, class U> inline
|
||||
static auto member_load_minimal(Archive const & ar, T & t, U && u, const std::uint32_t version) -> decltype(t.load_minimal(ar, std::forward<U>(u), version))
|
||||
{ t.load_minimal(ar, std::forward<U>(u), version); }
|
||||
static auto member_load_minimal(Archive const & ar, T & t, U && u, const std::uint32_t version) -> decltype(t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u), version))
|
||||
{ return t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u), version); }
|
||||
|
||||
// ####### Other Functionality ##########################################
|
||||
// for detecting inheritance from enable_shared_from_this
|
||||
|
@ -292,6 +293,13 @@ namespace cereal
|
|||
new (ptr) T( std::forward<Args>( args )... );
|
||||
}
|
||||
|
||||
// for non-placement new with a default constructor
|
||||
template <class T> inline
|
||||
static T * construct()
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
|
||||
template <class T> inline
|
||||
static std::false_type load_and_construct(...)
|
||||
{ return std::false_type(); }
|
||||
|
|
163
3party/Alohalytics/src/cereal/include/archives/adapters.hpp
Normal file
163
3party/Alohalytics/src/cereal/include/archives/adapters.hpp
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*! \file adapters.hpp
|
||||
\brief Archive adapters that provide additional functionality
|
||||
on top of an existing archive */
|
||||
/*
|
||||
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_ARCHIVES_ADAPTERS_HPP_
|
||||
#define CEREAL_ARCHIVES_ADAPTERS_HPP_
|
||||
|
||||
#include "../details/helpers.hpp"
|
||||
#include <utility>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
#ifdef CEREAL_FUTURE_EXPERIMENTAL
|
||||
|
||||
// Forward declaration for friend access
|
||||
template <class U, class A> U & get_user_data( A & );
|
||||
|
||||
//! Wraps an archive and gives access to user data
|
||||
/*! This adapter is useful if you require access to
|
||||
either raw pointers or references within your
|
||||
serialization functions.
|
||||
|
||||
While cereal does not directly support serialization
|
||||
raw pointers or references, it is sometimes the case
|
||||
that you may want to supply something such as a raw
|
||||
pointer or global reference to some constructor.
|
||||
In this situation this adapter would likely be used
|
||||
with the construct class to allow for non-default
|
||||
constructors.
|
||||
|
||||
@note This feature is experimental and may be altered or removed in a future release. See issue #46.
|
||||
|
||||
@code{.cpp}
|
||||
struct MyUserData
|
||||
{
|
||||
int * myRawPointer;
|
||||
std::reference_wrapper<MyOtherType> myReference;
|
||||
};
|
||||
|
||||
struct MyClass
|
||||
{
|
||||
// Note the raw pointer parameter
|
||||
MyClass( int xx, int * rawP );
|
||||
|
||||
int x;
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{ ar( x ); }
|
||||
|
||||
template <class Archive>
|
||||
static void load_and_construct( Archive & ar, cereal::construct<MyClass> & construct )
|
||||
{
|
||||
int xx;
|
||||
ar( xx );
|
||||
// note the need to use get_user_data to retrieve user data from the archive
|
||||
construct( xx, cereal::get_user_data<MyUserData>( ar ).myRawPointer );
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
MyUserData md;
|
||||
md.myRawPointer = &something;
|
||||
md.myReference = someInstanceOfType;
|
||||
|
||||
std::ifstream is( "data.xml" );
|
||||
cereal::UserDataAdapter<MyUserData, cereal::XMLInputArchive> ar( md, is );
|
||||
|
||||
std::unique_ptr<MyClass> sc;
|
||||
ar( sc ); // use as normal
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@relates get_user_data
|
||||
|
||||
@tparam UserData The type to give the archive access to
|
||||
@tparam Archive The archive to wrap */
|
||||
template <class UserData, class Archive>
|
||||
class UserDataAdapter : public Archive
|
||||
{
|
||||
public:
|
||||
//! Construct the archive with some user data struct
|
||||
/*! This will forward all arguments (other than the user
|
||||
data) to the wrapped archive type. The UserDataAdapter
|
||||
can then be used identically to the wrapped archive type
|
||||
|
||||
@tparam Args The arguments to pass to the constructor of
|
||||
the archive. */
|
||||
template <class ... Args>
|
||||
UserDataAdapter( UserData & ud, Args && ... args ) :
|
||||
Archive( std::forward<Args>( args )... ),
|
||||
userdata( ud )
|
||||
{ }
|
||||
|
||||
private:
|
||||
//! Overload the rtti function to enable dynamic_cast
|
||||
void rtti() {}
|
||||
friend UserData & get_user_data<UserData>( Archive & ar );
|
||||
UserData & userdata; //!< The actual user data
|
||||
};
|
||||
|
||||
//! Retrieves user data from an archive wrapped by UserDataAdapter
|
||||
/*! This will attempt to retrieve the user data associated with
|
||||
some archive wrapped by UserDataAdapter. If this is used on
|
||||
an archive that is not wrapped, a run-time exception will occur.
|
||||
|
||||
@note This feature is experimental and may be altered or removed in a future release. See issue #46.
|
||||
|
||||
@note The correct use of this function cannot be enforced at compile
|
||||
time.
|
||||
|
||||
@relates UserDataAdapter
|
||||
@tparam UserData The data struct contained in the archive
|
||||
@tparam Archive The archive, which should be wrapped by UserDataAdapter
|
||||
@param ar The archive
|
||||
@throws Exception if the archive this is used upon is not wrapped with
|
||||
UserDataAdapter. */
|
||||
template <class UserData, class Archive>
|
||||
UserData & get_user_data( Archive & ar )
|
||||
{
|
||||
try
|
||||
{
|
||||
return dynamic_cast<UserDataAdapter<UserData, Archive> &>( ar ).userdata;
|
||||
}
|
||||
catch( std::bad_cast const & )
|
||||
{
|
||||
throw ::cereal::Exception("Attempting to get user data from archive not wrapped in UserDataAdapter");
|
||||
}
|
||||
}
|
||||
#endif // CEREAL_FUTURE_EXPERIMENTAL
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_ARCHIVES_ADAPTERS_HPP_
|
|
@ -44,7 +44,7 @@ namespace cereal
|
|||
architectures with different endianness, use PortableBinaryOutputArchive.
|
||||
|
||||
When using a binary archive and a file stream, you must use the
|
||||
std::ios::binary format flag to avoid having your data altered
|
||||
std::ios::binary format flag to avoid having your data altered
|
||||
inadvertently.
|
||||
|
||||
\ingroup Archives */
|
||||
|
@ -77,9 +77,9 @@ namespace cereal
|
|||
/* This archive does nothing to ensure that the endianness of the saved
|
||||
and loaded data is the same. If you need to have portability over
|
||||
architectures with different endianness, use PortableBinaryOutputArchive.
|
||||
|
||||
|
||||
When using a binary archive and a file stream, you must use the
|
||||
std::ios::binary format flag to avoid having your data altered
|
||||
std::ios::binary format flag to avoid having your data altered
|
||||
inadvertently.
|
||||
|
||||
\ingroup Archives */
|
||||
|
@ -111,7 +111,7 @@ namespace cereal
|
|||
//! Saving for POD types to binary
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
save(BinaryOutputArchive & ar, T const & t)
|
||||
CEREAL_SAVE_FUNCTION_NAME(BinaryOutputArchive & ar, T const & t)
|
||||
{
|
||||
ar.saveBinary(std::addressof(t), sizeof(t));
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ namespace cereal
|
|||
//! Loading for POD types from binary
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
load(BinaryInputArchive & ar, T & t)
|
||||
CEREAL_LOAD_FUNCTION_NAME(BinaryInputArchive & ar, T & t)
|
||||
{
|
||||
ar.loadBinary(std::addressof(t), sizeof(t));
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ namespace cereal
|
|||
//! Serializing NVP types to binary
|
||||
template <class Archive, class T> inline
|
||||
CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive)
|
||||
serialize( Archive & ar, NameValuePair<T> & t )
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, NameValuePair<T> & t )
|
||||
{
|
||||
ar( t.value );
|
||||
}
|
||||
|
@ -135,21 +135,21 @@ namespace cereal
|
|||
//! Serializing SizeTags to binary
|
||||
template <class Archive, class T> inline
|
||||
CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive)
|
||||
serialize( Archive & ar, SizeTag<T> & t )
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, SizeTag<T> & t )
|
||||
{
|
||||
ar( t.size );
|
||||
}
|
||||
|
||||
//! Saving binary data
|
||||
template <class T> inline
|
||||
void save(BinaryOutputArchive & ar, BinaryData<T> const & bd)
|
||||
void CEREAL_SAVE_FUNCTION_NAME(BinaryOutputArchive & ar, BinaryData<T> const & bd)
|
||||
{
|
||||
ar.saveBinary( bd.data, static_cast<std::size_t>( bd.size ) );
|
||||
}
|
||||
|
||||
//! Loading binary data
|
||||
template <class T> inline
|
||||
void load(BinaryInputArchive & ar, BinaryData<T> & bd)
|
||||
void CEREAL_LOAD_FUNCTION_NAME(BinaryInputArchive & ar, BinaryData<T> & bd)
|
||||
{
|
||||
ar.loadBinary(bd.data, static_cast<std::size_t>(bd.size));
|
||||
}
|
||||
|
@ -159,4 +159,7 @@ namespace cereal
|
|||
CEREAL_REGISTER_ARCHIVE(cereal::BinaryOutputArchive)
|
||||
CEREAL_REGISTER_ARCHIVE(cereal::BinaryInputArchive)
|
||||
|
||||
// tie input and output archives together
|
||||
CEREAL_SETUP_ARCHIVE_TRAITS(cereal::BinaryInputArchive, cereal::BinaryOutputArchive)
|
||||
|
||||
#endif // CEREAL_ARCHIVES_BINARY_HPP_
|
||||
|
|
|
@ -85,7 +85,7 @@ namespace cereal
|
|||
that the container is variable sized and may be edited.
|
||||
|
||||
\ingroup Archives */
|
||||
class JSONOutputArchive : public OutputArchive<JSONOutputArchive>
|
||||
class JSONOutputArchive : public OutputArchive<JSONOutputArchive>, public traits::TextArchive
|
||||
{
|
||||
enum class NodeType { StartObject, InObject, StartArray, InArray };
|
||||
|
||||
|
@ -153,7 +153,8 @@ namespace cereal
|
|||
//! Destructor, flushes the JSON
|
||||
~JSONOutputArchive()
|
||||
{
|
||||
itsWriter.EndObject();
|
||||
if (itsNodeStack.top() == NodeType::InObject)
|
||||
itsWriter.EndObject();
|
||||
}
|
||||
|
||||
//! Saves some binary data, encoded as a base64 string, with an optional name
|
||||
|
@ -240,24 +241,24 @@ namespace cereal
|
|||
// special overloads to handle these cases.
|
||||
|
||||
//! 32 bit signed long saving to current node
|
||||
template <class T> inline
|
||||
typename std::enable_if<sizeof(T) == sizeof(std::int32_t) && std::is_signed<T>::value, void>::type
|
||||
saveLong(T l){ saveValue( static_cast<std::int32_t>( l ) ); }
|
||||
template <class T, traits::EnableIf<sizeof(T) == sizeof(std::int32_t),
|
||||
std::is_signed<T>::value> = traits::sfinae> inline
|
||||
void saveLong(T l){ saveValue( static_cast<std::int32_t>( l ) ); }
|
||||
|
||||
//! non 32 bit signed long saving to current node
|
||||
template <class T> inline
|
||||
typename std::enable_if<sizeof(T) != sizeof(std::int32_t) && std::is_signed<T>::value, void>::type
|
||||
saveLong(T l){ saveValue( static_cast<std::int64_t>( l ) ); }
|
||||
template <class T, traits::EnableIf<sizeof(T) != sizeof(std::int32_t),
|
||||
std::is_signed<T>::value> = traits::sfinae> inline
|
||||
void saveLong(T l){ saveValue( static_cast<std::int64_t>( l ) ); }
|
||||
|
||||
//! 32 bit unsigned long saving to current node
|
||||
template <class T> inline
|
||||
typename std::enable_if<sizeof(T) == sizeof(std::uint32_t) && !std::is_signed<T>::value, void>::type
|
||||
saveLong(T lu){ saveValue( static_cast<std::uint32_t>( lu ) ); }
|
||||
template <class T, traits::EnableIf<sizeof(T) == sizeof(std::int32_t),
|
||||
std::is_unsigned<T>::value> = traits::sfinae> inline
|
||||
void saveLong(T lu){ saveValue( static_cast<std::uint32_t>( lu ) ); }
|
||||
|
||||
//! non 32 bit unsigned long saving to current node
|
||||
template <class T> inline
|
||||
typename std::enable_if<sizeof(T) != sizeof(std::uint32_t) && !std::is_signed<T>::value, void>::type
|
||||
saveLong(T lu){ saveValue( static_cast<std::uint64_t>( lu ) ); }
|
||||
template <class T, traits::EnableIf<sizeof(T) != sizeof(std::int32_t),
|
||||
std::is_unsigned<T>::value> = traits::sfinae> inline
|
||||
void saveLong(T lu){ saveValue( static_cast<std::uint64_t>( lu ) ); }
|
||||
|
||||
public:
|
||||
#ifdef _MSC_VER
|
||||
|
@ -265,30 +266,27 @@ namespace cereal
|
|||
void saveValue( unsigned long lu ){ saveLong( lu ); };
|
||||
#else // _MSC_VER
|
||||
//! Serialize a long if it would not be caught otherwise
|
||||
template <class T> inline
|
||||
typename std::enable_if<std::is_same<T, long>::value &&
|
||||
!std::is_same<T, std::int32_t>::value &&
|
||||
!std::is_same<T, std::int64_t>::value, void>::type
|
||||
saveValue( T t ){ saveLong( t ); }
|
||||
template <class T, traits::EnableIf<std::is_same<T, long>::value,
|
||||
!std::is_same<T, std::int32_t>::value,
|
||||
!std::is_same<T, std::int64_t>::value> = traits::sfinae> inline
|
||||
void saveValue( T t ){ saveLong( t ); }
|
||||
|
||||
//! Serialize an unsigned long if it would not be caught otherwise
|
||||
template <class T> inline
|
||||
typename std::enable_if<std::is_same<T, unsigned long>::value &&
|
||||
!std::is_same<T, std::uint32_t>::value &&
|
||||
!std::is_same<T, std::uint64_t>::value, void>::type
|
||||
saveValue( T t ){ saveLong( t ); }
|
||||
template <class T, traits::EnableIf<std::is_same<T, unsigned long>::value,
|
||||
!std::is_same<T, std::uint32_t>::value,
|
||||
!std::is_same<T, std::uint64_t>::value> = traits::sfinae> inline
|
||||
void saveValue( T t ){ saveLong( t ); }
|
||||
#endif // _MSC_VER
|
||||
|
||||
//! Save exotic arithmetic as strings to current node
|
||||
/*! Handles long long (if distinct from other types), unsigned long (if distinct), and long double */
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value &&
|
||||
!std::is_same<T, long>::value &&
|
||||
!std::is_same<T, unsigned long>::value &&
|
||||
!std::is_same<T, std::int64_t>::value &&
|
||||
!std::is_same<T, std::uint64_t>::value &&
|
||||
(sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long)), void>::type
|
||||
saveValue(T const & t)
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value,
|
||||
!std::is_same<T, long>::value,
|
||||
!std::is_same<T, unsigned long>::value,
|
||||
!std::is_same<T, std::int64_t>::value,
|
||||
!std::is_same<T, std::uint64_t>::value,
|
||||
(sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> inline
|
||||
void saveValue(T const & t)
|
||||
{
|
||||
std::stringstream ss; ss.precision( std::numeric_limits<long double>::max_digits10 );
|
||||
ss << t;
|
||||
|
@ -390,7 +388,7 @@ namespace cereal
|
|||
@endcode
|
||||
|
||||
\ingroup Archives */
|
||||
class JSONInputArchive : public InputArchive<JSONInputArchive>
|
||||
class JSONInputArchive : public InputArchive<JSONInputArchive>, public traits::TextArchive
|
||||
{
|
||||
private:
|
||||
typedef rapidjson::GenericReadStream ReadStream;
|
||||
|
@ -562,6 +560,13 @@ namespace cereal
|
|||
++itsIteratorStack.back();
|
||||
}
|
||||
|
||||
//! Retrieves the current node name
|
||||
/*! @return nullptr if no name exists */
|
||||
const char * getNodeName() const
|
||||
{
|
||||
return itsIteratorStack.back().name();
|
||||
}
|
||||
|
||||
//! Sets the name for the next node created with startNode
|
||||
void setNextName( const char * name )
|
||||
{
|
||||
|
@ -569,9 +574,9 @@ namespace cereal
|
|||
}
|
||||
|
||||
//! Loads a value from the current node - small signed overload
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_signed<T>::value && sizeof(T) < sizeof(int64_t), void>::type
|
||||
loadValue(T & val)
|
||||
template <class T, traits::EnableIf<std::is_signed<T>::value,
|
||||
sizeof(T) < sizeof(int64_t)> = traits::sfinae> inline
|
||||
void loadValue(T & val)
|
||||
{
|
||||
search();
|
||||
|
||||
|
@ -580,10 +585,10 @@ namespace cereal
|
|||
}
|
||||
|
||||
//! Loads a value from the current node - small unsigned overload
|
||||
template<class T> inline
|
||||
typename std::enable_if<(std::is_unsigned<T>::value && sizeof(T) < sizeof(uint64_t)) &&
|
||||
!std::is_same<bool, T>::value, void>::type
|
||||
loadValue(T & val)
|
||||
template <class T, traits::EnableIf<std::is_unsigned<T>::value,
|
||||
sizeof(T) < sizeof(uint64_t),
|
||||
!std::is_same<bool, T>::value> = traits::sfinae> inline
|
||||
void loadValue(T & val)
|
||||
{
|
||||
search();
|
||||
|
||||
|
@ -604,6 +609,46 @@ namespace cereal
|
|||
//! Loads a value from the current node - string overload
|
||||
void loadValue(std::string & val) { search(); val = itsIteratorStack.back().value().GetString(); ++itsIteratorStack.back(); }
|
||||
|
||||
// Special cases to handle various flavors of long, which tend to conflict with
|
||||
// the int32_t or int64_t on various compiler/OS combinations. MSVC doesn't need any of this.
|
||||
#ifndef _MSC_VER
|
||||
private:
|
||||
//! 32 bit signed long loading from current node
|
||||
template <class T> inline
|
||||
typename std::enable_if<sizeof(T) == sizeof(std::int32_t) && std::is_signed<T>::value, void>::type
|
||||
loadLong(T & l){ loadValue( reinterpret_cast<std::int32_t&>( l ) ); }
|
||||
|
||||
//! non 32 bit signed long loading from current node
|
||||
template <class T> inline
|
||||
typename std::enable_if<sizeof(T) == sizeof(std::int64_t) && std::is_signed<T>::value, void>::type
|
||||
loadLong(T & l){ loadValue( reinterpret_cast<std::int64_t&>( l ) ); }
|
||||
|
||||
//! 32 bit unsigned long loading from current node
|
||||
template <class T> inline
|
||||
typename std::enable_if<sizeof(T) == sizeof(std::uint32_t) && !std::is_signed<T>::value, void>::type
|
||||
loadLong(T & lu){ loadValue( reinterpret_cast<std::uint32_t&>( lu ) ); }
|
||||
|
||||
//! non 32 bit unsigned long loading from current node
|
||||
template <class T> inline
|
||||
typename std::enable_if<sizeof(T) == sizeof(std::uint64_t) && !std::is_signed<T>::value, void>::type
|
||||
loadLong(T & lu){ loadValue( reinterpret_cast<std::uint64_t&>( lu ) ); }
|
||||
|
||||
public:
|
||||
//! Serialize a long if it would not be caught otherwise
|
||||
template <class T> inline
|
||||
typename std::enable_if<std::is_same<T, long>::value &&
|
||||
!std::is_same<T, std::int32_t>::value &&
|
||||
!std::is_same<T, std::int64_t>::value, void>::type
|
||||
loadValue( T & t ){ loadLong(t); }
|
||||
|
||||
//! Serialize an unsigned long if it would not be caught otherwise
|
||||
template <class T> inline
|
||||
typename std::enable_if<std::is_same<T, unsigned long>::value &&
|
||||
!std::is_same<T, std::uint32_t>::value &&
|
||||
!std::is_same<T, std::uint64_t>::value, void>::type
|
||||
loadValue( T & t ){ loadLong(t); }
|
||||
#endif // _MSC_VER
|
||||
|
||||
private:
|
||||
//! Convert a string to a long long
|
||||
void stringToNumber( std::string const & str, long long & val ) { val = std::stoll( str ); }
|
||||
|
@ -614,14 +659,13 @@ namespace cereal
|
|||
|
||||
public:
|
||||
//! Loads a value from the current node - long double and long long overloads
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value &&
|
||||
!std::is_same<T, long>::value &&
|
||||
!std::is_same<T, unsigned long>::value &&
|
||||
!std::is_same<T, std::int64_t>::value &&
|
||||
!std::is_same<T, std::uint64_t>::value &&
|
||||
(sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long)), void>::type
|
||||
loadValue(T & val)
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value,
|
||||
!std::is_same<T, long>::value,
|
||||
!std::is_same<T, unsigned long>::value,
|
||||
!std::is_same<T, std::int64_t>::value,
|
||||
!std::is_same<T, std::uint64_t>::value,
|
||||
(sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae>
|
||||
inline void loadValue(T & val)
|
||||
{
|
||||
std::string encoded;
|
||||
loadValue( encoded );
|
||||
|
@ -705,19 +749,19 @@ namespace cereal
|
|||
that may be given data by the type about to be archived
|
||||
|
||||
Minimal types do not start or finish nodes */
|
||||
template <class T> inline
|
||||
typename std::enable_if<!std::is_arithmetic<T>::value &&
|
||||
!traits::has_minimal_output_serialization<T, JSONOutputArchive>::value, void>::type
|
||||
prologue( JSONOutputArchive & ar, T const & )
|
||||
template <class T, traits::DisableIf<std::is_arithmetic<T>::value ||
|
||||
traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, JSONOutputArchive>::value ||
|
||||
traits::has_minimal_output_serialization<T, JSONOutputArchive>::value> = traits::sfinae>
|
||||
inline void prologue( JSONOutputArchive & ar, T const & )
|
||||
{
|
||||
ar.startNode();
|
||||
}
|
||||
|
||||
//! Prologue for all other types for JSON archives
|
||||
template <class T> inline
|
||||
typename std::enable_if<!std::is_arithmetic<T>::value &&
|
||||
!traits::has_minimal_input_serialization<T, JSONOutputArchive>::value, void>::type
|
||||
prologue( JSONInputArchive & ar, T const & )
|
||||
template <class T, traits::DisableIf<std::is_arithmetic<T>::value ||
|
||||
traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, JSONInputArchive>::value ||
|
||||
traits::has_minimal_input_serialization<T, JSONInputArchive>::value> = traits::sfinae>
|
||||
inline void prologue( JSONInputArchive & ar, T const & )
|
||||
{
|
||||
ar.startNode();
|
||||
}
|
||||
|
@ -727,49 +771,45 @@ namespace cereal
|
|||
/*! Finishes the node created in the prologue
|
||||
|
||||
Minimal types do not start or finish nodes */
|
||||
template <class T> inline
|
||||
typename std::enable_if<!std::is_arithmetic<T>::value &&
|
||||
!traits::has_minimal_output_serialization<T, JSONOutputArchive>::value, void>::type
|
||||
epilogue( JSONOutputArchive & ar, T const & )
|
||||
template <class T, traits::DisableIf<std::is_arithmetic<T>::value ||
|
||||
traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, JSONOutputArchive>::value ||
|
||||
traits::has_minimal_output_serialization<T, JSONOutputArchive>::value> = traits::sfinae>
|
||||
inline void epilogue( JSONOutputArchive & ar, T const & )
|
||||
{
|
||||
ar.finishNode();
|
||||
}
|
||||
|
||||
//! Epilogue for all other types other for JSON archives
|
||||
template <class T> inline
|
||||
typename std::enable_if<!std::is_arithmetic<T>::value &&
|
||||
!traits::has_minimal_input_serialization<T, JSONOutputArchive>::value, void>::type
|
||||
epilogue( JSONInputArchive & ar, T const & )
|
||||
template <class T, traits::DisableIf<std::is_arithmetic<T>::value ||
|
||||
traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, JSONInputArchive>::value ||
|
||||
traits::has_minimal_input_serialization<T, JSONInputArchive>::value> = traits::sfinae>
|
||||
inline void epilogue( JSONInputArchive & ar, T const & )
|
||||
{
|
||||
ar.finishNode();
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
//! Prologue for arithmetic types for JSON archives
|
||||
template <class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
prologue( JSONOutputArchive & ar, T const & )
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
|
||||
void prologue( JSONOutputArchive & ar, T const & )
|
||||
{
|
||||
ar.writeName();
|
||||
}
|
||||
|
||||
//! Prologue for arithmetic types for JSON archives
|
||||
template <class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
prologue( JSONInputArchive &, T const & )
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
|
||||
void prologue( JSONInputArchive &, T const & )
|
||||
{ }
|
||||
|
||||
// ######################################################################
|
||||
//! Epilogue for arithmetic types for JSON archives
|
||||
template <class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
epilogue( JSONOutputArchive &, T const & )
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
|
||||
void epilogue( JSONOutputArchive &, T const & )
|
||||
{ }
|
||||
|
||||
//! Epilogue for arithmetic types for JSON archives
|
||||
template <class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
epilogue( JSONInputArchive &, T const & )
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
|
||||
void epilogue( JSONInputArchive &, T const & )
|
||||
{ }
|
||||
|
||||
// ######################################################################
|
||||
|
@ -799,48 +839,45 @@ namespace cereal
|
|||
// ######################################################################
|
||||
// Common JSONArchive serialization functions
|
||||
// ######################################################################
|
||||
|
||||
//! Serializing NVP types to JSON
|
||||
template <class T> inline
|
||||
void save( JSONOutputArchive & ar, NameValuePair<T> const & t )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( JSONOutputArchive & ar, NameValuePair<T> const & t )
|
||||
{
|
||||
ar.setNextName( t.name );
|
||||
ar( t.value );
|
||||
}
|
||||
|
||||
template <class T> inline
|
||||
void load( JSONInputArchive & ar, NameValuePair<T> & t )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( JSONInputArchive & ar, NameValuePair<T> & t )
|
||||
{
|
||||
ar.setNextName( t.name );
|
||||
ar( t.value );
|
||||
}
|
||||
|
||||
//! Saving for arithmetic to JSON
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
save(JSONOutputArchive & ar, T const & t)
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, T const & t)
|
||||
{
|
||||
ar.saveValue( t );
|
||||
}
|
||||
|
||||
//! Loading arithmetic from JSON
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
load(JSONInputArchive & ar, T & t)
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, T & t)
|
||||
{
|
||||
ar.loadValue( t );
|
||||
}
|
||||
|
||||
//! saving string to JSON
|
||||
template<class CharT, class Traits, class Alloc> inline
|
||||
void save(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
|
||||
void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
|
||||
{
|
||||
ar.saveValue( str );
|
||||
}
|
||||
|
||||
//! loading string from JSON
|
||||
template<class CharT, class Traits, class Alloc> inline
|
||||
void load(JSONInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
|
||||
void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
|
||||
{
|
||||
ar.loadValue( str );
|
||||
}
|
||||
|
@ -848,14 +885,14 @@ namespace cereal
|
|||
// ######################################################################
|
||||
//! Saving SizeTags to JSON
|
||||
template <class T> inline
|
||||
void save( JSONOutputArchive &, SizeTag<T> const & )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( JSONOutputArchive &, SizeTag<T> const & )
|
||||
{
|
||||
// nothing to do here, we don't explicitly save the size
|
||||
}
|
||||
|
||||
//! Loading SizeTags from JSON
|
||||
template <class T> inline
|
||||
void load( JSONInputArchive & ar, SizeTag<T> & st )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( JSONInputArchive & ar, SizeTag<T> & st )
|
||||
{
|
||||
ar.loadSize( st.size );
|
||||
}
|
||||
|
@ -865,4 +902,7 @@ namespace cereal
|
|||
CEREAL_REGISTER_ARCHIVE(cereal::JSONInputArchive)
|
||||
CEREAL_REGISTER_ARCHIVE(cereal::JSONOutputArchive)
|
||||
|
||||
// tie input and output archives together
|
||||
CEREAL_SETUP_ARCHIVE_TRAITS(cereal::JSONInputArchive, cereal::JSONOutputArchive)
|
||||
|
||||
#endif // CEREAL_ARCHIVES_JSON_HPP_
|
||||
|
|
|
@ -175,7 +175,7 @@ namespace cereal
|
|||
//! Saving for POD types to portable binary
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
save(PortableBinaryOutputArchive & ar, T const & t)
|
||||
CEREAL_SAVE_FUNCTION_NAME(PortableBinaryOutputArchive & ar, T const & t)
|
||||
{
|
||||
static_assert( !std::is_floating_point<T>::value ||
|
||||
(std::is_floating_point<T>::value && std::numeric_limits<T>::is_iec559),
|
||||
|
@ -186,7 +186,7 @@ namespace cereal
|
|||
//! Loading for POD types from portable binary
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
load(PortableBinaryInputArchive & ar, T & t)
|
||||
CEREAL_LOAD_FUNCTION_NAME(PortableBinaryInputArchive & ar, T & t)
|
||||
{
|
||||
static_assert( !std::is_floating_point<T>::value ||
|
||||
(std::is_floating_point<T>::value && std::numeric_limits<T>::is_iec559),
|
||||
|
@ -197,7 +197,7 @@ namespace cereal
|
|||
//! Serializing NVP types to portable binary
|
||||
template <class Archive, class T> inline
|
||||
CEREAL_ARCHIVE_RESTRICT(PortableBinaryInputArchive, PortableBinaryOutputArchive)
|
||||
serialize( Archive & ar, NameValuePair<T> & t )
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, NameValuePair<T> & t )
|
||||
{
|
||||
ar( t.value );
|
||||
}
|
||||
|
@ -205,14 +205,14 @@ namespace cereal
|
|||
//! Serializing SizeTags to portable binary
|
||||
template <class Archive, class T> inline
|
||||
CEREAL_ARCHIVE_RESTRICT(PortableBinaryInputArchive, PortableBinaryOutputArchive)
|
||||
serialize( Archive & ar, SizeTag<T> & t )
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, SizeTag<T> & t )
|
||||
{
|
||||
ar( t.size );
|
||||
}
|
||||
|
||||
//! Saving binary data to portable binary
|
||||
template <class T> inline
|
||||
void save(PortableBinaryOutputArchive & ar, BinaryData<T> const & bd)
|
||||
void CEREAL_SAVE_FUNCTION_NAME(PortableBinaryOutputArchive & ar, BinaryData<T> const & bd)
|
||||
{
|
||||
typedef typename std::remove_pointer<T>::type TT;
|
||||
static_assert( !std::is_floating_point<TT>::value ||
|
||||
|
@ -224,7 +224,7 @@ namespace cereal
|
|||
|
||||
//! Loading binary data from portable binary
|
||||
template <class T> inline
|
||||
void load(PortableBinaryInputArchive & ar, BinaryData<T> & bd)
|
||||
void CEREAL_LOAD_FUNCTION_NAME(PortableBinaryInputArchive & ar, BinaryData<T> & bd)
|
||||
{
|
||||
typedef typename std::remove_pointer<T>::type TT;
|
||||
static_assert( !std::is_floating_point<TT>::value ||
|
||||
|
@ -239,4 +239,7 @@ namespace cereal
|
|||
CEREAL_REGISTER_ARCHIVE(cereal::PortableBinaryOutputArchive)
|
||||
CEREAL_REGISTER_ARCHIVE(cereal::PortableBinaryInputArchive)
|
||||
|
||||
// tie input and output archives together
|
||||
CEREAL_SETUP_ARCHIVE_TRAITS(cereal::PortableBinaryInputArchive, cereal::PortableBinaryOutputArchive)
|
||||
|
||||
#endif // CEREAL_ARCHIVES_PORTABLE_BINARY_HPP_
|
||||
|
|
|
@ -56,6 +56,12 @@ namespace cereal
|
|||
|
||||
//! The name given to the root node in a cereal xml archive
|
||||
static const char * CEREAL_XML_STRING = CEREAL_XML_STRING_VALUE;
|
||||
|
||||
//! Returns true if the character is whitespace
|
||||
inline bool isWhitespace( char c )
|
||||
{
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
|
||||
}
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
|
@ -87,7 +93,7 @@ namespace cereal
|
|||
is accomplished through the cereal::SizeTag object, which will also add an attribute
|
||||
to its parent field.
|
||||
\ingroup Archives */
|
||||
class XMLOutputArchive : public OutputArchive<XMLOutputArchive>
|
||||
class XMLOutputArchive : public OutputArchive<XMLOutputArchive>, public traits::TextArchive
|
||||
{
|
||||
public:
|
||||
/*! @name Common Functionality
|
||||
|
@ -196,7 +202,7 @@ namespace cereal
|
|||
const auto nameString = itsNodes.top().getValueName();
|
||||
|
||||
// allocate strings for all of the data in the XML object
|
||||
auto namePtr = itsXML.allocate_string( nameString.data(), nameString.size() );
|
||||
auto namePtr = itsXML.allocate_string( nameString.data(), nameString.length() + 1 );
|
||||
|
||||
// insert into the XML
|
||||
auto node = itsXML.allocate_node( rapidxml::node_element, namePtr, nullptr, nameString.size() );
|
||||
|
@ -226,8 +232,16 @@ namespace cereal
|
|||
itsOS.clear(); itsOS.seekp( 0, std::ios::beg );
|
||||
itsOS << value << std::ends;
|
||||
|
||||
const auto strValue = itsOS.str();
|
||||
// if there is the first or the last character in string is whitespace then add xml:space attribute
|
||||
// the last character has index length-2 because there is \0 character at end added with std::ends
|
||||
if( !strValue.empty() && ( xml_detail::isWhitespace( strValue[0] ) || xml_detail::isWhitespace( strValue[strValue.length() - 2] ) ) )
|
||||
{
|
||||
itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "xml:space", "preserve" ) );
|
||||
}
|
||||
|
||||
// allocate strings for all of the data in the XML object
|
||||
auto dataPtr = itsXML.allocate_string( itsOS.str().c_str() );
|
||||
auto dataPtr = itsXML.allocate_string( itsOS.str().c_str(), itsOS.str().length() + 1 );
|
||||
|
||||
// insert into the XML
|
||||
itsNodes.top().node->append_node( itsXML.allocate_node( rapidxml::node_data, nullptr, dataPtr ) );
|
||||
|
@ -256,7 +270,7 @@ namespace cereal
|
|||
const auto nameString = util::demangledName<T>();
|
||||
|
||||
// allocate strings for all of the data in the XML object
|
||||
auto namePtr = itsXML.allocate_string( nameString.data(), nameString.size() );
|
||||
auto namePtr = itsXML.allocate_string( nameString.data(), nameString.length() + 1 );
|
||||
|
||||
itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "type", namePtr ) );
|
||||
}
|
||||
|
@ -348,7 +362,7 @@ namespace cereal
|
|||
@endcode
|
||||
|
||||
\ingroup Archives */
|
||||
class XMLInputArchive : public InputArchive<XMLInputArchive>
|
||||
class XMLInputArchive : public InputArchive<XMLInputArchive>, public traits::TextArchive
|
||||
{
|
||||
public:
|
||||
/*! @name Common Functionality
|
||||
|
@ -367,7 +381,7 @@ namespace cereal
|
|||
try
|
||||
{
|
||||
itsData.push_back('\0'); // rapidxml will do terrible things without the data being null terminated
|
||||
itsXML.parse<rapidxml::parse_no_data_nodes | rapidxml::parse_declaration_node>( reinterpret_cast<char *>( itsData.data() ) );
|
||||
itsXML.parse<rapidxml::parse_trim_whitespace | rapidxml::parse_no_data_nodes | rapidxml::parse_declaration_node>( reinterpret_cast<char *>( itsData.data() ) );
|
||||
}
|
||||
catch( rapidxml::parse_error const & )
|
||||
{
|
||||
|
@ -461,6 +475,13 @@ namespace cereal
|
|||
itsNodes.top().name = nullptr;
|
||||
}
|
||||
|
||||
//! Retrieves the current node name
|
||||
//! will return @c nullptr if the node does not have a name
|
||||
const char * getNodeName() const
|
||||
{
|
||||
return itsNodes.top().node->name();
|
||||
}
|
||||
|
||||
//! Sets the name for the next node created with startNode
|
||||
void setNextName( const char * name )
|
||||
{
|
||||
|
@ -468,51 +489,78 @@ namespace cereal
|
|||
}
|
||||
|
||||
//! Loads a bool from the current top node
|
||||
template <class T> inline
|
||||
typename std::enable_if<std::is_unsigned<T>::value && std::is_same<T, bool>::value, void>::type
|
||||
loadValue( T & value )
|
||||
template <class T, traits::EnableIf<std::is_unsigned<T>::value,
|
||||
std::is_same<T, bool>::value> = traits::sfinae> inline
|
||||
void loadValue( T & value )
|
||||
{
|
||||
std::istringstream is( itsNodes.top().node->value() );
|
||||
is.setf( std::ios::boolalpha );
|
||||
is >> value;
|
||||
}
|
||||
|
||||
//! Loads a char (signed or unsigned) from the current top node
|
||||
template <class T, traits::EnableIf<std::is_integral<T>::value,
|
||||
!std::is_same<T, bool>::value,
|
||||
sizeof(T) == sizeof(char)> = traits::sfinae> inline
|
||||
void loadValue( T & value )
|
||||
{
|
||||
value = *reinterpret_cast<T*>( itsNodes.top().node->value() );
|
||||
}
|
||||
|
||||
//! Load an int8_t from the current top node (ensures we parse entire number)
|
||||
void loadValue( int8_t & value )
|
||||
{
|
||||
int32_t val; loadValue( val ); value = val;
|
||||
}
|
||||
|
||||
//! Load a uint8_t from the current top node (ensures we parse entire number)
|
||||
void loadValue( uint8_t & value )
|
||||
{
|
||||
uint32_t val; loadValue( val ); value = val;
|
||||
}
|
||||
|
||||
//! Loads a type best represented as an unsigned long from the current top node
|
||||
template <class T> inline
|
||||
typename std::enable_if<std::is_unsigned<T>::value && !std::is_same<T, bool>::value && sizeof(T) < sizeof(long long), void>::type
|
||||
loadValue( T & value )
|
||||
template <class T, traits::EnableIf<std::is_unsigned<T>::value,
|
||||
!std::is_same<T, bool>::value,
|
||||
!std::is_same<T, unsigned char>::value,
|
||||
sizeof(T) < sizeof(long long)> = traits::sfinae> inline
|
||||
void loadValue( T & value )
|
||||
{
|
||||
value = static_cast<T>( std::stoul( itsNodes.top().node->value() ) );
|
||||
}
|
||||
|
||||
//! Loads a type best represented as an unsigned long long from the current top node
|
||||
template <class T> inline
|
||||
typename std::enable_if<std::is_unsigned<T>::value && !std::is_same<T, bool>::value && sizeof(T) >= sizeof(long long), void>::type
|
||||
loadValue( T & value )
|
||||
template <class T, traits::EnableIf<std::is_unsigned<T>::value,
|
||||
!std::is_same<T, bool>::value,
|
||||
sizeof(T) >= sizeof(long long)> = traits::sfinae> inline
|
||||
void loadValue( T & value )
|
||||
{
|
||||
value = static_cast<T>( std::stoull( itsNodes.top().node->value() ) );
|
||||
}
|
||||
|
||||
//! Loads a type best represented as an int from the current top node
|
||||
template <class T> inline
|
||||
typename std::enable_if<std::is_signed<T>::value && sizeof(T) <= sizeof(int), void>::type
|
||||
loadValue( T & value )
|
||||
template <class T, traits::EnableIf<std::is_signed<T>::value,
|
||||
!std::is_same<T, char>::value,
|
||||
sizeof(T) <= sizeof(int)> = traits::sfinae> inline
|
||||
void loadValue( T & value )
|
||||
{
|
||||
value = static_cast<T>( std::stoi( itsNodes.top().node->value() ) );
|
||||
}
|
||||
|
||||
//! Loads a type best represented as a long from the current top node
|
||||
template <class T> inline
|
||||
typename std::enable_if<std::is_signed<T>::value && (sizeof(T) > sizeof(int)) && (sizeof(T) <= sizeof(long)), void>::type
|
||||
loadValue( T & value )
|
||||
template <class T, traits::EnableIf<std::is_signed<T>::value,
|
||||
(sizeof(T) > sizeof(int)),
|
||||
sizeof(T) <= sizeof(long)> = traits::sfinae> inline
|
||||
void loadValue( T & value )
|
||||
{
|
||||
value = static_cast<T>( std::stol( itsNodes.top().node->value() ) );
|
||||
}
|
||||
|
||||
//! Loads a type best represented as a long long from the current top node
|
||||
template <class T> inline
|
||||
typename std::enable_if<std::is_signed<T>::value && (sizeof(T) > sizeof(long)) && (sizeof(T) <= sizeof(long long)), void>::type
|
||||
loadValue( T & value )
|
||||
template <class T, traits::EnableIf<std::is_signed<T>::value,
|
||||
(sizeof(T) > sizeof(long)),
|
||||
sizeof(T) <= sizeof(long long)> = traits::sfinae> inline
|
||||
void loadValue( T & value )
|
||||
{
|
||||
value = static_cast<T>( std::stoll( itsNodes.top().node->value() ) );
|
||||
}
|
||||
|
@ -721,18 +769,18 @@ namespace cereal
|
|||
that may be given data by the type about to be archived
|
||||
|
||||
Minimal types do not start or end nodes */
|
||||
template <class T> inline
|
||||
typename std::enable_if<!traits::has_minimal_output_serialization<T, XMLOutputArchive>::value, void>::type
|
||||
prologue( XMLOutputArchive & ar, T const & )
|
||||
template <class T, traits::DisableIf<traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, XMLOutputArchive>::value ||
|
||||
traits::has_minimal_output_serialization<T, XMLOutputArchive>::value> = traits::sfinae> inline
|
||||
void prologue( XMLOutputArchive & ar, T const & )
|
||||
{
|
||||
ar.startNode();
|
||||
ar.insertType<T>();
|
||||
}
|
||||
|
||||
//! Prologue for all other types for XML input archives (except minimal types)
|
||||
template <class T> inline
|
||||
typename std::enable_if<!traits::has_minimal_input_serialization<T, XMLInputArchive>::value, void>::type
|
||||
prologue( XMLInputArchive & ar, T const & )
|
||||
template <class T, traits::DisableIf<traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, XMLInputArchive>::value ||
|
||||
traits::has_minimal_input_serialization<T, XMLInputArchive>::value> = traits::sfinae> inline
|
||||
void prologue( XMLInputArchive & ar, T const & )
|
||||
{
|
||||
ar.startNode();
|
||||
}
|
||||
|
@ -742,17 +790,17 @@ namespace cereal
|
|||
/*! Finishes the node created in the prologue
|
||||
|
||||
Minimal types do not start or end nodes */
|
||||
template <class T> inline
|
||||
typename std::enable_if<!traits::has_minimal_output_serialization<T, XMLOutputArchive>::value, void>::type
|
||||
epilogue( XMLOutputArchive & ar, T const & )
|
||||
template <class T, traits::DisableIf<traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, XMLOutputArchive>::value ||
|
||||
traits::has_minimal_output_serialization<T, XMLOutputArchive>::value> = traits::sfinae> inline
|
||||
void epilogue( XMLOutputArchive & ar, T const & )
|
||||
{
|
||||
ar.finishNode();
|
||||
}
|
||||
|
||||
//! Epilogue for all other types other for XML output archives (except minimal types)
|
||||
template <class T> inline
|
||||
typename std::enable_if<!traits::has_minimal_input_serialization<T, XMLInputArchive>::value, void>::type
|
||||
epilogue( XMLInputArchive & ar, T const & )
|
||||
template <class T, traits::DisableIf<traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, XMLInputArchive>::value ||
|
||||
traits::has_minimal_input_serialization<T, XMLInputArchive>::value> = traits::sfinae> inline
|
||||
void epilogue( XMLInputArchive & ar, T const & )
|
||||
{
|
||||
ar.finishNode();
|
||||
}
|
||||
|
@ -763,7 +811,7 @@ namespace cereal
|
|||
|
||||
//! Saving NVP types to XML
|
||||
template <class T> inline
|
||||
void save( XMLOutputArchive & ar, NameValuePair<T> const & t )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( XMLOutputArchive & ar, NameValuePair<T> const & t )
|
||||
{
|
||||
ar.setNextName( t.name );
|
||||
ar( t.value );
|
||||
|
@ -771,7 +819,7 @@ namespace cereal
|
|||
|
||||
//! Loading NVP types from XML
|
||||
template <class T> inline
|
||||
void load( XMLInputArchive & ar, NameValuePair<T> & t )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( XMLInputArchive & ar, NameValuePair<T> & t )
|
||||
{
|
||||
ar.setNextName( t.name );
|
||||
ar( t.value );
|
||||
|
@ -780,29 +828,27 @@ namespace cereal
|
|||
// ######################################################################
|
||||
//! Saving SizeTags to XML
|
||||
template <class T> inline
|
||||
void save( XMLOutputArchive &, SizeTag<T> const & )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( XMLOutputArchive &, SizeTag<T> const & )
|
||||
{ }
|
||||
|
||||
//! Loading SizeTags from XML
|
||||
template <class T> inline
|
||||
void load( XMLInputArchive & ar, SizeTag<T> & st )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( XMLInputArchive & ar, SizeTag<T> & st )
|
||||
{
|
||||
ar.loadSize( st.size );
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
//! Saving for POD types to xml
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
save(XMLOutputArchive & ar, T const & t)
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME(XMLOutputArchive & ar, T const & t)
|
||||
{
|
||||
ar.saveValue( t );
|
||||
}
|
||||
|
||||
//! Loading for POD types from xml
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
load(XMLInputArchive & ar, T & t)
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME(XMLInputArchive & ar, T & t)
|
||||
{
|
||||
ar.loadValue( t );
|
||||
}
|
||||
|
@ -810,14 +856,14 @@ namespace cereal
|
|||
// ######################################################################
|
||||
//! saving string to xml
|
||||
template<class CharT, class Traits, class Alloc> inline
|
||||
void save(XMLOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
|
||||
void CEREAL_SAVE_FUNCTION_NAME(XMLOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
|
||||
{
|
||||
ar.saveValue( str );
|
||||
}
|
||||
|
||||
//! loading string from xml
|
||||
template<class CharT, class Traits, class Alloc> inline
|
||||
void load(XMLInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
|
||||
void CEREAL_LOAD_FUNCTION_NAME(XMLInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
|
||||
{
|
||||
ar.loadValue( str );
|
||||
}
|
||||
|
@ -827,4 +873,7 @@ namespace cereal
|
|||
CEREAL_REGISTER_ARCHIVE(cereal::XMLOutputArchive)
|
||||
CEREAL_REGISTER_ARCHIVE(cereal::XMLInputArchive)
|
||||
|
||||
// tie input and output archives together
|
||||
CEREAL_SETUP_ARCHIVE_TRAITS(cereal::XMLInputArchive, cereal::XMLOutputArchive)
|
||||
|
||||
#endif // CEREAL_ARCHIVES_XML_HPP_
|
||||
|
|
|
@ -39,9 +39,10 @@
|
|||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
#include "./details/traits.hpp"
|
||||
#include "./details/helpers.hpp"
|
||||
#include "./types/base_class.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "details/traits.hpp"
|
||||
#include "details/helpers.hpp"
|
||||
#include "types/base_class.hpp"
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
|
@ -137,13 +138,14 @@ namespace cereal
|
|||
support pointers to polymorphic data types. All archives that
|
||||
come with cereal are already registered.
|
||||
@ingroup Internal */
|
||||
#define CEREAL_REGISTER_ARCHIVE(Archive) \
|
||||
namespace cereal { namespace detail { \
|
||||
template <class T> \
|
||||
typename polymorphic_serialization_support<Archive, T>::type \
|
||||
instantiate_polymorphic_binding( T*, Archive*, adl_tag ); \
|
||||
} } // end namespaces
|
||||
#define CEREAL_REGISTER_ARCHIVE(Archive) \
|
||||
namespace cereal { namespace detail { \
|
||||
template <class T, class BindingTag> \
|
||||
typename polymorphic_serialization_support<Archive, T>::type \
|
||||
instantiate_polymorphic_binding( T*, Archive*, BindingTag, adl_tag ); \
|
||||
} } /* end namespaces */
|
||||
|
||||
// ######################################################################
|
||||
//! Defines a class version for some type
|
||||
/*! Versioning information is optional and adds some small amount of
|
||||
overhead to serialization. This overhead will occur both in terms of
|
||||
|
@ -167,7 +169,9 @@ namespace cereal
|
|||
automatically.
|
||||
|
||||
Versioning cannot be mixed with non-versioned serialization functions.
|
||||
Having both types will result result in a compile time error.
|
||||
Having both types will result result in a compile time error. Data
|
||||
serialized without versioning cannot be loaded by a serialization
|
||||
function with added versioning support.
|
||||
|
||||
Example interface for versioning on a non-member serialize function:
|
||||
|
||||
|
@ -196,18 +200,20 @@ namespace cereal
|
|||
namespace cereal { namespace detail { \
|
||||
template <> struct Version<TYPE> \
|
||||
{ \
|
||||
static const std::uint32_t version = VERSION_NUMBER; \
|
||||
static Version<TYPE> registerVersion() \
|
||||
static const std::uint32_t version; \
|
||||
static std::uint32_t registerVersion() \
|
||||
{ \
|
||||
::cereal::detail::StaticObject<Versions>::getInstance().mapping.emplace( \
|
||||
std::type_index(typeid(TYPE)).hash_code(), VERSION_NUMBER ); \
|
||||
return {}; \
|
||||
return VERSION_NUMBER; \
|
||||
} \
|
||||
static void unused() { (void)version; } \
|
||||
}; /* end Version */ \
|
||||
static const auto CEREAL_CLASS_VERSION_REGISTER##TYPE##VERSION_NUMBER = \
|
||||
const std::uint32_t Version<TYPE>::version = \
|
||||
Version<TYPE>::registerVersion(); \
|
||||
} } // end namespaces
|
||||
|
||||
// ######################################################################
|
||||
//! The base output archive class
|
||||
/*! This is the base output archive for all output archives. If you create
|
||||
a custom archive class, it should derive from this, passing itself as
|
||||
|
@ -357,100 +363,98 @@ namespace cereal
|
|||
return *self;
|
||||
}
|
||||
|
||||
//! Helper macro that expands the requirements for activating an overload
|
||||
#define PROCESS_IF(name) \
|
||||
traits::EnableIf<traits::has_##name<T, ArchiveType>::value, \
|
||||
!traits::has_invalid_output_versioning<T, ArchiveType>::value, \
|
||||
(traits::is_specialized_##name<T, ArchiveType>::value || \
|
||||
traits::is_output_serializable<T, ArchiveType>::value)> = traits::sfinae
|
||||
|
||||
//! Member serialization
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_member_serialize<T, ArchiveType>::value && !traits::has_invalid_output_versioning<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_member_serialize<T, ArchiveType>::value || traits::is_output_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T const & t)
|
||||
template <class T, PROCESS_IF(member_serialize)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
access::member_serialize(*self, const_cast<T &>(t));
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member serialization
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_non_member_serialize<T, ArchiveType>::value && !traits::has_invalid_output_versioning<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_non_member_serialize<T, ArchiveType>::value || traits::is_output_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T const & t)
|
||||
template <class T, PROCESS_IF(non_member_serialize)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
serialize(*self, const_cast<T &>(t));
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast<T &>(t));
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (save)
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_member_save<T, ArchiveType>::value && !traits::has_invalid_output_versioning<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_member_save<T, ArchiveType>::value || traits::is_output_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T const & t)
|
||||
template <class T, PROCESS_IF(member_save)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
access::member_save(*self, t);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member split (save)
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_non_member_save<T, ArchiveType>::value && !traits::has_invalid_output_versioning<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_non_member_save<T, ArchiveType>::value || traits::is_output_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T const & t)
|
||||
template <class T, PROCESS_IF(non_member_save)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
save(*self, t);
|
||||
CEREAL_SAVE_FUNCTION_NAME(*self, t);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (save_minimal)
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_member_save_minimal<T, ArchiveType>::value && !traits::has_invalid_output_versioning<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_member_save_minimal<T, ArchiveType>::value || traits::is_output_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T const & t)
|
||||
template <class T, PROCESS_IF(member_save_minimal)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
self->process( access::member_save_minimal(*self, t) );
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member split (save_minimal)
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_non_member_save_minimal<T, ArchiveType>::value && !traits::has_invalid_output_versioning<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_non_member_save_minimal<T, ArchiveType>::value || traits::is_output_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T const & t)
|
||||
template <class T, PROCESS_IF(non_member_save_minimal)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
self->process( save_minimal(*self, t) );
|
||||
self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t) );
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Empty class specialization
|
||||
template <class T> inline
|
||||
typename std::enable_if<(Flags & AllowEmptyClassElision) &&
|
||||
!traits::is_specialized<T, ArchiveType>::value &&
|
||||
!traits::is_output_serializable<T, ArchiveType>::value && std::is_empty<T>::value, ArchiveType &>::type
|
||||
processImpl(T const &)
|
||||
template <class T, traits::EnableIf<(Flags & AllowEmptyClassElision),
|
||||
!traits::is_specialized<T, ArchiveType>::value,
|
||||
!traits::is_output_serializable<T, ArchiveType>::value,
|
||||
std::is_empty<T>::value> = traits::sfinae> inline
|
||||
ArchiveType & processImpl(T const &)
|
||||
{
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! No matching serialization
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_invalid_output_versioning<T, ArchiveType>::value ||
|
||||
(!traits::is_specialized<T, ArchiveType>::value && !traits::is_output_serializable<T, ArchiveType>::value &&
|
||||
(!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty<T>::value))),
|
||||
ArchiveType &>::type
|
||||
processImpl(T const &)
|
||||
/*! Invalid if we have invalid output versioning or
|
||||
we have no specialization, are not output serializable, and either
|
||||
don't allow empty class ellision or allow it but are not serializing an empty class */
|
||||
template <class T, traits::EnableIf<traits::has_invalid_output_versioning<T, ArchiveType>::value ||
|
||||
(!traits::is_specialized<T, ArchiveType>::value &&
|
||||
!traits::is_output_serializable<T, ArchiveType>::value &&
|
||||
(!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae> inline
|
||||
ArchiveType & processImpl(T const &)
|
||||
{
|
||||
static_assert(traits::is_output_serializable<T, ArchiveType>::value, "Trying to serialize an unserializable type with an output archive. \n\n "
|
||||
static_assert(traits::detail::count_output_serializers<T, ArchiveType>::value != 0,
|
||||
"cereal could not find any output serialization functions for the provided type and archive combination. \n\n "
|
||||
"Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
|
||||
"Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n "
|
||||
"In addition, you may not mix versioned with non-versioned serialization functions. \n "
|
||||
"Serialize functions generally have the following signature: \n\n "
|
||||
"template<class Archive> \n "
|
||||
" void serialize(Archive & ar) \n "
|
||||
" { \n "
|
||||
" ar( member1, member2, member3 ); \n "
|
||||
" } \n\n " );
|
||||
|
||||
static_assert(traits::detail::count_output_serializers<T, ArchiveType>::value < 2,
|
||||
"cereal found more than one compatible output serialization function for the provided type and archive combination. \n\n "
|
||||
"Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
|
||||
"Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n "
|
||||
"Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n "
|
||||
"In addition, you may not mix versioned with non-versioned serialization functions. \n\n ");
|
||||
|
||||
return *self;
|
||||
}
|
||||
|
||||
|
@ -461,92 +465,75 @@ namespace cereal
|
|||
@tparam T The type of the class being serialized
|
||||
@param version The version number associated with it */
|
||||
template <class T> inline
|
||||
void registerClassVersion( const std::uint32_t version )
|
||||
std::uint32_t registerClassVersion()
|
||||
{
|
||||
static const auto hash = std::type_index(typeid(T)).hash_code();
|
||||
const auto insertResult = itsVersionedTypes.insert( hash );
|
||||
const auto version =
|
||||
detail::StaticObject<detail::Versions>::getInstance().find( hash, detail::Version<T>::version );
|
||||
|
||||
if( insertResult.second ) // insertion took place, serialize the version number
|
||||
process( make_nvp<ArchiveType>("cereal_class_version", version) );
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
//! Member serialization
|
||||
/*! Versioning implementation */
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_member_versioned_serialize<T, ArchiveType>::value && !traits::has_invalid_output_versioning<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_member_serialize<T, ArchiveType>::value || traits::is_output_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T const & t)
|
||||
template <class T, PROCESS_IF(member_versioned_serialize)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
registerClassVersion<T>( detail::Version<T>::version );
|
||||
access::member_serialize(*self, const_cast<T &>(t), detail::Version<T>::version);
|
||||
access::member_serialize(*self, const_cast<T &>(t), registerClassVersion<T>());
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member serialization
|
||||
/*! Versioning implementation */
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_non_member_versioned_serialize<T, ArchiveType>::value && !traits::has_invalid_output_versioning<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_non_member_serialize<T, ArchiveType>::value || traits::is_output_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T const & t)
|
||||
template <class T, PROCESS_IF(non_member_versioned_serialize)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
registerClassVersion<T>( detail::Version<T>::version );
|
||||
serialize(*self, const_cast<T &>(t), detail::Version<T>::version);
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast<T &>(t), registerClassVersion<T>());
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (save)
|
||||
/*! Versioning implementation */
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_member_versioned_save<T, ArchiveType>::value && !traits::has_invalid_output_versioning<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_member_save<T, ArchiveType>::value || traits::is_output_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T const & t)
|
||||
template <class T, PROCESS_IF(member_versioned_save)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
registerClassVersion<T>( detail::Version<T>::version );
|
||||
access::member_save(*self, t, detail::Version<T>::version);
|
||||
access::member_save(*self, t, registerClassVersion<T>());
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member split (save)
|
||||
/*! Versioning implementation */
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_non_member_versioned_save<T, ArchiveType>::value && !traits::has_invalid_output_versioning<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_non_member_save<T, ArchiveType>::value || traits::is_output_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T const & t)
|
||||
template <class T, PROCESS_IF(non_member_versioned_save)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
registerClassVersion<T>( detail::Version<T>::version );
|
||||
save(*self, t, detail::Version<T>::version);
|
||||
CEREAL_SAVE_FUNCTION_NAME(*self, t, registerClassVersion<T>());
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (save_minimal)
|
||||
/*! Versioning implementation */
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_member_versioned_save_minimal<T, ArchiveType>::value && !traits::has_invalid_output_versioning<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_member_save_minimal<T, ArchiveType>::value || traits::is_output_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T const & t)
|
||||
template <class T, PROCESS_IF(member_versioned_save_minimal)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
registerClassVersion<T>( detail::Version<T>::version );
|
||||
self->process( access::member_save_minimal(*self, t, detail::Version<T>::version) );
|
||||
self->process( access::member_save_minimal(*self, t, registerClassVersion<T>()) );
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member split (save_minimal)
|
||||
/*! Versioning implementation */
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_non_member_versioned_save_minimal<T, ArchiveType>::value && !traits::has_invalid_output_versioning<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_non_member_save_minimal<T, ArchiveType>::value || traits::is_output_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T const & t)
|
||||
template <class T, PROCESS_IF(non_member_versioned_save_minimal)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
registerClassVersion<T>( detail::Version<T>::version );
|
||||
self->process( save_minimal(*self, t, detail::Version<T>::version) );
|
||||
self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t, registerClassVersion<T>()) );
|
||||
return *self;
|
||||
}
|
||||
|
||||
#undef PROCESS_IF
|
||||
|
||||
private:
|
||||
ArchiveType * const self;
|
||||
|
||||
|
@ -737,103 +724,104 @@ namespace cereal
|
|||
return *self;
|
||||
}
|
||||
|
||||
//! Helper macro that expands the requirements for activating an overload
|
||||
#define PROCESS_IF(name) \
|
||||
traits::EnableIf<traits::has_##name<T, ArchiveType>::value, \
|
||||
!traits::has_invalid_input_versioning<T, ArchiveType>::value, \
|
||||
(traits::is_specialized_##name<T, ArchiveType>::value || \
|
||||
traits::is_input_serializable<T, ArchiveType>::value)> = traits::sfinae
|
||||
|
||||
//! Member serialization
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_member_serialize<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_member_serialize<T, ArchiveType>::value || traits::is_input_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T & t)
|
||||
template <class T, PROCESS_IF(member_serialize)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
access::member_serialize(*self, t);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member serialization
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_non_member_serialize<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_non_member_serialize<T, ArchiveType>::value || traits::is_input_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T & t)
|
||||
template <class T, PROCESS_IF(non_member_serialize)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
serialize(*self, t);
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME(*self, t);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (load)
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_member_load<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_member_load<T, ArchiveType>::value || traits::is_input_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T & t)
|
||||
template <class T, PROCESS_IF(member_load)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
access::member_load(*self, t);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member split (load)
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_non_member_load<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_non_member_load<T, ArchiveType>::value || traits::is_input_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T & t)
|
||||
template <class T, PROCESS_IF(non_member_load)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
load(*self, t);
|
||||
CEREAL_LOAD_FUNCTION_NAME(*self, t);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (load_minimal)
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_member_load_minimal<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_member_load_minimal<T, ArchiveType>::value || traits::is_input_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T & t)
|
||||
template <class T, PROCESS_IF(member_load_minimal)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
typename traits::has_member_save_minimal<T, ArchiveType>::type value;
|
||||
using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
|
||||
typename traits::has_member_save_minimal<T, OutArchiveType>::type value;
|
||||
self->process( value );
|
||||
access::member_load_minimal(*self, t, value);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member split (load_minimal)
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_non_member_load_minimal<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_non_member_load_minimal<T, ArchiveType>::value || traits::is_input_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T & t)
|
||||
template <class T, PROCESS_IF(non_member_load_minimal)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
typename traits::has_non_member_save_minimal<T, ArchiveType>::type value;
|
||||
using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
|
||||
typename traits::has_non_member_save_minimal<T, OutArchiveType>::type value;
|
||||
self->process( value );
|
||||
load_minimal(*self, t, value);
|
||||
CEREAL_LOAD_MINIMAL_FUNCTION_NAME(*self, t, value);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Empty class specialization
|
||||
template <class T> inline
|
||||
typename std::enable_if<(Flags & AllowEmptyClassElision) &&
|
||||
!traits::is_specialized<T, ArchiveType>::value &&
|
||||
!traits::is_input_serializable<T, ArchiveType>::value && std::is_empty<T>::value, ArchiveType &>::type
|
||||
processImpl(T const &)
|
||||
template <class T, traits::EnableIf<(Flags & AllowEmptyClassElision),
|
||||
!traits::is_specialized<T, ArchiveType>::value,
|
||||
!traits::is_input_serializable<T, ArchiveType>::value,
|
||||
std::is_empty<T>::value> = traits::sfinae> inline
|
||||
ArchiveType & processImpl(T const &)
|
||||
{
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! No matching serialization
|
||||
template <class T> inline
|
||||
typename std::enable_if<!traits::is_specialized<T, ArchiveType>::value && !traits::is_input_serializable<T, ArchiveType>::value &&
|
||||
(!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)),
|
||||
ArchiveType &>::type
|
||||
processImpl(T const &)
|
||||
/*! Invalid if we have invalid input versioning or
|
||||
we have no specialization, are not input serializable, and either
|
||||
don't allow empty class ellision or allow it but are not serializing an empty class */
|
||||
template <class T, traits::EnableIf<traits::has_invalid_input_versioning<T, ArchiveType>::value ||
|
||||
(!traits::is_specialized<T, ArchiveType>::value &&
|
||||
!traits::is_input_serializable<T, ArchiveType>::value &&
|
||||
(!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae> inline
|
||||
ArchiveType & processImpl(T const &)
|
||||
{
|
||||
static_assert(traits::is_output_serializable<T, ArchiveType>::value, "Trying to serialize an unserializable type with an output archive. \n\n "
|
||||
static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value != 0,
|
||||
"cereal could not find any input serialization functions for the provided type and archive combination. \n\n "
|
||||
"Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
|
||||
"Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n "
|
||||
"In addition, you may not mix versioned with non-versioned serialization functions. \n "
|
||||
"Serialize functions generally have the following signature: \n\n "
|
||||
"template<class Archive> \n "
|
||||
" void serialize(Archive & ar) \n "
|
||||
" { \n "
|
||||
" ar( member1, member2, member3 ); \n "
|
||||
" } \n\n " );
|
||||
|
||||
static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value < 2,
|
||||
"cereal found more than one compatible input serialization function for the provided type and archive combination. \n\n "
|
||||
"Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
|
||||
"Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n "
|
||||
"Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n "
|
||||
"In addition, you may not mix versioned with non-versioned serialization functions. \n\n ");
|
||||
|
||||
return *self;
|
||||
}
|
||||
|
||||
|
@ -864,11 +852,8 @@ namespace cereal
|
|||
|
||||
//! Member serialization
|
||||
/*! Versioning implementation */
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_member_versioned_serialize<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_member_serialize<T, ArchiveType>::value || traits::is_input_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T & t)
|
||||
template <class T, PROCESS_IF(member_versioned_serialize)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
const auto version = loadClassVersion<T>();
|
||||
access::member_serialize(*self, t, version);
|
||||
|
@ -877,24 +862,18 @@ namespace cereal
|
|||
|
||||
//! Non member serialization
|
||||
/*! Versioning implementation */
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_non_member_versioned_serialize<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_non_member_serialize<T, ArchiveType>::value || traits::is_input_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T & t)
|
||||
template <class T, PROCESS_IF(non_member_versioned_serialize)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
const auto version = loadClassVersion<T>();
|
||||
serialize(*self, t, version);
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME(*self, t, version);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (load)
|
||||
/*! Versioning implementation */
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_member_versioned_load<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_member_load<T, ArchiveType>::value || traits::is_input_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T & t)
|
||||
template <class T, PROCESS_IF(member_versioned_load)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
const auto version = loadClassVersion<T>();
|
||||
access::member_load(*self, t, version);
|
||||
|
@ -903,27 +882,22 @@ namespace cereal
|
|||
|
||||
//! Non member split (load)
|
||||
/*! Versioning implementation */
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_non_member_versioned_load<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_non_member_load<T, ArchiveType>::value || traits::is_input_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T & t)
|
||||
template <class T, PROCESS_IF(non_member_versioned_load)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
const auto version = loadClassVersion<T>();
|
||||
load(*self, t, version);
|
||||
CEREAL_LOAD_FUNCTION_NAME(*self, t, version);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (load_minimal)
|
||||
/*! Versioning implementation */
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_member_versioned_load_minimal<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_member_load_minimal<T, ArchiveType>::value || traits::is_input_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T & t)
|
||||
template <class T, PROCESS_IF(member_versioned_load_minimal)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
|
||||
const auto version = loadClassVersion<T>();
|
||||
typename traits::has_member_versioned_save_minimal<T, ArchiveType>::type value;
|
||||
typename traits::has_member_versioned_save_minimal<T, OutArchiveType>::type value;
|
||||
self->process(value);
|
||||
access::member_load_minimal(*self, t, value, version);
|
||||
return *self;
|
||||
|
@ -931,19 +905,19 @@ namespace cereal
|
|||
|
||||
//! Non member split (load_minimal)
|
||||
/*! Versioning implementation */
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::has_non_member_versioned_load_minimal<T, ArchiveType>::value &&
|
||||
(traits::is_specialized_non_member_load_minimal<T, ArchiveType>::value || traits::is_input_serializable<T, ArchiveType>::value),
|
||||
ArchiveType &>::type
|
||||
processImpl(T & t)
|
||||
template <class T, PROCESS_IF(non_member_versioned_load_minimal)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
|
||||
const auto version = loadClassVersion<T>();
|
||||
typename traits::has_non_member_versioned_save_minimal<T, ArchiveType>::type value;
|
||||
typename traits::has_non_member_versioned_save_minimal<T, OutArchiveType>::type value;
|
||||
self->process(value);
|
||||
load_minimal(*self, t, value, version);
|
||||
CEREAL_LOAD_MINIMAL_FUNCTION_NAME(*self, t, value, version);
|
||||
return *self;
|
||||
}
|
||||
|
||||
#undef PROCESS_IF
|
||||
|
||||
private:
|
||||
ArchiveType * const self;
|
||||
|
||||
|
@ -962,6 +936,6 @@ namespace cereal
|
|||
} // namespace cereal
|
||||
|
||||
// This include needs to come after things such as binary_data, make_nvp, etc
|
||||
#include "./types/common.hpp"
|
||||
#include "types/common.hpp"
|
||||
|
||||
#endif // CEREAL_CEREAL_HPP_
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <unordered_map>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "../macros.hpp"
|
||||
#include "../details/static_object.hpp"
|
||||
|
||||
namespace cereal
|
||||
|
@ -46,15 +47,15 @@ namespace cereal
|
|||
/*! @ingroup Utility */
|
||||
struct Exception : public std::runtime_error
|
||||
{
|
||||
Exception( const std::string & what_ ) : std::runtime_error(what_) {}
|
||||
Exception( const char * what_ ) : std::runtime_error(what_) {}
|
||||
explicit Exception( const std::string & what_ ) : std::runtime_error(what_) {}
|
||||
explicit Exception( const char * what_ ) : std::runtime_error(what_) {}
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
//! The size type used by cereal
|
||||
/*! To ensure compatability between 32, 64, etc bit machines, we need to use
|
||||
* a fixed size type instead of size_t, which may vary from machine to
|
||||
* machine. */
|
||||
a fixed size type instead of size_t, which may vary from machine to
|
||||
machine. */
|
||||
using size_type = uint64_t;
|
||||
|
||||
// forward decls
|
||||
|
@ -64,7 +65,7 @@ namespace cereal
|
|||
// ######################################################################
|
||||
namespace detail
|
||||
{
|
||||
struct NameValuePairCore {};
|
||||
struct NameValuePairCore {}; //!< Traits struct for NVPs
|
||||
}
|
||||
|
||||
//! For holding name value pairs
|
||||
|
@ -108,7 +109,7 @@ namespace cereal
|
|||
@endcode
|
||||
|
||||
There is a slight amount of overhead to creating NameValuePairs, so there
|
||||
is a third method which will elide the names when they are not needed by
|
||||
is a third method which will elide the names when they are not used by
|
||||
the Archive:
|
||||
|
||||
@code{.cpp}
|
||||
|
@ -134,16 +135,14 @@ namespace cereal
|
|||
class NameValuePair : detail::NameValuePairCore
|
||||
{
|
||||
private:
|
||||
// If we get passed an RValue, we'll just make a local copy if it here
|
||||
// otherwise, we store a reference. If we were passed an array, don't
|
||||
// decay the type - keep it as an array, and then proceed as normal
|
||||
// with the RValue business
|
||||
using DT = typename std::conditional<std::is_array<typename std::remove_reference<T>::type>::value,
|
||||
typename std::remove_cv<T>::type,
|
||||
typename std::decay<T>::type>::type;
|
||||
using Type = typename std::conditional<std::is_rvalue_reference<T>::value,
|
||||
DT,
|
||||
typename std::add_lvalue_reference<DT>::type>::type;
|
||||
// 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" );
|
||||
|
@ -155,9 +154,9 @@ namespace cereal
|
|||
the value can be both loaded and saved to. If you pass an r-value reference,
|
||||
the NameValuePair will store a copy of it instead of a reference. Thus you should
|
||||
only pass r-values in cases where this makes sense, such as the result of some
|
||||
size() call. In either case, any constness will be stripped away
|
||||
@internal */
|
||||
NameValuePair( char const * n, T && v ) : name(n), value(const_cast<Type>(v)) {}
|
||||
size() call.
|
||||
@internal */
|
||||
NameValuePair( char const * n, T && v ) : name(n), value(std::forward<T>(v)) {}
|
||||
|
||||
char const * name;
|
||||
Type value;
|
||||
|
@ -193,7 +192,7 @@ namespace cereal
|
|||
/*! For use in inteneral generic typing functions which have an
|
||||
Archive type declared
|
||||
@internal */
|
||||
#define _CEREAL_NVP(name, value) ::cereal::make_nvp<Archive>(name, value)
|
||||
#define CEREAL_NVP_(name, value) ::cereal::make_nvp<Archive>(name, value)
|
||||
|
||||
// ######################################################################
|
||||
//! A wrapper around data that can be serialized in a binary fashion
|
||||
|
@ -211,9 +210,9 @@ namespace cereal
|
|||
const void *,
|
||||
void *>::type;
|
||||
|
||||
BinaryData( T && d, uint64_t s ) : data(d), size(s) {}
|
||||
BinaryData( T && d, uint64_t s ) : data(std::forward<T>(d)), size(s) {}
|
||||
|
||||
PT data; //!< pointer to beginning of data
|
||||
PT data; //!< pointer to beginning of data
|
||||
uint64_t size; //!< size in bytes
|
||||
};
|
||||
|
||||
|
@ -221,15 +220,18 @@ namespace cereal
|
|||
namespace detail
|
||||
{
|
||||
// base classes for type checking
|
||||
struct OutputArchiveBase {};
|
||||
struct InputArchiveBase {};
|
||||
/* 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 { private: virtual void rtti(){} };
|
||||
class InputArchiveBase { 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 int32_t msb_32bit = 0x80000000;
|
||||
static const int32_t msb_32bit = 0x80000000;
|
||||
static const int32_t msb2_32bit = 0x40000000;
|
||||
}
|
||||
|
||||
|
@ -246,15 +248,14 @@ namespace cereal
|
|||
class SizeTag
|
||||
{
|
||||
private:
|
||||
// If we get passed an RValue, we'll just make a local copy if it here
|
||||
// otherwise, we store a reference
|
||||
using DT = typename std::decay<T>::type;
|
||||
using Type = typename std::conditional<std::is_rvalue_reference<T>::value,
|
||||
DT,
|
||||
typename std::add_lvalue_reference<DT>::type>::type;
|
||||
// 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;
|
||||
|
||||
public:
|
||||
SizeTag( T && sz ) : size(const_cast<Type>(sz)) {}
|
||||
SizeTag( T && sz ) : size(std::forward<T>(sz)) {}
|
||||
|
||||
Type size;
|
||||
};
|
||||
|
@ -283,28 +284,26 @@ namespace cereal
|
|||
template <class Key, class Value>
|
||||
struct MapItem
|
||||
{
|
||||
using DecayKey = typename std::decay<Key>::type;
|
||||
using KeyType = typename std::conditional<
|
||||
std::is_rvalue_reference<Key>::value,
|
||||
DecayKey,
|
||||
typename std::add_lvalue_reference<DecayKey>::type>::type;
|
||||
std::is_lvalue_reference<Key>::value,
|
||||
Key,
|
||||
typename std::decay<Key>::type>::type;
|
||||
|
||||
using DecayValue = typename std::decay<Value>::type;
|
||||
using ValueType = typename std::conditional<
|
||||
std::is_rvalue_reference<Value>::value,
|
||||
DecayValue,
|
||||
typename std::add_lvalue_reference<DecayValue>::type>::type;
|
||||
using ValueType = typename std::conditional<
|
||||
std::is_lvalue_reference<Value>::value,
|
||||
Value,
|
||||
typename std::decay<Value>::type>::type;
|
||||
|
||||
//! Construct a MapItem from a key and a value
|
||||
/*! @internal */
|
||||
MapItem( Key && key_, Value && value_ ) : key(const_cast<KeyType>(key_)), value(const_cast<ValueType>(value_)) {}
|
||||
MapItem( Key && key_, Value && value_ ) : key(std::forward<Key>(key_)), value(std::forward<Value>(value_)) {}
|
||||
|
||||
KeyType key;
|
||||
ValueType value;
|
||||
|
||||
//! Serialize the MapItem with the NVPs "key" and "value"
|
||||
template <class Archive> inline
|
||||
void serialize(Archive & archive)
|
||||
void CEREAL_SERIALIZE_FUNCTION_NAME(Archive & archive)
|
||||
{
|
||||
archive( make_nvp<Archive>("key", key),
|
||||
make_nvp<Archive>("value", value) );
|
||||
|
@ -322,129 +321,33 @@ namespace cereal
|
|||
|
||||
namespace detail
|
||||
{
|
||||
// ######################################################################
|
||||
//! Holds all registered version information
|
||||
struct Versions
|
||||
{
|
||||
std::unordered_map<std::size_t, std::uint32_t> mapping;
|
||||
}; // struct Versions
|
||||
//! Tag for Version, which due to its anonymous namespace, becomes a different
|
||||
//! type in each translation unit
|
||||
/*! This allows CEREAL_CLASS_VERSION to be safely called in a header file */
|
||||
namespace{ struct version_binding_tag {}; }
|
||||
|
||||
// ######################################################################
|
||||
//! Version information class
|
||||
/*! This is the base case for classes that have not been explicitly
|
||||
registered */
|
||||
template <class T> struct Version
|
||||
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
|
||||
};
|
||||
|
||||
#ifdef CEREAL_FUTURE_EXPERIMENTAL
|
||||
// ######################################################################
|
||||
//! A class that can store any type
|
||||
/*! This is inspired by boost::any and is intended to be a very light-weight
|
||||
replacement for internal use only.
|
||||
|
||||
This class is only here as a candidate for issue #46 (see github) and
|
||||
should be considered unsupported until a future version of cereal.
|
||||
*/
|
||||
class Any
|
||||
//! Holds all registered version information
|
||||
struct Versions
|
||||
{
|
||||
private:
|
||||
//! Convenience alias for decay
|
||||
template <class T>
|
||||
using ST = typename std::decay<T>::type;
|
||||
std::unordered_map<std::size_t, std::uint32_t> mapping;
|
||||
|
||||
struct Base
|
||||
{
|
||||
virtual ~Base() {}
|
||||
virtual std::unique_ptr<Base> clone() const = 0;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Derived : Base
|
||||
{
|
||||
template <class U>
|
||||
Derived( U && data ) : value( std::forward<U>( data ) ) {}
|
||||
|
||||
std::unique_ptr<Base> clone() const
|
||||
{
|
||||
return std::unique_ptr<Base>( new Derived<T>( value ) );
|
||||
}
|
||||
|
||||
T value;
|
||||
};
|
||||
|
||||
public:
|
||||
//! Construct from any type
|
||||
template <class T> inline
|
||||
Any( T && data ) :
|
||||
itsPtr( new Derived<ST<T>>( std::forward<T>( data ) ) )
|
||||
{ }
|
||||
|
||||
//! Convert to any type, if possible
|
||||
/*! Attempts to perform the conversion if possible,
|
||||
otherwise throws an exception.
|
||||
|
||||
@throw Exception if conversion is not possible (see get() for more info)
|
||||
@tparam The requested type to convert to */
|
||||
template <class T> inline
|
||||
operator T()
|
||||
{
|
||||
return get<ST<T>>();
|
||||
}
|
||||
|
||||
Any() : itsPtr() {}
|
||||
Any( Any & other ) : itsPtr( other.clone() ) {}
|
||||
Any( Any const & other ) : itsPtr( other.clone() ) {}
|
||||
Any( Any && other ) : itsPtr( std::move( other.itsPtr ) ) {}
|
||||
|
||||
Any & operator=( Any const & other )
|
||||
{
|
||||
if( itsPtr == other.itsPtr ) return *this;
|
||||
|
||||
auto cloned = other.clone();
|
||||
itsPtr = std::move( cloned );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Any & operator=( Any && other )
|
||||
{
|
||||
if( itsPtr == other.itsPtr ) return *this;
|
||||
|
||||
itsPtr = std::move( other.itsPtr );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
//! Get the contained type as type T
|
||||
/*! @tparam T The requested type to convert to
|
||||
@return The type converted to T
|
||||
@throw Exception if conversion is impossible */
|
||||
template <class T>
|
||||
ST<T> & get()
|
||||
{
|
||||
auto * derived = dynamic_cast<Derived<ST<T>> *>( itsPtr.get() );
|
||||
|
||||
if( !derived )
|
||||
throw ::cereal::Exception( "Invalid conversion requested on ASDFA" );
|
||||
|
||||
return derived->value;
|
||||
}
|
||||
|
||||
//! Clones the held data if it exists
|
||||
std::unique_ptr<Base> clone() const
|
||||
{
|
||||
if( itsPtr ) return itsPtr->clone();
|
||||
else return {};
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Base> itsPtr;
|
||||
}; // struct Any
|
||||
#endif // CEREAL_FUTURE_EXPERIMENTAL
|
||||
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
|
||||
|
||||
|
|
|
@ -52,22 +52,23 @@
|
|||
#include <map>
|
||||
|
||||
//! Binds a polymorhic type to all registered archives
|
||||
/*! This binds a polymorphic type to all registered archives that
|
||||
/*! This binds a polymorphic type to all compatible registered archives that
|
||||
have been registered with CEREAL_REGISTER_ARCHIVE. This must be called
|
||||
after all archives are registered (usually after the archives themselves
|
||||
have been included). */
|
||||
#define CEREAL_BIND_TO_ARCHIVES(T) \
|
||||
namespace cereal { \
|
||||
namespace detail { \
|
||||
template<> \
|
||||
struct init_binding<T> { \
|
||||
static bind_to_archives<T> const & b; \
|
||||
}; \
|
||||
bind_to_archives<T> const & init_binding<T>::b = \
|
||||
::cereal::detail::StaticObject< \
|
||||
bind_to_archives<T> \
|
||||
>::getInstance().bind(); \
|
||||
}} // end namespaces
|
||||
#define CEREAL_BIND_TO_ARCHIVES(T) \
|
||||
namespace cereal { \
|
||||
namespace detail { \
|
||||
template<> \
|
||||
struct init_binding<T> { \
|
||||
static bind_to_archives<T> const & b; \
|
||||
static void unused() { (void)b; } \
|
||||
}; \
|
||||
bind_to_archives<T> const & init_binding<T>::b = \
|
||||
::cereal::detail::StaticObject< \
|
||||
bind_to_archives<T> \
|
||||
>::getInstance().bind(); \
|
||||
}} /* end namespaces */
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
|
@ -136,8 +137,8 @@ namespace cereal
|
|||
};
|
||||
|
||||
// forward decls for archives from cereal.hpp
|
||||
struct InputArchiveBase;
|
||||
struct OutputArchiveBase;
|
||||
class InputArchiveBase;
|
||||
class OutputArchiveBase;
|
||||
|
||||
//! Creates a binding (map entry) between an input archive type and a polymorphic type
|
||||
/*! Bindings are made when types are registered, assuming that at least one
|
||||
|
@ -149,6 +150,13 @@ namespace cereal
|
|||
//! Initialize the binding
|
||||
InputBindingCreator()
|
||||
{
|
||||
auto & map = StaticObject<InputBindingMap<Archive>>::getInstance().map;
|
||||
auto key = std::string(binding_name<T>::name());
|
||||
auto lb = map.lower_bound(key);
|
||||
|
||||
if (lb != map.end() && lb->first == key)
|
||||
return;
|
||||
|
||||
typename InputBindingMap<Archive>::Serializers serializers;
|
||||
|
||||
serializers.shared_ptr =
|
||||
|
@ -157,7 +165,7 @@ namespace cereal
|
|||
Archive & ar = *static_cast<Archive*>(arptr);
|
||||
std::shared_ptr<T> ptr;
|
||||
|
||||
ar( _CEREAL_NVP("ptr_wrapper", ::cereal::memory_detail::make_ptr_wrapper(ptr)) );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", ::cereal::memory_detail::make_ptr_wrapper(ptr)) );
|
||||
|
||||
dptr = ptr;
|
||||
};
|
||||
|
@ -168,12 +176,12 @@ namespace cereal
|
|||
Archive & ar = *static_cast<Archive*>(arptr);
|
||||
std::unique_ptr<T> ptr;
|
||||
|
||||
ar( _CEREAL_NVP("ptr_wrapper", ::cereal::memory_detail::make_ptr_wrapper(ptr)) );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", ::cereal::memory_detail::make_ptr_wrapper(ptr)) );
|
||||
|
||||
dptr.reset(ptr.release());
|
||||
};
|
||||
|
||||
StaticObject<InputBindingMap<Archive>>::getInstance().map.insert( { std::string(binding_name<T>::name()), serializers } );
|
||||
map.insert( lb, { std::move(key), std::move(serializers) } );
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -192,13 +200,13 @@ namespace cereal
|
|||
std::uint32_t id = ar.registerPolymorphicType(name);
|
||||
|
||||
// Serialize the id
|
||||
ar( _CEREAL_NVP("polymorphic_id", id) );
|
||||
ar( CEREAL_NVP_("polymorphic_id", id) );
|
||||
|
||||
// If the msb of the id is 1, then the type name is new, and we should serialize it
|
||||
if( id & detail::msb_32bit )
|
||||
{
|
||||
std::string namestring(name);
|
||||
ar( _CEREAL_NVP("polymorphic_name", namestring) );
|
||||
ar( CEREAL_NVP_("polymorphic_name", namestring) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,7 +258,7 @@ namespace cereal
|
|||
{
|
||||
::cereal::memory_detail::EnableSharedStateHelper<T> state( static_cast<T *>(const_cast<void *>(dptr)) );
|
||||
PolymorphicSharedPointerWrapper psptr( dptr );
|
||||
ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( psptr() ) ) );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( psptr() ) ) );
|
||||
}
|
||||
|
||||
//! Does the actual work of saving a polymorphic shared_ptr
|
||||
|
@ -264,12 +272,19 @@ namespace cereal
|
|||
static inline void savePolymorphicSharedPtr( Archive & ar, void const * dptr, std::false_type /* has_shared_from_this */ )
|
||||
{
|
||||
PolymorphicSharedPointerWrapper psptr( dptr );
|
||||
ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( psptr() ) ) );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( psptr() ) ) );
|
||||
}
|
||||
|
||||
//! Initialize the binding
|
||||
OutputBindingCreator()
|
||||
{
|
||||
auto & map = StaticObject<OutputBindingMap<Archive>>::getInstance().map;
|
||||
auto key = std::type_index(typeid(T));
|
||||
auto lb = map.lower_bound(key);
|
||||
|
||||
if (lb != map.end() && lb->first == key)
|
||||
return;
|
||||
|
||||
typename OutputBindingMap<Archive>::Serializers serializers;
|
||||
|
||||
serializers.shared_ptr =
|
||||
|
@ -295,10 +310,10 @@ namespace cereal
|
|||
|
||||
std::unique_ptr<T const, EmptyDeleter<T const>> const ptr(static_cast<T const *>(dptr));
|
||||
|
||||
ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
|
||||
};
|
||||
|
||||
StaticObject<OutputBindingMap<Archive>>::getInstance().map.insert( {std::type_index(typeid(T)), serializers} );
|
||||
map.insert( { std::move(key), std::move(serializers) } );
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -306,6 +321,10 @@ namespace cereal
|
|||
//! of instantiate_polymorphic_binding
|
||||
struct adl_tag {};
|
||||
|
||||
//! Tag for init_binding, bind_to_archives and instantiate_polymorphic_binding. Due to the use of anonymous
|
||||
//! namespace it becomes a different type in each translation unit.
|
||||
namespace { struct polymorphic_binding_tag {}; }
|
||||
|
||||
//! Causes the static object bindings between an archive type and a serializable type T
|
||||
template <class Archive, class T>
|
||||
struct create_bindings
|
||||
|
@ -338,14 +357,14 @@ namespace cereal
|
|||
template <class Archive, class T>
|
||||
struct polymorphic_serialization_support
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
|
||||
//! Creates the appropriate bindings depending on whether the archive supports
|
||||
//! saving or loading
|
||||
virtual void instantiate();
|
||||
virtual CEREAL_DLL_EXPORT void instantiate() CEREAL_USED;
|
||||
#else // NOT _MSC_VER
|
||||
//! Creates the appropriate bindings depending on whether the archive supports
|
||||
//! saving or loading
|
||||
static void instantiate();
|
||||
static CEREAL_DLL_EXPORT void instantiate() CEREAL_USED;
|
||||
//! This typedef causes the compiler to instantiate this static function
|
||||
typedef instantiate_function<instantiate> unused;
|
||||
#endif // _MSC_VER
|
||||
|
@ -353,11 +372,15 @@ namespace cereal
|
|||
|
||||
// instantiate implementation
|
||||
template <class Archive, class T>
|
||||
void polymorphic_serialization_support<Archive,T>::instantiate()
|
||||
CEREAL_DLL_EXPORT void polymorphic_serialization_support<Archive,T>::instantiate()
|
||||
{
|
||||
create_bindings<Archive,T>::save( std::is_base_of<detail::OutputArchiveBase, Archive>() );
|
||||
create_bindings<Archive,T>::save( std::integral_constant<bool,
|
||||
std::is_base_of<detail::OutputArchiveBase, Archive>::value &&
|
||||
traits::is_output_serializable<T, Archive>::value>{} );
|
||||
|
||||
create_bindings<Archive,T>::load( std::is_base_of<detail::InputArchiveBase, Archive>() );
|
||||
create_bindings<Archive,T>::load( std::integral_constant<bool,
|
||||
std::is_base_of<detail::InputArchiveBase, Archive>::value &&
|
||||
traits::is_input_serializable<T, Archive>::value>{} );
|
||||
}
|
||||
|
||||
//! Begins the binding process of a type to all registered archives
|
||||
|
@ -365,13 +388,13 @@ namespace cereal
|
|||
the CEREAL_REGISTER_ARCHIVE macro. Overload resolution will then force
|
||||
several static objects to be made that allow us to bind together all
|
||||
registered archive types with the parameter type T. */
|
||||
template <class T>
|
||||
template <class T, class Tag = polymorphic_binding_tag>
|
||||
struct bind_to_archives
|
||||
{
|
||||
//! Binding for non abstract types
|
||||
void bind(std::false_type) const
|
||||
{
|
||||
instantiate_polymorphic_binding((T*) 0, 0, adl_tag{});
|
||||
instantiate_polymorphic_binding((T*) 0, 0, Tag{}, adl_tag{});
|
||||
}
|
||||
|
||||
//! Binding for abstract types
|
||||
|
@ -391,7 +414,7 @@ namespace cereal
|
|||
};
|
||||
|
||||
//! Used to hide the static object used to bind T to registered archives
|
||||
template <class T>
|
||||
template <class T, class Tag = polymorphic_binding_tag>
|
||||
struct init_binding;
|
||||
|
||||
//! Base case overload for instantiation
|
||||
|
@ -406,8 +429,8 @@ namespace cereal
|
|||
mechanisms even though they are never called.
|
||||
|
||||
See the documentation for the other functions to try and understand this */
|
||||
template <class T>
|
||||
void instantiate_polymorphic_binding( T*, int, adl_tag ) {}
|
||||
template <class T, typename BindingTag>
|
||||
void instantiate_polymorphic_binding( T*, int, BindingTag, adl_tag ) {}
|
||||
} // namespace detail
|
||||
} // namespace cereal
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
/*
|
||||
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
|
||||
|
@ -15,7 +14,6 @@
|
|||
* 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
|
||||
|
@ -30,7 +28,23 @@
|
|||
#ifndef CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
||||
#define CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
||||
|
||||
#include "../details/util.hpp"
|
||||
//! Prevent link optimization from removing non-referenced static objects
|
||||
/*! Especially for polymorphic support, we create static objects which
|
||||
may not ever be explicitly referenced. Most linkers will detect this
|
||||
and remove the code causing various unpleasant runtime errors. These
|
||||
macros, adopted from Boost (see force_include.hpp) prevent this
|
||||
(C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
Use, modification and distribution is subject to the Boost Software
|
||||
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt) */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define CEREAL_DLL_EXPORT __declspec(dllexport)
|
||||
# define CEREAL_USED
|
||||
#else // clang or gcc
|
||||
# define CEREAL_DLL_EXPORT
|
||||
# define CEREAL_USED __attribute__ ((__used__))
|
||||
#endif
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
|
@ -40,12 +54,11 @@ namespace cereal
|
|||
/*! This class will create a single copy (singleton) of some
|
||||
type and ensures that merely referencing this type will
|
||||
cause it to be instantiated and initialized pre-execution.
|
||||
|
||||
For example, this is used heavily in the polymorphic pointer
|
||||
serialization mechanisms to bind various archive types with
|
||||
different polymorphic classes */
|
||||
template <class T>
|
||||
class StaticObject
|
||||
class CEREAL_DLL_EXPORT StaticObject
|
||||
{
|
||||
private:
|
||||
//! Forces instantiation at pre-execution time
|
||||
|
@ -71,7 +84,7 @@ namespace cereal
|
|||
};
|
||||
|
||||
template <class T> T & StaticObject<T>::instance = StaticObject<T>::create();
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
||||
#endif // CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
File diff suppressed because it is too large
Load diff
|
@ -41,17 +41,13 @@ namespace cereal
|
|||
//! Demangles the type encoded in a string
|
||||
/*! @internal */
|
||||
inline std::string demangle( std::string const & name )
|
||||
{
|
||||
return name;
|
||||
}
|
||||
{ return name; }
|
||||
|
||||
//! Gets the demangled name of a type
|
||||
/*! @internal */
|
||||
template <class T> inline
|
||||
std::string demangledName()
|
||||
{
|
||||
return typeid( T ).name();
|
||||
}
|
||||
std::string demangledName()
|
||||
{ return typeid( T ).name(); }
|
||||
} // namespace util
|
||||
} // namespace cereal
|
||||
#else // clang or gcc
|
||||
|
@ -79,7 +75,7 @@ namespace cereal
|
|||
inline std::string demangle(std::string mangledName)
|
||||
{
|
||||
int status = 0;
|
||||
char *demangledName = NULL;
|
||||
char *demangledName = nullptr;
|
||||
std::size_t len;
|
||||
|
||||
demangledName = abi::__cxa_demangle(mangledName.c_str(), 0, &len, &status);
|
||||
|
@ -93,12 +89,9 @@ namespace cereal
|
|||
//! Gets the demangled name of a type
|
||||
/*! @internal */
|
||||
template<class T> inline
|
||||
std::string demangledName()
|
||||
{ return demangle(typeid(T).name()); }
|
||||
std::string demangledName()
|
||||
{ return demangle(typeid(T).name()); }
|
||||
}
|
||||
} // namespace cereal
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif // clang or gcc branch of _MSC_VER
|
||||
#endif // CEREAL_DETAILS_UTIL_HPP_
|
||||
|
|
|
@ -410,7 +410,7 @@ private:
|
|||
}
|
||||
|
||||
template <>
|
||||
bool characterOk<char>( Ch )
|
||||
bool characterOk<char>( char )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -185,7 +185,7 @@ protected:
|
|||
}
|
||||
|
||||
template <>
|
||||
bool characterOk<char>( Ch )
|
||||
bool characterOk<char>( char )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -334,6 +334,14 @@ namespace rapidxml
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Ch>
|
||||
inline bool preserve_space(xml_node<Ch>* node)
|
||||
{
|
||||
const Ch preserve_value[] = { Ch('p'), Ch('r'), Ch('e'), Ch('s'), Ch('e'), Ch('r'), Ch('v'), Ch('e') };
|
||||
const xml_attribute<Ch>* space = node->first_attribute("xml:space");
|
||||
return space && internal::compare(space->value(), space->value_size(), preserve_value, sizeof(preserve_value) / sizeof(Ch), true);
|
||||
}
|
||||
}
|
||||
//! \endcond
|
||||
|
||||
|
@ -1566,7 +1574,7 @@ namespace rapidxml
|
|||
// - replacing XML character entity references with proper characters (' & " < > &#...;)
|
||||
// - condensing whitespace sequences to single space character
|
||||
template<class StopPred, class StopPredPure, int Flags>
|
||||
static Ch *skip_and_expand_character_refs(Ch *&text)
|
||||
static Ch *skip_and_expand_character_refs(Ch *&text, bool preserve_space)
|
||||
{
|
||||
// If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip
|
||||
if (Flags & parse_no_entity_translation &&
|
||||
|
@ -1691,7 +1699,7 @@ namespace rapidxml
|
|||
}
|
||||
|
||||
// If whitespace condensing is enabled
|
||||
if (Flags & parse_normalize_whitespace)
|
||||
if ((Flags & parse_normalize_whitespace) && !preserve_space)
|
||||
{
|
||||
// Test if condensing is needed
|
||||
if (whitespace_pred::test(*src))
|
||||
|
@ -1942,15 +1950,17 @@ namespace rapidxml
|
|||
if (!(Flags & parse_trim_whitespace))
|
||||
text = contents_start;
|
||||
|
||||
const bool preserve_space = internal::preserve_space(node);
|
||||
|
||||
// Skip until end of data
|
||||
Ch *value_ = text, *end;
|
||||
if (Flags & parse_normalize_whitespace)
|
||||
end = skip_and_expand_character_refs<text_pred, text_pure_with_ws_pred, Flags>(text);
|
||||
if ((Flags & parse_normalize_whitespace) && !preserve_space)
|
||||
end = skip_and_expand_character_refs<text_pred, text_pure_with_ws_pred, Flags>(text, false);
|
||||
else
|
||||
end = skip_and_expand_character_refs<text_pred, text_pure_no_ws_pred, Flags>(text);
|
||||
end = skip_and_expand_character_refs<text_pred, text_pure_no_ws_pred, Flags>(text, preserve_space);
|
||||
|
||||
// Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after >
|
||||
if (Flags & parse_trim_whitespace)
|
||||
if ((Flags & parse_trim_whitespace) && !preserve_space)
|
||||
{
|
||||
if (Flags & parse_normalize_whitespace)
|
||||
{
|
||||
|
@ -2187,6 +2197,12 @@ namespace rapidxml
|
|||
case Ch('<'):
|
||||
if (text[1] == Ch('/'))
|
||||
{
|
||||
Ch *contents_end = 0;
|
||||
if (internal::preserve_space(node))
|
||||
{
|
||||
contents_end = text;
|
||||
}
|
||||
|
||||
// Node closing
|
||||
text += 2; // Skip '</'
|
||||
if (Flags & parse_validate_closing_tags)
|
||||
|
@ -2207,6 +2223,12 @@ namespace rapidxml
|
|||
if (*text != Ch('>'))
|
||||
RAPIDXML_PARSE_ERROR("expected >", text);
|
||||
++text; // Skip '>'
|
||||
|
||||
if (contents_end && contents_end != contents_start)
|
||||
{
|
||||
node->value(contents_start, contents_end - contents_start);
|
||||
node->value()[node->value_size()] = Ch('\0');
|
||||
}
|
||||
return; // Node closed, finished parsing contents
|
||||
}
|
||||
else
|
||||
|
@ -2275,9 +2297,9 @@ namespace rapidxml
|
|||
Ch *value_ = text, *end;
|
||||
const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes
|
||||
if (quote == Ch('\''))
|
||||
end = skip_and_expand_character_refs<attribute_value_pred<Ch('\'')>, attribute_value_pure_pred<Ch('\'')>, AttFlags>(text);
|
||||
end = skip_and_expand_character_refs<attribute_value_pred<Ch('\'')>, attribute_value_pure_pred<Ch('\'')>, AttFlags>(text, false);
|
||||
else
|
||||
end = skip_and_expand_character_refs<attribute_value_pred<Ch('"')>, attribute_value_pure_pred<Ch('"')>, AttFlags>(text);
|
||||
end = skip_and_expand_character_refs<attribute_value_pred<Ch('"')>, attribute_value_pure_pred<Ch('"')>, AttFlags>(text, false);
|
||||
|
||||
// Set attribute value
|
||||
attribute->value(value_, end - value_);
|
||||
|
|
82
3party/Alohalytics/src/cereal/include/macros.hpp
Normal file
82
3party/Alohalytics/src/cereal/include/macros.hpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*! \file macros.hpp
|
||||
\brief Preprocessor macros that can customise the cereal library
|
||||
|
||||
By default, cereal looks for serialization functions with very
|
||||
specific names, that is: serialize, load, save, load_minimal,
|
||||
or save_minimal.
|
||||
|
||||
This file allows an advanced user to change these names to conform
|
||||
to some other style or preference. This is implemented using
|
||||
preprocessor macros.
|
||||
|
||||
As a result of this, in internal cereal code you will see macros
|
||||
used for these function names. In user code, you should name
|
||||
the functions like you normally would and not use the macros
|
||||
to improve readability.
|
||||
\ingroup utility */
|
||||
/*
|
||||
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_MACROS_HPP_
|
||||
#define CEREAL_MACROS_HPP_
|
||||
|
||||
#ifndef CEREAL_SERIALIZE_FUNCTION_NAME
|
||||
//! The serialization/deserialization function name to search for.
|
||||
/*! You can define @c CEREAL_SERIALIZE_FUNCTION_NAME to be different assuming
|
||||
you do so before this file is included. */
|
||||
#define CEREAL_SERIALIZE_FUNCTION_NAME serialize
|
||||
#endif // CEREAL_SERIALIZE_FUNCTION_NAME
|
||||
|
||||
#ifndef CEREAL_LOAD_FUNCTION_NAME
|
||||
//! The deserialization (load) function name to search for.
|
||||
/*! You can define @c CEREAL_LOAD_FUNCTION_NAME to be different assuming you do so
|
||||
before this file is included. */
|
||||
#define CEREAL_LOAD_FUNCTION_NAME load
|
||||
#endif // CEREAL_LOAD_FUNCTION_NAME
|
||||
|
||||
#ifndef CEREAL_SAVE_FUNCTION_NAME
|
||||
//! The serialization (save) function name to search for.
|
||||
/*! You can define @c CEREAL_SAVE_FUNCTION_NAME to be different assuming you do so
|
||||
before this file is included. */
|
||||
#define CEREAL_SAVE_FUNCTION_NAME save
|
||||
#endif // CEREAL_SAVE_FUNCTION_NAME
|
||||
|
||||
#ifndef CEREAL_LOAD_MINIMAL_FUNCTION_NAME
|
||||
//! The deserialization (load_minimal) function name to search for.
|
||||
/*! You can define @c CEREAL_LOAD_MINIMAL_FUNCTION_NAME to be different assuming you do so
|
||||
before this file is included. */
|
||||
#define CEREAL_LOAD_MINIMAL_FUNCTION_NAME load_minimal
|
||||
#endif // CEREAL_LOAD_MINIMAL_FUNCTION_NAME
|
||||
|
||||
#ifndef CEREAL_SAVE_MINIMAL_FUNCTION_NAME
|
||||
//! The serialization (save_minimal) function name to search for.
|
||||
/*! You can define @c CEREAL_SAVE_MINIMAL_FUNCTION_NAME to be different assuming you do so
|
||||
before this file is included. */
|
||||
#define CEREAL_SAVE_MINIMAL_FUNCTION_NAME save_minimal
|
||||
#endif // CEREAL_SAVE_MINIMAL_FUNCTION_NAME
|
||||
|
||||
#endif // CEREAL_MACROS_HPP_
|
|
@ -40,7 +40,7 @@ namespace cereal
|
|||
template <class Archive, class T, size_t N> inline
|
||||
typename std::enable_if<traits::is_output_serializable<BinaryData<T>, Archive>::value
|
||||
&& std::is_arithmetic<T>::value, void>::type
|
||||
save( Archive & ar, std::array<T, N> const & array )
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::array<T, N> const & array )
|
||||
{
|
||||
ar( binary_data( array.data(), sizeof(array) ) );
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ namespace cereal
|
|||
template <class Archive, class T, size_t N> inline
|
||||
typename std::enable_if<traits::is_input_serializable<BinaryData<T>, Archive>::value
|
||||
&& std::is_arithmetic<T>::value, void>::type
|
||||
load( Archive & ar, std::array<T, N> & array )
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::array<T, N> & array )
|
||||
{
|
||||
ar( binary_data( array.data(), sizeof(array) ) );
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ namespace cereal
|
|||
template <class Archive, class T, size_t N> inline
|
||||
typename std::enable_if<!traits::is_output_serializable<BinaryData<T>, Archive>::value
|
||||
|| !std::is_arithmetic<T>::value, void>::type
|
||||
save( Archive & ar, std::array<T, N> const & array )
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::array<T, N> const & array )
|
||||
{
|
||||
for( auto const & i : array )
|
||||
ar( i );
|
||||
|
@ -69,7 +69,7 @@ namespace cereal
|
|||
template <class Archive, class T, size_t N> inline
|
||||
typename std::enable_if<!traits::is_input_serializable<BinaryData<T>, Archive>::value
|
||||
|| !std::is_arithmetic<T>::value, void>::type
|
||||
load( Archive & ar, std::array<T, N> & array )
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::array<T, N> & array )
|
||||
{
|
||||
for( auto & i : array )
|
||||
ar( i );
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#ifndef CEREAL_TYPES_BASE_CLASS_HPP_
|
||||
#define CEREAL_TYPES_BASE_CLASS_HPP_
|
||||
|
||||
#include "../details/traits.hpp"
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
//! Casts a derived class to its non-virtual base class in a way that safely supports abstract classes
|
||||
|
@ -67,12 +69,12 @@ namespace cereal
|
|||
};
|
||||
@endcode */
|
||||
template<class Base>
|
||||
struct base_class
|
||||
struct base_class : private traits::detail::BaseCastBase
|
||||
{
|
||||
template<class Derived>
|
||||
base_class(Derived const * derived) :
|
||||
base_ptr(const_cast<Base*>(static_cast<Base const *>(derived)))
|
||||
{ }
|
||||
{ static_assert( std::is_base_of<Base, Derived>::value, "Can only use base_class on a valid base class" ); }
|
||||
|
||||
Base * base_ptr;
|
||||
};
|
||||
|
@ -147,12 +149,12 @@ namespace cereal
|
|||
}
|
||||
@endcode */
|
||||
template<class Base>
|
||||
struct virtual_base_class
|
||||
struct virtual_base_class : private traits::detail::BaseCastBase
|
||||
{
|
||||
template<class Derived>
|
||||
virtual_base_class(Derived const * derived) :
|
||||
base_ptr(const_cast<Base*>(static_cast<Base const *>(derived)))
|
||||
{ }
|
||||
{ static_assert( std::is_base_of<Base, Derived>::value, "Can only use base_class on a valid base class" ); }
|
||||
|
||||
Base * base_ptr;
|
||||
};
|
||||
|
|
|
@ -49,57 +49,57 @@ namespace cereal
|
|||
|
||||
//! Serializing (save) for std::bitset
|
||||
template <class Archive, size_t N> inline
|
||||
void save( Archive & ar, std::bitset<N> const & bits )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::bitset<N> const & bits )
|
||||
{
|
||||
try
|
||||
{
|
||||
auto const b = bits.to_ulong();
|
||||
ar( _CEREAL_NVP("type", bitset_detail::type::ulong) );
|
||||
ar( _CEREAL_NVP("data", b) );
|
||||
ar( CEREAL_NVP_("type", bitset_detail::type::ulong) );
|
||||
ar( CEREAL_NVP_("data", b) );
|
||||
}
|
||||
catch( std::overflow_error const & )
|
||||
{
|
||||
try
|
||||
{
|
||||
auto const b = bits.to_ullong();
|
||||
ar( _CEREAL_NVP("type", bitset_detail::type::ullong) );
|
||||
ar( _CEREAL_NVP("data", b) );
|
||||
ar( CEREAL_NVP_("type", bitset_detail::type::ullong) );
|
||||
ar( CEREAL_NVP_("data", b) );
|
||||
}
|
||||
catch( std::overflow_error const & )
|
||||
{
|
||||
ar( _CEREAL_NVP("type", bitset_detail::type::string) );
|
||||
ar( _CEREAL_NVP("data", bits.to_string()) );
|
||||
ar( CEREAL_NVP_("type", bitset_detail::type::string) );
|
||||
ar( CEREAL_NVP_("data", bits.to_string()) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Serializing (load) for std::bitset
|
||||
template <class Archive, size_t N> inline
|
||||
void load( Archive & ar, std::bitset<N> & bits )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::bitset<N> & bits )
|
||||
{
|
||||
bitset_detail::type t;
|
||||
ar( _CEREAL_NVP("type", t) );
|
||||
ar( CEREAL_NVP_("type", t) );
|
||||
|
||||
switch( t )
|
||||
{
|
||||
case bitset_detail::type::ulong:
|
||||
{
|
||||
unsigned long b;
|
||||
ar( _CEREAL_NVP("data", b) );
|
||||
ar( CEREAL_NVP_("data", b) );
|
||||
bits = std::bitset<N>( b );
|
||||
break;
|
||||
}
|
||||
case bitset_detail::type::ullong:
|
||||
{
|
||||
unsigned long long b;
|
||||
ar( _CEREAL_NVP("data", b) );
|
||||
ar( CEREAL_NVP_("data", b) );
|
||||
bits = std::bitset<N>( b );
|
||||
break;
|
||||
}
|
||||
case bitset_detail::type::string:
|
||||
{
|
||||
std::string b;
|
||||
ar( _CEREAL_NVP("data", b) );
|
||||
ar( CEREAL_NVP_("data", b) );
|
||||
bits = std::bitset<N>( b );
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace cereal
|
|||
template<class T>
|
||||
void operator()(T const & value) const
|
||||
{
|
||||
ar( _CEREAL_NVP("data", value) );
|
||||
ar( CEREAL_NVP_("data", value) );
|
||||
}
|
||||
|
||||
Archive & ar;
|
||||
|
@ -69,7 +69,7 @@ namespace cereal
|
|||
if(N == target)
|
||||
{
|
||||
H value;
|
||||
ar( _CEREAL_NVP("data", value) );
|
||||
ar( CEREAL_NVP_("data", value) );
|
||||
variant = value;
|
||||
}
|
||||
else
|
||||
|
@ -80,22 +80,22 @@ namespace cereal
|
|||
|
||||
//! Saving for boost::variant
|
||||
template <class Archive, typename... VariantTypes> inline
|
||||
void save( Archive & ar, boost::variant<VariantTypes...> const & variant )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, boost::variant<VariantTypes...> const & variant )
|
||||
{
|
||||
int32_t which = variant.which();
|
||||
ar( _CEREAL_NVP("which", which) );
|
||||
ar( CEREAL_NVP_("which", which) );
|
||||
variant_detail::variant_save_visitor<Archive> visitor(ar);
|
||||
variant.apply_visitor(visitor);
|
||||
}
|
||||
|
||||
//! Loading for boost::variant
|
||||
template <class Archive, typename... VariantTypes> inline
|
||||
void load( Archive & ar, boost::variant<VariantTypes...> & variant )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, boost::variant<VariantTypes...> & variant )
|
||||
{
|
||||
typedef typename boost::variant<VariantTypes...>::types types;
|
||||
|
||||
int32_t which;
|
||||
ar( _CEREAL_NVP("which", which) );
|
||||
ar( CEREAL_NVP_("which", which) );
|
||||
if(which >= boost::mpl::size<types>::value)
|
||||
throw Exception("Invalid 'which' selector when deserializing boost::variant");
|
||||
|
||||
|
|
|
@ -36,34 +36,34 @@ namespace cereal
|
|||
{
|
||||
//! Saving std::chrono::duration
|
||||
template <class Archive, class R, class P> inline
|
||||
void save( Archive & ar, std::chrono::duration<R, P> const & dur )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::chrono::duration<R, P> const & dur )
|
||||
{
|
||||
ar( _CEREAL_NVP("count", dur.count()) );
|
||||
ar( CEREAL_NVP_("count", dur.count()) );
|
||||
}
|
||||
|
||||
//! Loading std::chrono::duration
|
||||
template <class Archive, class R, class P> inline
|
||||
void load( Archive & ar, std::chrono::duration<R, P> & dur )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::chrono::duration<R, P> & dur )
|
||||
{
|
||||
R count;
|
||||
ar( _CEREAL_NVP("count", count) );
|
||||
ar( CEREAL_NVP_("count", count) );
|
||||
|
||||
dur = std::chrono::duration<R, P>{count};
|
||||
}
|
||||
|
||||
//! Saving std::chrono::time_point
|
||||
template <class Archive, class C, class D> inline
|
||||
void save( Archive & ar, std::chrono::time_point<C, D> const & dur )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::chrono::time_point<C, D> const & dur )
|
||||
{
|
||||
ar( _CEREAL_NVP("time_since_epoch", dur.time_since_epoch()) );
|
||||
ar( CEREAL_NVP_("time_since_epoch", dur.time_since_epoch()) );
|
||||
}
|
||||
|
||||
//! Loading std::chrono::time_point
|
||||
template <class Archive, class C, class D> inline
|
||||
void load( Archive & ar, std::chrono::time_point<C, D> & dur )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::chrono::time_point<C, D> & dur )
|
||||
{
|
||||
D elapsed;
|
||||
ar( _CEREAL_NVP("time_since_epoch", elapsed) );
|
||||
ar( CEREAL_NVP_("time_since_epoch", elapsed) );
|
||||
|
||||
dur = std::chrono::time_point<C, D>{elapsed};
|
||||
}
|
||||
|
|
|
@ -90,8 +90,9 @@ namespace cereal
|
|||
|
||||
//! Saving for enum types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<common_detail::is_enum<T>::value, typename common_detail::is_enum<T>::base_type>::type
|
||||
save_minimal( Archive const &, T const & t )
|
||||
typename std::enable_if<common_detail::is_enum<T>::value,
|
||||
typename common_detail::is_enum<T>::base_type>::type
|
||||
CEREAL_SAVE_MINIMAL_FUNCTION_NAME( Archive const &, T const & t )
|
||||
{
|
||||
return static_cast<typename common_detail::is_enum<T>::base_type>(t);
|
||||
}
|
||||
|
@ -99,7 +100,8 @@ namespace cereal
|
|||
//! Loading for enum types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<common_detail::is_enum<T>::value, void>::type
|
||||
load_minimal( Archive const &, T && t, typename common_detail::is_enum<T>::base_type const & value )
|
||||
CEREAL_LOAD_MINIMAL_FUNCTION_NAME( Archive const &, T && t,
|
||||
typename common_detail::is_enum<T>::base_type const & value )
|
||||
{
|
||||
t = reinterpret_cast<typename common_detail::is_enum<T>::type const &>( value );
|
||||
}
|
||||
|
@ -107,7 +109,7 @@ namespace cereal
|
|||
//! Serialization for raw pointers
|
||||
/*! This exists only to throw a static_assert to let users know we don't support raw pointers. */
|
||||
template <class Archive, class T> inline
|
||||
void serialize( Archive &, T * & )
|
||||
void CEREAL_SERIALIZE_FUNCTION_NAME( Archive &, T * & )
|
||||
{
|
||||
static_assert(cereal::traits::detail::delay_static_assert<T>::value,
|
||||
"Cereal does not support serializing raw pointers - please use a smart pointer");
|
||||
|
@ -116,7 +118,7 @@ namespace cereal
|
|||
//! Serialization for C style arrays
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<std::is_array<T>::value, void>::type
|
||||
serialize(Archive & ar, T & array)
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME(Archive & ar, T & array)
|
||||
{
|
||||
common_detail::serializeArray( ar, array,
|
||||
std::integral_constant<bool, traits::is_output_serializable<BinaryData<T>, Archive>::value &&
|
||||
|
|
|
@ -36,19 +36,19 @@ namespace cereal
|
|||
{
|
||||
//! Serializing (save) for std::complex
|
||||
template <class Archive, class T> inline
|
||||
void save( Archive & ar, std::complex<T> const & comp )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::complex<T> const & comp )
|
||||
{
|
||||
ar( _CEREAL_NVP("real", comp.real()),
|
||||
_CEREAL_NVP("imag", comp.imag()) );
|
||||
ar( CEREAL_NVP_("real", comp.real()),
|
||||
CEREAL_NVP_("imag", comp.imag()) );
|
||||
}
|
||||
|
||||
//! Serializing (load) for std::complex
|
||||
template <class Archive, class T> inline
|
||||
void load( Archive & ar, std::complex<T> & bits )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::complex<T> & bits )
|
||||
{
|
||||
T real, imag;
|
||||
ar( _CEREAL_NVP("real", real),
|
||||
_CEREAL_NVP("imag", imag) );
|
||||
ar( CEREAL_NVP_("real", real),
|
||||
CEREAL_NVP_("imag", imag) );
|
||||
bits = {real, imag};
|
||||
}
|
||||
} // namespace cereal
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace cereal
|
|||
{
|
||||
//! Saving for std::deque
|
||||
template <class Archive, class T, class A> inline
|
||||
void save( Archive & ar, std::deque<T, A> const & deque )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::deque<T, A> const & deque )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(deque.size()) ) );
|
||||
|
||||
|
@ -47,7 +47,7 @@ namespace cereal
|
|||
|
||||
//! Loading for std::deque
|
||||
template <class Archive, class T, class A> inline
|
||||
void load( Archive & ar, std::deque<T, A> & deque )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::deque<T, A> & deque )
|
||||
{
|
||||
size_type size;
|
||||
ar( make_size_tag( size ) );
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace cereal
|
|||
{
|
||||
//! Saving for std::forward_list all other types
|
||||
template <class Archive, class T, class A> inline
|
||||
void save( Archive & ar, std::forward_list<T, A> const & forward_list )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::forward_list<T, A> const & forward_list )
|
||||
{
|
||||
// write the size - note that this is slow because we need to traverse
|
||||
// the entire list. there are ways we could avoid this but this was chosen
|
||||
|
@ -53,7 +53,7 @@ namespace cereal
|
|||
|
||||
//! Loading for std::forward_list all other types from
|
||||
template <class Archive, class T, class A>
|
||||
void load( Archive & ar, std::forward_list<T, A> & forward_list )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::forward_list<T, A> & forward_list )
|
||||
{
|
||||
size_type size;
|
||||
ar( make_size_tag( size ) );
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace cereal
|
|||
{
|
||||
//! Saving for std::list
|
||||
template <class Archive, class T, class A> inline
|
||||
void save( Archive & ar, std::list<T, A> const & list )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::list<T, A> const & list )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(list.size()) ) );
|
||||
|
||||
|
@ -47,7 +47,7 @@ namespace cereal
|
|||
|
||||
//! Loading for std::list
|
||||
template <class Archive, class T, class A> inline
|
||||
void load( Archive & ar, std::list<T, A> & list )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::list<T, A> & list )
|
||||
{
|
||||
size_type size;
|
||||
ar( make_size_tag( size ) );
|
||||
|
|
|
@ -76,14 +76,14 @@ namespace cereal
|
|||
|
||||
//! Saving for std::map
|
||||
template <class Archive, class K, class T, class C, class A> inline
|
||||
void save( Archive & ar, std::map<K, T, C, A> const & map )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::map<K, T, C, A> const & map )
|
||||
{
|
||||
map_detail::save( ar, map );
|
||||
}
|
||||
|
||||
//! Loading for std::map
|
||||
template <class Archive, class K, class T, class C, class A> inline
|
||||
void load( Archive & ar, std::map<K, T, C, A> & map )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::map<K, T, C, A> & map )
|
||||
{
|
||||
map_detail::load( ar, map );
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ namespace cereal
|
|||
//! Saving for std::multimap
|
||||
/*! @note serialization for this type is not guaranteed to preserve ordering */
|
||||
template <class Archive, class K, class T, class C, class A> inline
|
||||
void save( Archive & ar, std::multimap<K, T, C, A> const & multimap )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::multimap<K, T, C, A> const & multimap )
|
||||
{
|
||||
map_detail::save( ar, multimap );
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ namespace cereal
|
|||
//! Loading for std::multimap
|
||||
/*! @note serialization for this type is not guaranteed to preserve ordering */
|
||||
template <class Archive, class K, class T, class C, class A> inline
|
||||
void load( Archive & ar, std::multimap<K, T, C, A> & multimap )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::multimap<K, T, C, A> & multimap )
|
||||
{
|
||||
map_detail::load( ar, multimap );
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ namespace cereal
|
|||
construct( ptr )
|
||||
{ }
|
||||
|
||||
inline void serialize( Archive & ar )
|
||||
inline void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar )
|
||||
{
|
||||
::cereal::detail::Construct<T, Archive>::load_andor_construct( ar, construct );
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ namespace cereal
|
|||
memory_detail::EnableSharedStateHelper<T> state( ptr );
|
||||
|
||||
// let the user perform their initialization
|
||||
ar( _CEREAL_NVP("data", loadWrapper) );
|
||||
ar( CEREAL_NVP_("data", loadWrapper) );
|
||||
}
|
||||
|
||||
//! Performs loading and construction for a shared pointer that is NOT derived from
|
||||
|
@ -167,59 +167,59 @@ namespace cereal
|
|||
void loadAndConstructSharedPtr( Archive & ar, T * ptr, std::false_type /* has_shared_from_this */ )
|
||||
{
|
||||
memory_detail::LoadAndConstructLoadWrapper<Archive, T> loadWrapper( ptr );
|
||||
ar( _CEREAL_NVP("data", loadWrapper) );
|
||||
ar( CEREAL_NVP_("data", loadWrapper) );
|
||||
}
|
||||
} // end namespace memory_detail
|
||||
|
||||
//! Saving std::shared_ptr for non polymorphic types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<!std::is_polymorphic<T>::value, void>::type
|
||||
save( Archive & ar, std::shared_ptr<T> const & ptr )
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::shared_ptr<T> const & ptr )
|
||||
{
|
||||
ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) );
|
||||
}
|
||||
|
||||
//! Loading std::shared_ptr, case when no user load and construct for non polymorphic types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<!std::is_polymorphic<T>::value, void>::type
|
||||
load( Archive & ar, std::shared_ptr<T> & ptr )
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::shared_ptr<T> & ptr )
|
||||
{
|
||||
ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) );
|
||||
}
|
||||
|
||||
//! Saving std::weak_ptr for non polymorphic types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<!std::is_polymorphic<T>::value, void>::type
|
||||
save( Archive & ar, std::weak_ptr<T> const & ptr )
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::weak_ptr<T> const & ptr )
|
||||
{
|
||||
auto const sptr = ptr.lock();
|
||||
ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( sptr )) );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( sptr )) );
|
||||
}
|
||||
|
||||
//! Loading std::weak_ptr for non polymorphic types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<!std::is_polymorphic<T>::value, void>::type
|
||||
load( Archive & ar, std::weak_ptr<T> & ptr )
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::weak_ptr<T> & ptr )
|
||||
{
|
||||
std::shared_ptr<T> sptr;
|
||||
ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( sptr )) );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( sptr )) );
|
||||
ptr = sptr;
|
||||
}
|
||||
|
||||
//! Saving std::unique_ptr for non polymorphic types
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<!std::is_polymorphic<T>::value, void>::type
|
||||
save( Archive & ar, std::unique_ptr<T, D> const & ptr )
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unique_ptr<T, D> const & ptr )
|
||||
{
|
||||
ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) );
|
||||
}
|
||||
|
||||
//! Loading std::unique_ptr, case when user provides load_and_construct for non polymorphic types
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<!std::is_polymorphic<T>::value, void>::type
|
||||
load( Archive & ar, std::unique_ptr<T, D> & ptr )
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unique_ptr<T, D> & ptr )
|
||||
{
|
||||
ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) );
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
|
@ -228,16 +228,16 @@ namespace cereal
|
|||
//! Saving std::shared_ptr (wrapper implementation)
|
||||
/*! @internal */
|
||||
template <class Archive, class T> inline
|
||||
void save( Archive & ar, memory_detail::PtrWrapper<std::shared_ptr<T> const &> const & wrapper )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper<std::shared_ptr<T> const &> const & wrapper )
|
||||
{
|
||||
auto & ptr = wrapper.ptr;
|
||||
|
||||
uint32_t id = ar.registerSharedPointer( ptr.get() );
|
||||
ar( _CEREAL_NVP("id", id) );
|
||||
ar( CEREAL_NVP_("id", id) );
|
||||
|
||||
if( id & detail::msb_32bit )
|
||||
{
|
||||
ar( _CEREAL_NVP("data", *ptr) );
|
||||
ar( CEREAL_NVP_("data", *ptr) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,13 +245,13 @@ namespace cereal
|
|||
/*! @internal */
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<traits::has_load_and_construct<T, Archive>::value, void>::type
|
||||
load( Archive & ar, memory_detail::PtrWrapper<std::shared_ptr<T> &> & wrapper )
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper<std::shared_ptr<T> &> & wrapper )
|
||||
{
|
||||
auto & ptr = wrapper.ptr;
|
||||
|
||||
uint32_t id;
|
||||
|
||||
ar( _CEREAL_NVP("id", id) );
|
||||
ar( CEREAL_NVP_("id", id) );
|
||||
|
||||
if( id & detail::msb_32bit )
|
||||
{
|
||||
|
@ -292,19 +292,19 @@ namespace cereal
|
|||
/*! @internal */
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<!traits::has_load_and_construct<T, Archive>::value, void>::type
|
||||
load( Archive & ar, memory_detail::PtrWrapper<std::shared_ptr<T> &> & wrapper )
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper<std::shared_ptr<T> &> & wrapper )
|
||||
{
|
||||
auto & ptr = wrapper.ptr;
|
||||
|
||||
uint32_t id;
|
||||
|
||||
ar( _CEREAL_NVP("id", id) );
|
||||
ar( CEREAL_NVP_("id", id) );
|
||||
|
||||
if( id & detail::msb_32bit )
|
||||
{
|
||||
ptr.reset( detail::Construct<T, Archive>::load_andor_construct() );
|
||||
ar.registerSharedPointer( id, ptr );
|
||||
ar( _CEREAL_NVP("data", *ptr) );
|
||||
ar( CEREAL_NVP_("data", *ptr) );
|
||||
}
|
||||
else
|
||||
ptr = std::static_pointer_cast<T>(ar.getSharedPointer(id));
|
||||
|
@ -313,7 +313,7 @@ namespace cereal
|
|||
//! Saving std::unique_ptr (wrapper implementation)
|
||||
/*! @internal */
|
||||
template <class Archive, class T, class D> inline
|
||||
void save( Archive & ar, memory_detail::PtrWrapper<std::unique_ptr<T, D> const &> const & wrapper )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper<std::unique_ptr<T, D> const &> const & wrapper )
|
||||
{
|
||||
auto & ptr = wrapper.ptr;
|
||||
|
||||
|
@ -322,11 +322,11 @@ namespace cereal
|
|||
// 1 == not null
|
||||
|
||||
if( !ptr )
|
||||
ar( _CEREAL_NVP("valid", uint8_t(0)) );
|
||||
ar( CEREAL_NVP_("valid", uint8_t(0)) );
|
||||
else
|
||||
{
|
||||
ar( _CEREAL_NVP("valid", uint8_t(1)) );
|
||||
ar( _CEREAL_NVP("data", *ptr) );
|
||||
ar( CEREAL_NVP_("valid", uint8_t(1)) );
|
||||
ar( CEREAL_NVP_("data", *ptr) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,10 +334,10 @@ namespace cereal
|
|||
/*! @internal */
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<traits::has_load_and_construct<T, Archive>::value, void>::type
|
||||
load( Archive & ar, memory_detail::PtrWrapper<std::unique_ptr<T, D> &> & wrapper )
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper<std::unique_ptr<T, D> &> & wrapper )
|
||||
{
|
||||
uint8_t isValid;
|
||||
ar( _CEREAL_NVP("valid", isValid) );
|
||||
ar( CEREAL_NVP_("valid", isValid) );
|
||||
|
||||
auto & ptr = wrapper.ptr;
|
||||
|
||||
|
@ -355,7 +355,7 @@ namespace cereal
|
|||
memory_detail::LoadAndConstructLoadWrapper<Archive, T> loadWrapper( reinterpret_cast<T *>( stPtr.get() ) );
|
||||
|
||||
// Initialize storage
|
||||
ar( _CEREAL_NVP("data", loadWrapper) );
|
||||
ar( CEREAL_NVP_("data", loadWrapper) );
|
||||
|
||||
// Transfer ownership to correct unique_ptr type
|
||||
ptr.reset( reinterpret_cast<T *>( stPtr.release() ) );
|
||||
|
@ -368,17 +368,17 @@ namespace cereal
|
|||
/*! @internal */
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<!traits::has_load_and_construct<T, Archive>::value, void>::type
|
||||
load( Archive & ar, memory_detail::PtrWrapper<std::unique_ptr<T, D> &> & wrapper )
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper<std::unique_ptr<T, D> &> & wrapper )
|
||||
{
|
||||
uint8_t isValid;
|
||||
ar( _CEREAL_NVP("valid", isValid) );
|
||||
ar( CEREAL_NVP_("valid", isValid) );
|
||||
|
||||
auto & ptr = wrapper.ptr;
|
||||
|
||||
if( isValid )
|
||||
{
|
||||
ptr.reset( detail::Construct<T, Archive>::load_andor_construct() );
|
||||
ar( *ptr );
|
||||
ar( CEREAL_NVP_( "data", *ptr ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -44,19 +44,39 @@
|
|||
#define STATIC_CONSTEXPR static constexpr
|
||||
#endif
|
||||
|
||||
//! Registers a polymorphic type with cereal
|
||||
/*! Polymorphic types must be registered before pointers
|
||||
to them can be serialized. This also assumes that
|
||||
all relevent archives have also previously been
|
||||
registered. Registration for archives is usually done
|
||||
in the header file in which they are defined. This means
|
||||
that type registration needs to happen after specific
|
||||
archives to be used are included.
|
||||
//! Registers a derived polymorphic type with cereal
|
||||
/*! Polymorphic types must be registered before smart
|
||||
pointers to them can be serialized. Note that base
|
||||
classes do not need to be registered.
|
||||
|
||||
Registering a type lets cereal know how to properly
|
||||
serialize it when a pointer to a base object is
|
||||
serialize it when a smart pointer to a base object is
|
||||
used in conjunction with a derived class.
|
||||
|
||||
This assumes that all relevant archives have also
|
||||
previously been registered. Registration for archives
|
||||
is usually done in the header file in which they are
|
||||
defined. This means that type registration needs to
|
||||
happen after specific archives to be used are included.
|
||||
|
||||
It is recommended that type registration be done in
|
||||
the header file in which the type is declared.
|
||||
|
||||
Registration can also be placed in a source file,
|
||||
but this may require the use of the
|
||||
CEREAL_REGISTER_DYNAMIC_INIT macro (see below).
|
||||
|
||||
Registration may be called repeatedly for the same
|
||||
type in different translation units to add support
|
||||
for additional archives if they are not initially
|
||||
available (included and registered).
|
||||
|
||||
When building serialization support as a DLL on
|
||||
Windows, registration must happen in the header file.
|
||||
On Linux and Mac things should still work properly
|
||||
if placed in a source file, but see the above comments
|
||||
on registering in source files.
|
||||
|
||||
Polymorphic support in cereal requires RTTI to be
|
||||
enabled */
|
||||
#define CEREAL_REGISTER_TYPE(T) \
|
||||
|
@ -85,6 +105,57 @@
|
|||
} } /* end namespaces */ \
|
||||
CEREAL_BIND_TO_ARCHIVES(T)
|
||||
|
||||
//! Adds a way to force initialization of a translation unit containing
|
||||
//! calls to CEREAL_REGISTER_TYPE
|
||||
/*! In C++, dynamic initialization of non-local variables of a translation
|
||||
unit may be deferred until "the first odr-use of any function or variable
|
||||
defined in the same translation unit as the variable to be initialized."
|
||||
|
||||
Informally, odr-use means that your program takes the address of or binds
|
||||
a reference directly to an object, which must have a definition.
|
||||
|
||||
Since polymorphic type support in cereal relies on the dynamic
|
||||
initialization of certain global objects happening before
|
||||
serialization is performed, it is important to ensure that something
|
||||
from files that call CEREAL_REGISTER_TYPE is odr-used before serialization
|
||||
occurs, otherwise the registration will never take place. This may often
|
||||
be the case when serialization is built as a shared library external from
|
||||
your main program.
|
||||
|
||||
This macro, with any name of your choosing, should be placed into the
|
||||
source file that contains calls to CEREAL_REGISTER_TYPE.
|
||||
|
||||
Its counterpart, CEREAL_FORCE_DYNAMIC_INIT, should be placed in its
|
||||
associated header file such that it is included in the translation units
|
||||
(source files) in which you want the registration to appear.
|
||||
|
||||
@relates CEREAL_FORCE_DYNAMIC_INIT
|
||||
*/
|
||||
#define CEREAL_REGISTER_DYNAMIC_INIT(LibName) \
|
||||
namespace cereal { \
|
||||
namespace detail { \
|
||||
void CEREAL_DLL_EXPORT dynamic_init_dummy_##LibName() {} \
|
||||
} } /* end namespaces */
|
||||
|
||||
//! Forces dynamic initialization of polymorphic support in a
|
||||
//! previously registered source file
|
||||
/*! @sa CEREAL_REGISTER_DYNAMIC_INIT
|
||||
|
||||
See CEREAL_REGISTER_DYNAMIC_INIT for detailed explanation
|
||||
of how this macro should be used. The name used should
|
||||
match that for CEREAL_REGISTER_DYNAMIC_INIT. */
|
||||
#define CEREAL_FORCE_DYNAMIC_INIT(LibName) \
|
||||
namespace cereal { \
|
||||
namespace detail { \
|
||||
void dynamic_init_dummy_##LibName(); \
|
||||
} /* end detail */ \
|
||||
namespace { \
|
||||
void dynamic_init_##LibName() \
|
||||
{ \
|
||||
::cereal::detail::dynamic_init_dummy_##LibName(); \
|
||||
} \
|
||||
} } /* end namespaces */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#undef CONSTEXPR
|
||||
#endif
|
||||
|
@ -93,6 +164,14 @@ namespace cereal
|
|||
{
|
||||
namespace polymorphic_detail
|
||||
{
|
||||
//! Error message used for unregistered polymorphic types
|
||||
/*! @internal */
|
||||
#define UNREGISTERED_POLYMORPHIC_EXCEPTION(LoadSave, Name) \
|
||||
throw cereal::Exception("Trying to " #LoadSave " an unregistered polymorphic type (" + Name + ").\n" \
|
||||
"Make sure your type is registered with CEREAL_REGISTER_TYPE and that the archive " \
|
||||
"you are using was included (and registered with CEREAL_REGISTER_ARCHIVE) prior to calling CEREAL_REGISTER_TYPE.\n" \
|
||||
"If your type is already registered and you still see this error, you may need to use CEREAL_REGISTER_DYNAMIC_INIT.");
|
||||
|
||||
//! Get an input binding from the given archive by deserializing the type meta data
|
||||
/*! @internal */
|
||||
template<class Archive> inline
|
||||
|
@ -110,7 +189,7 @@ namespace cereal
|
|||
std::string name;
|
||||
if(nameid & detail::msb_32bit)
|
||||
{
|
||||
ar( _CEREAL_NVP("polymorphic_name", name) );
|
||||
ar( CEREAL_NVP_("polymorphic_name", name) );
|
||||
ar.registerPolymorphicName(nameid, name);
|
||||
}
|
||||
else
|
||||
|
@ -120,7 +199,7 @@ namespace cereal
|
|||
|
||||
auto binding = bindingMap.find(name);
|
||||
if(binding == bindingMap.end())
|
||||
throw cereal::Exception("Trying to load an unregistered polymorphic type (" + name + ")");
|
||||
UNREGISTERED_POLYMORPHIC_EXCEPTION(load, name)
|
||||
return binding->second;
|
||||
}
|
||||
|
||||
|
@ -132,14 +211,14 @@ namespace cereal
|
|||
default constructors, but on clang/gcc this will return false. So we also need to check for that here.
|
||||
@internal */
|
||||
template<class Archive, class T> inline
|
||||
typename std::enable_if<(std::is_default_constructible<T>::value
|
||||
typename std::enable_if<(traits::is_default_constructible<T>::value
|
||||
|| traits::has_load_and_construct<T, Archive>::value)
|
||||
&& !std::is_abstract<T>::value, bool>::type
|
||||
serialize_wrapper(Archive & ar, std::shared_ptr<T> & ptr, std::uint32_t const nameid)
|
||||
{
|
||||
if(nameid & detail::msb2_32bit)
|
||||
{
|
||||
ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -150,14 +229,14 @@ namespace cereal
|
|||
using the derived class serialize function
|
||||
@internal */
|
||||
template<class Archive, class T, class D> inline
|
||||
typename std::enable_if<(std::is_default_constructible<T>::value
|
||||
typename std::enable_if<(traits::is_default_constructible<T>::value
|
||||
|| traits::has_load_and_construct<T, Archive>::value)
|
||||
&& !std::is_abstract<T>::value, bool>::type
|
||||
serialize_wrapper(Archive & ar, std::unique_ptr<T, D> & ptr, std::uint32_t const nameid)
|
||||
{
|
||||
if(nameid & detail::msb2_32bit)
|
||||
{
|
||||
ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -170,7 +249,7 @@ namespace cereal
|
|||
this was a polymorphic type serialized by its proper pointer type
|
||||
@internal */
|
||||
template<class Archive, class T> inline
|
||||
typename std::enable_if<(!std::is_default_constructible<T>::value
|
||||
typename std::enable_if<(!traits::is_default_constructible<T>::value
|
||||
&& !traits::has_load_and_construct<T, Archive>::value)
|
||||
|| std::is_abstract<T>::value, bool>::type
|
||||
serialize_wrapper(Archive &, std::shared_ptr<T> &, std::uint32_t const nameid)
|
||||
|
@ -187,7 +266,7 @@ namespace cereal
|
|||
this was a polymorphic type serialized by its proper pointer type
|
||||
@internal */
|
||||
template<class Archive, class T, class D> inline
|
||||
typename std::enable_if<(!std::is_default_constructible<T>::value
|
||||
typename std::enable_if<(!traits::is_default_constructible<T>::value
|
||||
&& !traits::has_load_and_construct<T, Archive>::value)
|
||||
|| std::is_abstract<T>::value, bool>::type
|
||||
serialize_wrapper(Archive &, std::unique_ptr<T, D> &, std::uint32_t const nameid)
|
||||
|
@ -204,12 +283,12 @@ namespace cereal
|
|||
//! Saving std::shared_ptr for polymorphic types, abstract
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value && std::is_abstract<T>::value, void>::type
|
||||
save( Archive & ar, std::shared_ptr<T> const & ptr )
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::shared_ptr<T> const & ptr )
|
||||
{
|
||||
if(!ptr)
|
||||
{
|
||||
// same behavior as nullptr in memory implementation
|
||||
ar( _CEREAL_NVP("polymorphic_id", std::uint32_t(0)) );
|
||||
ar( CEREAL_NVP_("polymorphic_id", std::uint32_t(0)) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -222,7 +301,7 @@ namespace cereal
|
|||
|
||||
auto binding = bindingMap.find(std::type_index(ptrinfo));
|
||||
if(binding == bindingMap.end())
|
||||
throw cereal::Exception("Trying to save an unregistered polymorphic type (" + cereal::util::demangle(ptrinfo.name()) + ")");
|
||||
UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name()))
|
||||
|
||||
binding->second.shared_ptr(&ar, ptr.get());
|
||||
}
|
||||
|
@ -230,12 +309,12 @@ namespace cereal
|
|||
//! Saving std::shared_ptr for polymorphic types, not abstract
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value && !std::is_abstract<T>::value, void>::type
|
||||
save( Archive & ar, std::shared_ptr<T> const & ptr )
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::shared_ptr<T> const & ptr )
|
||||
{
|
||||
if(!ptr)
|
||||
{
|
||||
// same behavior as nullptr in memory implementation
|
||||
ar( _CEREAL_NVP("polymorphic_id", std::uint32_t(0)) );
|
||||
ar( CEREAL_NVP_("polymorphic_id", std::uint32_t(0)) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -246,9 +325,9 @@ namespace cereal
|
|||
{
|
||||
// The 2nd msb signals that the following pointer does not need to be
|
||||
// cast with our polymorphic machinery
|
||||
ar( _CEREAL_NVP("polymorphic_id", detail::msb2_32bit) );
|
||||
ar( CEREAL_NVP_("polymorphic_id", detail::msb2_32bit) );
|
||||
|
||||
ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -257,7 +336,7 @@ namespace cereal
|
|||
|
||||
auto binding = bindingMap.find(std::type_index(ptrinfo));
|
||||
if(binding == bindingMap.end())
|
||||
throw cereal::Exception("Trying to save an unregistered polymorphic type (" + cereal::util::demangle(ptrinfo.name()) + ")");
|
||||
UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name()))
|
||||
|
||||
binding->second.shared_ptr(&ar, ptr.get());
|
||||
}
|
||||
|
@ -265,10 +344,10 @@ namespace cereal
|
|||
//! Loading std::shared_ptr for polymorphic types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value, void>::type
|
||||
load( Archive & ar, std::shared_ptr<T> & ptr )
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::shared_ptr<T> & ptr )
|
||||
{
|
||||
std::uint32_t nameid;
|
||||
ar( _CEREAL_NVP("polymorphic_id", nameid) );
|
||||
ar( CEREAL_NVP_("polymorphic_id", nameid) );
|
||||
|
||||
// Check to see if we can skip all of this polymorphism business
|
||||
if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid))
|
||||
|
@ -283,31 +362,31 @@ namespace cereal
|
|||
//! Saving std::weak_ptr for polymorphic types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value, void>::type
|
||||
save( Archive & ar, std::weak_ptr<T> const & ptr )
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::weak_ptr<T> const & ptr )
|
||||
{
|
||||
auto const sptr = ptr.lock();
|
||||
ar( _CEREAL_NVP("locked_ptr", sptr) );
|
||||
ar( CEREAL_NVP_("locked_ptr", sptr) );
|
||||
}
|
||||
|
||||
//! Loading std::weak_ptr for polymorphic types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value, void>::type
|
||||
load( Archive & ar, std::weak_ptr<T> & ptr )
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::weak_ptr<T> & ptr )
|
||||
{
|
||||
std::shared_ptr<T> sptr;
|
||||
ar( _CEREAL_NVP("locked_ptr", sptr) );
|
||||
ar( CEREAL_NVP_("locked_ptr", sptr) );
|
||||
ptr = sptr;
|
||||
}
|
||||
|
||||
//! Saving std::unique_ptr for polymorphic types that are abstract
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value && std::is_abstract<T>::value, void>::type
|
||||
save( Archive & ar, std::unique_ptr<T, D> const & ptr )
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unique_ptr<T, D> const & ptr )
|
||||
{
|
||||
if(!ptr)
|
||||
{
|
||||
// same behavior as nullptr in memory implementation
|
||||
ar( _CEREAL_NVP("polymorphic_id", std::uint32_t(0)) );
|
||||
ar( CEREAL_NVP_("polymorphic_id", std::uint32_t(0)) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -320,7 +399,7 @@ namespace cereal
|
|||
|
||||
auto binding = bindingMap.find(std::type_index(ptrinfo));
|
||||
if(binding == bindingMap.end())
|
||||
throw cereal::Exception("Trying to save an unregistered polymorphic type (" + cereal::util::demangle(ptrinfo.name()) + ")");
|
||||
UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name()))
|
||||
|
||||
binding->second.unique_ptr(&ar, ptr.get());
|
||||
}
|
||||
|
@ -328,12 +407,12 @@ namespace cereal
|
|||
//! Saving std::unique_ptr for polymorphic types, not abstract
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value && !std::is_abstract<T>::value, void>::type
|
||||
save( Archive & ar, std::unique_ptr<T, D> const & ptr )
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unique_ptr<T, D> const & ptr )
|
||||
{
|
||||
if(!ptr)
|
||||
{
|
||||
// same behavior as nullptr in memory implementation
|
||||
ar( _CEREAL_NVP("polymorphic_id", std::uint32_t(0)) );
|
||||
ar( CEREAL_NVP_("polymorphic_id", std::uint32_t(0)) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -344,9 +423,9 @@ namespace cereal
|
|||
{
|
||||
// The 2nd msb signals that the following pointer does not need to be
|
||||
// cast with our polymorphic machinery
|
||||
ar( _CEREAL_NVP("polymorphic_id", detail::msb2_32bit) );
|
||||
ar( CEREAL_NVP_("polymorphic_id", detail::msb2_32bit) );
|
||||
|
||||
ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -355,7 +434,7 @@ namespace cereal
|
|||
|
||||
auto binding = bindingMap.find(std::type_index(ptrinfo));
|
||||
if(binding == bindingMap.end())
|
||||
throw cereal::Exception("Trying to save an unregistered polymorphic type (" + cereal::util::demangle(ptrinfo.name()) + ")");
|
||||
UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name()))
|
||||
|
||||
binding->second.unique_ptr(&ar, ptr.get());
|
||||
}
|
||||
|
@ -363,10 +442,10 @@ namespace cereal
|
|||
//! Loading std::unique_ptr, case when user provides load_and_construct for polymorphic types
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value, void>::type
|
||||
load( Archive & ar, std::unique_ptr<T, D> & ptr )
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unique_ptr<T, D> & ptr )
|
||||
{
|
||||
std::uint32_t nameid;
|
||||
ar( _CEREAL_NVP("polymorphic_id", nameid) );
|
||||
ar( CEREAL_NVP_("polymorphic_id", nameid) );
|
||||
|
||||
// Check to see if we can skip all of this polymorphism business
|
||||
if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid))
|
||||
|
@ -377,5 +456,7 @@ namespace cereal
|
|||
binding.unique_ptr(&ar, result);
|
||||
ptr.reset(static_cast<T*>(result.release()));
|
||||
}
|
||||
|
||||
#undef UNREGISTERED_POLYMORPHIC_EXCEPTION
|
||||
} // namespace cereal
|
||||
#endif // CEREAL_TYPES_POLYMORPHIC_HPP_
|
||||
|
|
|
@ -91,37 +91,37 @@ namespace cereal
|
|||
|
||||
//! Saving for std::queue
|
||||
template <class Archive, class T, class C> inline
|
||||
void save( Archive & ar, std::queue<T, C> const & queue )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::queue<T, C> const & queue )
|
||||
{
|
||||
ar( _CEREAL_NVP("container", queue_detail::container( queue )) );
|
||||
ar( CEREAL_NVP_("container", queue_detail::container( queue )) );
|
||||
}
|
||||
|
||||
//! Loading for std::queue
|
||||
template <class Archive, class T, class C> inline
|
||||
void load( Archive & ar, std::queue<T, C> & queue )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::queue<T, C> & queue )
|
||||
{
|
||||
C container;
|
||||
ar( _CEREAL_NVP("container", container) );
|
||||
ar( CEREAL_NVP_("container", container) );
|
||||
queue = std::queue<T, C>( std::move( container ) );
|
||||
}
|
||||
|
||||
//! Saving for std::priority_queue
|
||||
template <class Archive, class T, class C, class Comp> inline
|
||||
void save( Archive & ar, std::priority_queue<T, C, Comp> const & priority_queue )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::priority_queue<T, C, Comp> const & priority_queue )
|
||||
{
|
||||
ar( _CEREAL_NVP("comparator", queue_detail::comparator( priority_queue )) );
|
||||
ar( _CEREAL_NVP("container", queue_detail::container( priority_queue )) );
|
||||
ar( CEREAL_NVP_("comparator", queue_detail::comparator( priority_queue )) );
|
||||
ar( CEREAL_NVP_("container", queue_detail::container( priority_queue )) );
|
||||
}
|
||||
|
||||
//! Loading for std::priority_queue
|
||||
template <class Archive, class T, class C, class Comp> inline
|
||||
void load( Archive & ar, std::priority_queue<T, C, Comp> & priority_queue )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::priority_queue<T, C, Comp> & priority_queue )
|
||||
{
|
||||
Comp comparator;
|
||||
ar( _CEREAL_NVP("comparator", comparator) );
|
||||
ar( CEREAL_NVP_("comparator", comparator) );
|
||||
|
||||
C container;
|
||||
ar( _CEREAL_NVP("container", container) );
|
||||
ar( CEREAL_NVP_("container", container) );
|
||||
|
||||
priority_queue = std::priority_queue<T, C, Comp>( comparator, std::move( container ) );
|
||||
}
|
||||
|
|
|
@ -73,28 +73,28 @@ namespace cereal
|
|||
|
||||
//! Saving for std::set
|
||||
template <class Archive, class K, class C, class A> inline
|
||||
void save( Archive & ar, std::set<K, C, A> const & set )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::set<K, C, A> const & set )
|
||||
{
|
||||
set_detail::save( ar, set );
|
||||
}
|
||||
|
||||
//! Loading for std::set
|
||||
template <class Archive, class K, class C, class A> inline
|
||||
void load( Archive & ar, std::set<K, C, A> & set )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::set<K, C, A> & set )
|
||||
{
|
||||
set_detail::load( ar, set );
|
||||
}
|
||||
|
||||
//! Saving for std::multiset
|
||||
template <class Archive, class K, class C, class A> inline
|
||||
void save( Archive & ar, std::multiset<K, C, A> const & multiset )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::multiset<K, C, A> const & multiset )
|
||||
{
|
||||
set_detail::save( ar, multiset );
|
||||
}
|
||||
|
||||
//! Loading for std::multiset
|
||||
template <class Archive, class K, class C, class A> inline
|
||||
void load( Archive & ar, std::multiset<K, C, A> & multiset )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::multiset<K, C, A> & multiset )
|
||||
{
|
||||
set_detail::load( ar, multiset );
|
||||
}
|
||||
|
|
|
@ -58,17 +58,17 @@ namespace cereal
|
|||
|
||||
//! Saving for std::stack
|
||||
template <class Archive, class T, class C> inline
|
||||
void save( Archive & ar, std::stack<T, C> const & stack )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::stack<T, C> const & stack )
|
||||
{
|
||||
ar( _CEREAL_NVP("container", stack_detail::container( stack )) );
|
||||
ar( CEREAL_NVP_("container", stack_detail::container( stack )) );
|
||||
}
|
||||
|
||||
//! Loading for std::stack
|
||||
template <class Archive, class T, class C> inline
|
||||
void load( Archive & ar, std::stack<T, C> & stack )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::stack<T, C> & stack )
|
||||
{
|
||||
C container;
|
||||
ar( _CEREAL_NVP("container", container) );
|
||||
ar( CEREAL_NVP_("container", container) );
|
||||
stack = std::stack<T, C>( std::move( container ) );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace cereal
|
|||
//! Serialization for basic_string types, if binary data is supported
|
||||
template<class Archive, class CharT, class Traits, class Alloc> inline
|
||||
typename std::enable_if<traits::is_output_serializable<BinaryData<CharT>, Archive>::value, void>::type
|
||||
save(Archive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
|
||||
CEREAL_SAVE_FUNCTION_NAME(Archive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
|
||||
{
|
||||
// Save number of chars + the data
|
||||
ar( make_size_tag( static_cast<size_type>(str.size()) ) );
|
||||
|
@ -48,7 +48,7 @@ namespace cereal
|
|||
//! Serialization for basic_string types, if binary data is supported
|
||||
template<class Archive, class CharT, class Traits, class Alloc> inline
|
||||
typename std::enable_if<traits::is_input_serializable<BinaryData<CharT>, Archive>::value, void>::type
|
||||
load(Archive & ar, std::basic_string<CharT, Traits, Alloc> & str)
|
||||
CEREAL_LOAD_FUNCTION_NAME(Archive & ar, std::basic_string<CharT, Traits, Alloc> & str)
|
||||
{
|
||||
size_type size;
|
||||
ar( make_size_tag( size ) );
|
||||
|
|
|
@ -37,6 +37,56 @@ namespace cereal
|
|||
{
|
||||
namespace tuple_detail
|
||||
{
|
||||
//! Creates a c string from a sequence of characters
|
||||
/*! The c string created will alwas be prefixed by "tuple_element"
|
||||
Based on code from: http://stackoverflow/a/20973438/710791
|
||||
@internal */
|
||||
template<char...Cs>
|
||||
struct char_seq_to_c_str
|
||||
{
|
||||
static const int size = 14;// Size of array for the word: tuple_element
|
||||
typedef const char (&arr_type)[sizeof...(Cs) + size];
|
||||
static const char str[sizeof...(Cs) + size];
|
||||
};
|
||||
|
||||
// the word tuple_element plus a number
|
||||
//! @internal
|
||||
template<char...Cs>
|
||||
const char char_seq_to_c_str<Cs...>::str[sizeof...(Cs) + size] =
|
||||
{'t','u','p','l','e','_','e','l','e','m','e','n','t', Cs..., '\0'};
|
||||
|
||||
//! Converts a number into a sequence of characters
|
||||
/*! @tparam Q The quotient of dividing the original number by 10
|
||||
@tparam R The remainder of dividing the original number by 10
|
||||
@tparam C The sequence built so far
|
||||
@internal */
|
||||
template <size_t Q, size_t R, char ... C>
|
||||
struct to_string_impl
|
||||
{
|
||||
using type = typename to_string_impl<Q/1, Q%10, R+'0', C...>::type;
|
||||
};
|
||||
|
||||
//! Base case with no quotient
|
||||
/*! @internal */
|
||||
template <size_t R, char ... C>
|
||||
struct to_string_impl<0, R, C...>
|
||||
{
|
||||
using type = char_seq_to_c_str<R+'0', C...>;
|
||||
};
|
||||
|
||||
//! Generates a c string for a given index of a tuple
|
||||
/*! Example use:
|
||||
@code{cpp}
|
||||
tuple_element_name<3>::c_str();// returns "tuple_element3"
|
||||
@endcode
|
||||
@internal */
|
||||
template<size_t T>
|
||||
struct tuple_element_name
|
||||
{
|
||||
using type = typename to_string_impl<T/10, T%10>::type;
|
||||
static const typename type::arr_type c_str(){ return type::str; };
|
||||
};
|
||||
|
||||
// unwinds a tuple to save it
|
||||
//! @internal
|
||||
template <size_t Height>
|
||||
|
@ -45,8 +95,9 @@ namespace cereal
|
|||
template <class Archive, class ... Types> inline
|
||||
static void apply( Archive & ar, std::tuple<Types...> & tuple )
|
||||
{
|
||||
ar( _CEREAL_NVP("tuple_element", std::get<Height - 1>( tuple )) );
|
||||
serialize<Height - 1>::template apply( ar, tuple );
|
||||
ar( CEREAL_NVP_(tuple_element_name<Height - 1>::c_str(),
|
||||
std::get<Height - 1>( tuple )) );
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -63,7 +114,7 @@ namespace cereal
|
|||
|
||||
//! Serializing for std::tuple
|
||||
template <class Archive, class ... Types> inline
|
||||
void serialize( Archive & ar, std::tuple<Types...> & tuple )
|
||||
void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, std::tuple<Types...> & tuple )
|
||||
{
|
||||
tuple_detail::serialize<std::tuple_size<std::tuple<Types...>>::value>::template apply( ar, tuple );
|
||||
}
|
||||
|
|
|
@ -70,28 +70,28 @@ namespace cereal
|
|||
|
||||
//! Saving for std::unordered_map
|
||||
template <class Archive, class K, class T, class H, class KE, class A> inline
|
||||
void save( Archive & ar, std::unordered_map<K, T, H, KE, A> const & unordered_map )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unordered_map<K, T, H, KE, A> const & unordered_map )
|
||||
{
|
||||
unordered_map_detail::save( ar, unordered_map );
|
||||
}
|
||||
|
||||
//! Loading for std::unordered_map
|
||||
template <class Archive, class K, class T, class H, class KE, class A> inline
|
||||
void load( Archive & ar, std::unordered_map<K, T, H, KE, A> & unordered_map )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unordered_map<K, T, H, KE, A> & unordered_map )
|
||||
{
|
||||
unordered_map_detail::load( ar, unordered_map );
|
||||
}
|
||||
|
||||
//! Saving for std::unordered_multimap
|
||||
template <class Archive, class K, class T, class H, class KE, class A> inline
|
||||
void save( Archive & ar, std::unordered_multimap<K, T, H, KE, A> const & unordered_multimap )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unordered_multimap<K, T, H, KE, A> const & unordered_multimap )
|
||||
{
|
||||
unordered_map_detail::save( ar, unordered_multimap );
|
||||
}
|
||||
|
||||
//! Loading for std::unordered_multimap
|
||||
template <class Archive, class K, class T, class H, class KE, class A> inline
|
||||
void load( Archive & ar, std::unordered_multimap<K, T, H, KE, A> & unordered_multimap )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unordered_multimap<K, T, H, KE, A> & unordered_multimap )
|
||||
{
|
||||
unordered_map_detail::load( ar, unordered_multimap );
|
||||
}
|
||||
|
|
|
@ -69,28 +69,28 @@ namespace cereal
|
|||
|
||||
//! Saving for std::unordered_set
|
||||
template <class Archive, class K, class H, class KE, class A> inline
|
||||
void save( Archive & ar, std::unordered_set<K, H, KE, A> const & unordered_set )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unordered_set<K, H, KE, A> const & unordered_set )
|
||||
{
|
||||
unordered_set_detail::save( ar, unordered_set );
|
||||
}
|
||||
|
||||
//! Loading for std::unordered_set
|
||||
template <class Archive, class K, class H, class KE, class A> inline
|
||||
void load( Archive & ar, std::unordered_set<K, H, KE, A> & unordered_set )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unordered_set<K, H, KE, A> & unordered_set )
|
||||
{
|
||||
unordered_set_detail::load( ar, unordered_set );
|
||||
}
|
||||
|
||||
//! Saving for std::unordered_multiset
|
||||
template <class Archive, class K, class H, class KE, class A> inline
|
||||
void save( Archive & ar, std::unordered_multiset<K, H, KE, A> const & unordered_multiset )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unordered_multiset<K, H, KE, A> const & unordered_multiset )
|
||||
{
|
||||
unordered_set_detail::save( ar, unordered_multiset );
|
||||
}
|
||||
|
||||
//! Loading for std::unordered_multiset
|
||||
template <class Archive, class K, class H, class KE, class A> inline
|
||||
void load( Archive & ar, std::unordered_multiset<K, H, KE, A> & unordered_multiset )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unordered_multiset<K, H, KE, A> & unordered_multiset )
|
||||
{
|
||||
unordered_set_detail::load( ar, unordered_multiset );
|
||||
}
|
||||
|
|
|
@ -37,10 +37,10 @@ namespace cereal
|
|||
{
|
||||
//! Serializing for std::pair
|
||||
template <class Archive, class T1, class T2> inline
|
||||
void serialize( Archive & ar, std::pair<T1, T2> & pair )
|
||||
void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, std::pair<T1, T2> & pair )
|
||||
{
|
||||
ar( _CEREAL_NVP("first", pair.first),
|
||||
_CEREAL_NVP("second", pair.second) );
|
||||
ar( CEREAL_NVP_("first", pair.first),
|
||||
CEREAL_NVP_("second", pair.second) );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace cereal
|
|||
template <class Archive, class T, class A> inline
|
||||
typename std::enable_if<traits::is_output_serializable<BinaryData<T>, Archive>::value
|
||||
&& std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, void>::type
|
||||
save( Archive & ar, std::vector<T, A> const & vector )
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::vector<T, A> const & vector )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(vector.size()) ) ); // number of elements
|
||||
ar( binary_data( vector.data(), vector.size() * sizeof(T) ) );
|
||||
|
@ -49,7 +49,7 @@ namespace cereal
|
|||
template <class Archive, class T, class A> inline
|
||||
typename std::enable_if<traits::is_input_serializable<BinaryData<T>, Archive>::value
|
||||
&& std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, void>::type
|
||||
load( Archive & ar, std::vector<T, A> & vector )
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::vector<T, A> & vector )
|
||||
{
|
||||
size_type vectorSize;
|
||||
ar( make_size_tag( vectorSize ) );
|
||||
|
@ -62,49 +62,49 @@ namespace cereal
|
|||
template <class Archive, class T, class A> inline
|
||||
typename std::enable_if<!traits::is_output_serializable<BinaryData<T>, Archive>::value
|
||||
|| !std::is_arithmetic<T>::value, void>::type
|
||||
save( Archive & ar, std::vector<T, A> const & vector )
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::vector<T, A> const & vector )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(vector.size()) ) ); // number of elements
|
||||
for( auto it = vector.begin(), end = vector.end(); it != end; ++it )
|
||||
ar( *it );
|
||||
for(auto && v : vector)
|
||||
ar( v );
|
||||
}
|
||||
|
||||
//! Serialization for non-arithmetic vector types
|
||||
template <class Archive, class T, class A> inline
|
||||
typename std::enable_if<!traits::is_input_serializable<BinaryData<T>, Archive>::value
|
||||
|| !std::is_arithmetic<T>::value, void>::type
|
||||
load( Archive & ar, std::vector<T, A> & vector )
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::vector<T, A> & vector )
|
||||
{
|
||||
size_type size;
|
||||
ar( make_size_tag( size ) );
|
||||
|
||||
vector.resize( static_cast<std::size_t>( size ) );
|
||||
for( auto it = vector.begin(), end = vector.end(); it != end; ++it )
|
||||
ar( *it );
|
||||
for(auto && v : vector)
|
||||
ar( v );
|
||||
}
|
||||
|
||||
//! Serialization for bool vector types
|
||||
template <class Archive, class A> inline
|
||||
void save( Archive & ar, std::vector<bool, A> const & vector )
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::vector<bool, A> const & vector )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(vector.size()) ) ); // number of elements
|
||||
for( auto it = vector.begin(), end = vector.end(); it != end; ++it )
|
||||
ar( static_cast<bool>( *it ) );
|
||||
for(auto && v : vector)
|
||||
ar( static_cast<bool>(v) );
|
||||
}
|
||||
|
||||
//! Serialization for bool vector types
|
||||
template <class Archive, class A> inline
|
||||
void load( Archive & ar, std::vector<bool, A> & vector )
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::vector<bool, A> & vector )
|
||||
{
|
||||
size_type size;
|
||||
ar( make_size_tag( size ) );
|
||||
|
||||
vector.resize( static_cast<std::size_t>( size ) );
|
||||
for( auto it = vector.begin(), end = vector.end(); it != end; ++it )
|
||||
for(auto && v : vector)
|
||||
{
|
||||
bool b;
|
||||
ar( b );
|
||||
*it = b;
|
||||
v = b;
|
||||
}
|
||||
}
|
||||
} // namespace cereal
|
||||
|
|
Loading…
Add table
Reference in a new issue