mirror of
https://github.com/USCiLab/cereal.git
synced 2025-10-18 01:45:52 +02:00
@@ -173,10 +173,7 @@ namespace cereal
|
||||
//! Construct the output archive
|
||||
/*! @param self A pointer to the derived ArchiveType (pass this from the derived archive) */
|
||||
OutputArchive(ArchiveType * const self) : self(self), itsCurrentPointerId(1), itsCurrentPolymorphicTypeId(1)
|
||||
{
|
||||
// Immediately dump all version information
|
||||
self->process( make_nvp<ArchiveType>( "cereal_version_information", detail::Versions ) );
|
||||
}
|
||||
{ }
|
||||
|
||||
//! Serializes all passed in data
|
||||
template <class ... Types> inline
|
||||
@@ -387,7 +384,8 @@ namespace cereal
|
||||
template <class T> inline
|
||||
void registerClassVersion( const std::uint32_t version )
|
||||
{
|
||||
const auto insertResult = itsVersionedTypes.insert( std::type_index(typeid(T)).hash_code() );
|
||||
static const auto hash = std::type_index(typeid(T)).hash_code();
|
||||
const auto insertResult = itsVersionedTypes.insert( hash );
|
||||
if( insertResult.second ) // insertion took place, serialize the version number
|
||||
process( make_nvp<ArchiveType>("cereal_class_version", version) );
|
||||
}
|
||||
@@ -696,6 +694,85 @@ namespace cereal
|
||||
return *self;
|
||||
}
|
||||
|
||||
/*! @name Boost Transition Layer (private)
|
||||
Specific private functionality and overrides for enabling the Boost Transition Layer */
|
||||
//! @{
|
||||
|
||||
//! Registers a class version with the archive and serializes it if necessary
|
||||
/*! If this is the first time this class has been serialized, we will record its
|
||||
version number and serialize that.
|
||||
|
||||
@tparam T The type of the class being serialized
|
||||
@param version The version number associated with it */
|
||||
template <class T> inline
|
||||
std::uint32_t loadClassVersion()
|
||||
{
|
||||
static const auto hash = std::type_index(typeid(T)).hash_code();
|
||||
auto lookupResult = itsVersionedTypes.find( hash );
|
||||
|
||||
if( lookupResult != itsVersionedTypes.end() ) // already exists
|
||||
return lookupResult->second;
|
||||
else // need to load
|
||||
{
|
||||
std::uint32_t version;
|
||||
|
||||
process( make_nvp<ArchiveType>("cereal_class_version", version) );
|
||||
itsVersionedTypes.emplace_hint( lookupResult, hash, version );
|
||||
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
//! Member serialization
|
||||
/*! Boost Transition Layer version */
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::is_input_serializable<T, ArchiveType>::value && traits::has_member_versioned_serialize<T, ArchiveType>::value,
|
||||
ArchiveType &>::type
|
||||
processImpl(T & t)
|
||||
{
|
||||
static const auto version = loadClassVersion<T>();
|
||||
access::member_serialize(*self, t, version);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member serialization
|
||||
/*! Boost Transition Layer version */
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::is_input_serializable<T, ArchiveType>::value && traits::has_non_member_versioned_serialize<T, ArchiveType>::value,
|
||||
ArchiveType &>::type
|
||||
processImpl(T & t)
|
||||
{
|
||||
static const auto version = loadClassVersion<T>();
|
||||
serialize(*self, t, version);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (load)
|
||||
/*! Boost Transition Layer version */
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::is_input_serializable<T, ArchiveType>::value && traits::has_member_versioned_load<T, ArchiveType>::value,
|
||||
ArchiveType &>::type
|
||||
processImpl(T & t)
|
||||
{
|
||||
static const auto version = loadClassVersion<T>();
|
||||
access::member_load(*self, t, version);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member split (load)
|
||||
/*! Boost Transition Layer version */
|
||||
template <class T> inline
|
||||
typename std::enable_if<traits::is_input_serializable<T, ArchiveType>::value && traits::has_non_member_versioned_load<T, ArchiveType>::value,
|
||||
ArchiveType &>::type
|
||||
processImpl(T & t)
|
||||
{
|
||||
static const auto version = loadClassVersion<T>();
|
||||
load(*self, t, version);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
private:
|
||||
ArchiveType * const self;
|
||||
|
||||
@@ -707,6 +784,9 @@ namespace cereal
|
||||
|
||||
//! Maps from name ids to names
|
||||
std::unordered_map<std::uint32_t, std::string> itsPolymorphicTypeMap;
|
||||
|
||||
//! Maps from type hash codes to version numbers
|
||||
std::unordered_map<std::size_t, std::uint32_t> itsVersionedTypes;
|
||||
}; // class InputArchive
|
||||
} // namespace cereal
|
||||
|
||||
|
||||
@@ -305,6 +305,28 @@ namespace cereal
|
||||
return {std::forward<KeyType>(key), std::forward<ValueType>(value)};
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
//! Holds all registered version information
|
||||
struct Versions
|
||||
{
|
||||
static std::unordered_map<std::size_t, std::uint32_t> mapping;
|
||||
}; // struct Versions
|
||||
|
||||
//! Initialize the mapping
|
||||
std::unordered_map<std::size_t, std::uint32_t> Versions::mapping = {};
|
||||
|
||||
//! Version information class - used in Boost Transition Layer
|
||||
/*! This is the base case for classes that have not been explicitly
|
||||
registered */
|
||||
template <class T> 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
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
//! Defines a class version for some type
|
||||
/*! This is part of the Boost Transition Layer and is not the recommended way
|
||||
of using cereal. This works identically to how it does in Boost serialization,
|
||||
|
||||
@@ -529,29 +529,6 @@ namespace cereal
|
||||
return LoadAndAllocate<T>::load_and_allocate( ar );
|
||||
}
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
}
|
||||
//! Holds all registered version information
|
||||
struct Versions
|
||||
{
|
||||
std::unordered_map<std::size_t, std::uint32_t> mapping;
|
||||
};
|
||||
|
||||
//! Initialize the mapping
|
||||
std::unordered_map<std::size_t, std::uint32_t> Versions::mapping = {};
|
||||
|
||||
//! Version information class - used in Boost Transition Layer
|
||||
/*! This is the base case for classes that have not been explicitly
|
||||
registered */
|
||||
template <class T> 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
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace cereal
|
||||
|
||||
|
||||
66
sandbox.cpp
66
sandbox.cpp
@@ -383,8 +383,12 @@ void test_unordered_loads()
|
||||
class BoostTransitionMS
|
||||
{
|
||||
public:
|
||||
BoostTransitionMS() {}
|
||||
BoostTransitionMS( int xx ) : x(xx) {}
|
||||
|
||||
int getX(){ return x; }
|
||||
void setX( int xx ){ x = xx; }
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
int x;
|
||||
@@ -397,8 +401,12 @@ class BoostTransitionMS
|
||||
class BoostTransitionSplit
|
||||
{
|
||||
public:
|
||||
BoostTransitionSplit() {}
|
||||
BoostTransitionSplit( int xx ) : x(xx) {}
|
||||
|
||||
int getX(){ return x; }
|
||||
void setX( int xx ){ x = xx; }
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
int x;
|
||||
@@ -415,6 +423,7 @@ class BoostTransitionSplit
|
||||
class BoostTransitionNMS
|
||||
{
|
||||
public:
|
||||
BoostTransitionNMS() {}
|
||||
BoostTransitionNMS( int xx ) : x(xx) {}
|
||||
|
||||
int x;
|
||||
@@ -422,11 +431,12 @@ class BoostTransitionNMS
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar, BoostTransitionNMS & bnms, const std::uint32_t version )
|
||||
{ ar( bnms.x ); }
|
||||
{ ar( bnms.x ); std::cout << "NMS version: " << version << std::endl; }
|
||||
|
||||
struct BoostTransitionNMSplit
|
||||
{
|
||||
public:
|
||||
BoostTransitionNMSplit() {}
|
||||
BoostTransitionNMSplit( int xx ) : x(xx) {}
|
||||
|
||||
int x;
|
||||
@@ -434,11 +444,11 @@ struct BoostTransitionNMSplit
|
||||
|
||||
template <class Archive>
|
||||
void save( Archive & ar, BoostTransitionNMSplit const & bnsplit, const std::uint32_t version )
|
||||
{ ar( bnsplit.x ); }
|
||||
{ ar( bnsplit.x ); std::cout << "NMsave version: " << version << std::endl; }
|
||||
|
||||
template <class Archive>
|
||||
void load( Archive & ar, BoostTransitionNMSplit & bnsplit, const std::uint32_t version )
|
||||
{ ar( bnsplit.x ); }
|
||||
{ ar( bnsplit.x ); std::cout << "NMload version: " << version << std::endl; }
|
||||
|
||||
// ######################################################################
|
||||
int main()
|
||||
@@ -711,22 +721,10 @@ int main()
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
std::cerr << "-------------------------" << std::endl;
|
||||
std::cout << cereal::traits::has_member_serialize<BoostTransitionMS, cereal::BinaryOutputArchive>() << std::endl;
|
||||
std::cout << cereal::traits::has_member_versioned_serialize<BoostTransitionMS, cereal::BinaryOutputArchive>() << std::endl;
|
||||
std::cout << cereal::traits::is_output_serializable<BoostTransitionMS, cereal::BinaryOutputArchive>() << std::endl;
|
||||
std::cout << cereal::traits::is_output_versioned<BoostTransitionMS, cereal::BinaryOutputArchive>() << std::endl;
|
||||
|
||||
std::cout << (cereal::traits::is_output_serializable<BoostTransitionMS, cereal::BinaryOutputArchive>::value &&
|
||||
cereal::traits::has_member_serialize<BoostTransitionMS, cereal::BinaryOutputArchive>::value &&
|
||||
cereal::traits::is_output_versioned<BoostTransitionMS, cereal::BinaryOutputArchive>::value )<< std::endl;
|
||||
|
||||
std::cout << "---------snarf" << std::endl;
|
||||
std::cout << cereal::traits::has_non_member_serialize<BoostTransitionNMS, cereal::BinaryOutputArchive>() << std::endl;
|
||||
|
||||
{
|
||||
// Boost transition layer stuff
|
||||
cereal::XMLOutputArchive ar(std::cout);
|
||||
std::ofstream ss("cereal_version.out");
|
||||
cereal::XMLOutputArchive ar(ss);
|
||||
|
||||
BoostTransitionMS b(3);
|
||||
ar( b, b );
|
||||
@@ -741,6 +739,40 @@ int main()
|
||||
ar( e, e );
|
||||
}
|
||||
|
||||
{
|
||||
// Boost transition layer stuff
|
||||
std::ifstream ss("cereal_version.out");
|
||||
cereal::XMLInputArchive ar(ss);
|
||||
|
||||
BoostTransitionMS b;
|
||||
ar( b );
|
||||
assert( b.getX() == 3 );
|
||||
b.setX( 0 );
|
||||
ar( b );
|
||||
assert( b.getX() == 3 );
|
||||
|
||||
BoostTransitionSplit c;
|
||||
ar( c );
|
||||
assert( c.getX() == 4 );
|
||||
c.setX( 0 );
|
||||
ar( c );
|
||||
assert( c.getX() == 4 );
|
||||
|
||||
BoostTransitionNMS d;
|
||||
ar( d );
|
||||
assert( d.x == 5 );
|
||||
d.x = 0;
|
||||
ar( d );
|
||||
assert( d.x == 5 );
|
||||
|
||||
BoostTransitionNMSplit e;
|
||||
ar( e );
|
||||
assert( e.x == 32 );
|
||||
e.x = 0;
|
||||
ar( e );
|
||||
assert( e.x == 32 );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user