mirror of
https://github.com/USCiLab/cereal.git
synced 2025-10-18 01:45:52 +02:00
Basic deserialization now working
This commit is contained in:
@@ -3,13 +3,14 @@
|
|||||||
namespace cereal
|
namespace cereal
|
||||||
{
|
{
|
||||||
|
|
||||||
class BinaryOutputArchive : public OutputArchive<BinaryOutputArchive>
|
// ######################################################################
|
||||||
{
|
class BinaryOutputArchive : public OutputArchive<BinaryOutputArchive>
|
||||||
public:
|
{
|
||||||
|
public:
|
||||||
BinaryOutputArchive(std::ostream & stream) :
|
BinaryOutputArchive(std::ostream & stream) :
|
||||||
OutputArchive<BinaryOutputArchive>(this),
|
OutputArchive<BinaryOutputArchive>(this),
|
||||||
itsStream(stream)
|
itsStream(stream)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
//! Writes size bytes of data to the output stream
|
//! Writes size bytes of data to the output stream
|
||||||
void save_binary( const void * data, size_t size )
|
void save_binary( const void * data, size_t size )
|
||||||
@@ -22,42 +23,79 @@ class BinaryOutputArchive : public OutputArchive<BinaryOutputArchive>
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::ostream & itsStream;
|
std::ostream & itsStream;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ######################################################################
|
||||||
|
class BinaryInputArchive : public InputArchive<BinaryInputArchive>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BinaryInputArchive(std::istream & stream) :
|
||||||
|
InputArchive<BinaryInputArchive>(this),
|
||||||
|
itsStream(stream)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
//! Reads size bytes of data from the input stream
|
||||||
|
void load_binary( void * const data, size_t size )
|
||||||
|
{
|
||||||
|
auto const readSize = itsStream.rdbuf()->sgetn( reinterpret_cast<char*>( data ), size );
|
||||||
|
|
||||||
|
if(readSize != size)
|
||||||
|
throw 1; // TODO: something terrible
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::istream & itsStream;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//! Serialization for POD types to binary
|
//! Serialization for POD types to binary
|
||||||
template<class T>
|
template<class T>
|
||||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||||
save(BinaryOutputArchive & ar, T const & t)
|
save(BinaryOutputArchive & ar, T const & t)
|
||||||
{
|
{
|
||||||
ar.save_binary(std::addressof(t), sizeof(t));
|
ar.save_binary(std::addressof(t), sizeof(t));
|
||||||
std::cout << "Serializing POD size: " << sizeof(T) << " [" << t << "]" << std::endl;
|
std::cout << "Saving POD size: " << sizeof(T) << " [" << t << "]" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||||
|
load(BinaryInputArchive & ar, T & t)
|
||||||
|
{
|
||||||
|
ar.load_binary(std::addressof(t), sizeof(t));
|
||||||
|
std::cout << "Loading POD size: " << sizeof(T) << " [" << t << "]" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
//! Serialization for NVP types to binary
|
//! Serialization for NVP types to binary
|
||||||
template<class T>
|
template<class T>
|
||||||
typename std::enable_if<std::is_base_of<cereal::detail::NameValuePairCore, T>::value, void>::type
|
void save(BinaryOutputArchive & ar, NameValuePair<T> const & t)
|
||||||
save(BinaryOutputArchive & ar, T const & t)
|
{
|
||||||
{
|
std::cout << "Saving NVP: " << t.name << std::endl;
|
||||||
std::cout << "Serializing NVP: " << t.name << " " << t.value << std::endl;
|
ar & t.value;
|
||||||
ar & t.value;
|
}
|
||||||
}
|
|
||||||
|
template<class T>
|
||||||
|
void load(BinaryInputArchive & ar, NameValuePair<T> t)
|
||||||
|
{
|
||||||
|
std::cout << "Loading NVP... " << std::endl;
|
||||||
|
ar & t.value;
|
||||||
|
}
|
||||||
|
|
||||||
//! Serialization for basic_string types to binary
|
//! Serialization for basic_string types to binary
|
||||||
template<class CharT, class Traits, class Alloc>
|
template<class CharT, class Traits, class Alloc>
|
||||||
void save(BinaryOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
|
void save(BinaryOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
|
||||||
{
|
{
|
||||||
// Save number of chars + the data
|
// Save number of chars + the data
|
||||||
ar & str.size();
|
ar & str.size();
|
||||||
ar.save_binary(str.data(), str.size() * sizeof(CharT));
|
ar.save_binary(str.data(), str.size() * sizeof(CharT));
|
||||||
|
|
||||||
std::cout << "Saving string: " << str << std::endl;
|
std::cout << "Saving string: " << str << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Serialization for basic_string types to binary
|
//! Serialization for basic_string types to binary
|
||||||
template<class CharT, class Traits, class Alloc>
|
template<class CharT, class Traits, class Alloc>
|
||||||
void load(BinaryOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
|
void load(BinaryInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
|
||||||
{
|
{
|
||||||
std::cout << "Loading string: " << str << std::endl;
|
std::cout << "Loading string: " << str << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
92
cereal.hpp
92
cereal.hpp
@@ -4,24 +4,19 @@
|
|||||||
|
|
||||||
namespace cereal
|
namespace cereal
|
||||||
{
|
{
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
struct NameValuePairCore {};
|
|
||||||
}
|
|
||||||
|
|
||||||
//! For holding name value pairs
|
//! For holding name value pairs
|
||||||
template <class T>
|
template <class T>
|
||||||
struct NameValuePair : detail::NameValuePairCore
|
struct NameValuePair
|
||||||
{
|
{
|
||||||
NameValuePair( std::string const & n, T const & v ) : name(n), value(v) {}
|
NameValuePair( std::string const & n, T & v ) : name(n), value(v) {}
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
T value;
|
T & value;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Creates a name value pair
|
//! Creates a name value pair
|
||||||
template <class T> inline
|
template <class T> inline
|
||||||
NameValuePair<T> make_nvp( std::string const & name, T const & value )
|
NameValuePair<T> make_nvp( std::string const & name, T & value )
|
||||||
{
|
{
|
||||||
return {name, value};
|
return {name, value};
|
||||||
}
|
}
|
||||||
@@ -29,6 +24,7 @@ namespace cereal
|
|||||||
//! Creates a name value pair for the variable T, using the same name
|
//! Creates a name value pair for the variable T, using the same name
|
||||||
#define CEREAL_NVP(T) ::cereal::make_nvp(#T, T);
|
#define CEREAL_NVP(T) ::cereal::make_nvp(#T, T);
|
||||||
|
|
||||||
|
// ######################################################################
|
||||||
template<class ArchiveType>
|
template<class ArchiveType>
|
||||||
class OutputArchive
|
class OutputArchive
|
||||||
{
|
{
|
||||||
@@ -56,7 +52,7 @@ namespace cereal
|
|||||||
{
|
{
|
||||||
std::cout << "Non member serialize" << std::endl;
|
std::cout << "Non member serialize" << std::endl;
|
||||||
|
|
||||||
serialize(*self, t);
|
serialize(*self, std::forward<T>(t));
|
||||||
return *self;
|
return *self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +84,7 @@ namespace cereal
|
|||||||
typename std::enable_if<!traits::is_output_serializable<T, ArchiveType>(), ArchiveType &>::type
|
typename std::enable_if<!traits::is_output_serializable<T, ArchiveType>(), ArchiveType &>::type
|
||||||
operator & (T const & t)
|
operator & (T const & t)
|
||||||
{
|
{
|
||||||
static_assert(traits::is_output_serializable<T, ArchiveType>(), "Trying to serialize an unserializable type.\n\n"
|
static_assert(traits::is_output_serializable<T, ArchiveType>(), "Trying to serialize an unserializable type with an output archive.\n\n"
|
||||||
"Types must either have a serialize function, or separate save/load functions (but not both).\n"
|
"Types must either have a serialize function, or separate save/load functions (but not both).\n"
|
||||||
"Serialize functions generally have the following signature:\n\n"
|
"Serialize functions generally have the following signature:\n\n"
|
||||||
"template<class Archive>\n"
|
"template<class Archive>\n"
|
||||||
@@ -102,4 +98,78 @@ namespace cereal
|
|||||||
private:
|
private:
|
||||||
ArchiveType * const self;
|
ArchiveType * const self;
|
||||||
}; // class OutputArchive
|
}; // class OutputArchive
|
||||||
|
|
||||||
|
// ######################################################################
|
||||||
|
template<class ArchiveType>
|
||||||
|
class InputArchive
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InputArchive(ArchiveType * const self) : self(self) { }
|
||||||
|
|
||||||
|
//! Member serialization
|
||||||
|
template <class T>
|
||||||
|
typename std::enable_if<traits::is_input_serializable<T, ArchiveType>() && traits::has_member_serialize<T, ArchiveType>(),
|
||||||
|
ArchiveType &>::type
|
||||||
|
operator & (T && t)
|
||||||
|
{
|
||||||
|
std::cout << "Member serialize" << std::endl;
|
||||||
|
|
||||||
|
t.serialize(*self);
|
||||||
|
return *self;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Non member serialization
|
||||||
|
template <class T>
|
||||||
|
typename std::enable_if<traits::is_input_serializable<T, ArchiveType>() && traits::has_non_member_serialize<T, ArchiveType>(),
|
||||||
|
ArchiveType &>::type
|
||||||
|
operator & (T && t)
|
||||||
|
{
|
||||||
|
std::cout << "Non member serialize" << std::endl;
|
||||||
|
|
||||||
|
serialize(*self, t);
|
||||||
|
return *self;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Member split (load)
|
||||||
|
template <class T>
|
||||||
|
typename std::enable_if<traits::is_input_serializable<T, ArchiveType>() && traits::has_member_load<T, ArchiveType>(),
|
||||||
|
ArchiveType &>::type
|
||||||
|
operator & (T && t)
|
||||||
|
{
|
||||||
|
std::cout << "Member split" << std::endl;
|
||||||
|
|
||||||
|
t.load(*self);
|
||||||
|
return *self;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Non member split (load)
|
||||||
|
template <class T>
|
||||||
|
typename std::enable_if<traits::is_input_serializable<T, ArchiveType>() && traits::has_non_member_load<T, ArchiveType>(),
|
||||||
|
ArchiveType &>::type
|
||||||
|
operator & (T && t)
|
||||||
|
{
|
||||||
|
std::cout << "Non member split" << std::endl;
|
||||||
|
load(*self, std::forward<T>(t));
|
||||||
|
return *self;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! No matching serialization
|
||||||
|
template <class T>
|
||||||
|
typename std::enable_if<!traits::is_input_serializable<T, ArchiveType>(), ArchiveType &>::type
|
||||||
|
operator & (T & t)
|
||||||
|
{
|
||||||
|
static_assert(traits::is_input_serializable<T, ArchiveType>(), "Trying to serialize an unserializable type with an input archive.\n\n"
|
||||||
|
"Types must either have a serialize function, or separate load/load functions (but not both).\n"
|
||||||
|
"Serialize functions generally have the following signature:\n\n"
|
||||||
|
"template<class Archive>\n"
|
||||||
|
" void serialize(int & ar)\n"
|
||||||
|
" {\n"
|
||||||
|
" ar & member1 & member2 & member3;\n"
|
||||||
|
" }\n\n" );
|
||||||
|
return *self;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ArchiveType * const self;
|
||||||
|
}; // class InputArchive
|
||||||
}
|
}
|
||||||
|
|||||||
74
test.cpp
74
test.cpp
@@ -3,6 +3,7 @@
|
|||||||
#include <cxxabi.h>
|
#include <cxxabi.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
// ###################################
|
// ###################################
|
||||||
struct Test1
|
struct Test1
|
||||||
@@ -67,34 +68,67 @@ namespace test4
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Everything
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
Test1 t1;
|
||||||
|
Test2 t2;
|
||||||
|
Test3 t3;
|
||||||
|
test4::Test4 t4;
|
||||||
|
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive & ar)
|
||||||
|
{
|
||||||
|
ar & CEREAL_NVP(x);
|
||||||
|
ar & CEREAL_NVP(y);
|
||||||
|
ar & CEREAL_NVP(t1);
|
||||||
|
ar & CEREAL_NVP(t2);
|
||||||
|
ar & CEREAL_NVP(t3);
|
||||||
|
ar & CEREAL_NVP(t4);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(Everything const & o)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
x == o.x &&
|
||||||
|
y == o.y &&
|
||||||
|
t1.a == o.t1.a &&
|
||||||
|
t2.a == o.t2.a &&
|
||||||
|
t3.a == o.t3.a &&
|
||||||
|
t4.a == o.t4.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
// ######################################################################
|
// ######################################################################
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
//std::ostringstream os;
|
Everything e_out;
|
||||||
std::ofstream os("out.txt");
|
e_out.x = 99;
|
||||||
cereal::BinaryOutputArchive archive(os);
|
e_out.y = 100;
|
||||||
|
e_out.t1 = {1};
|
||||||
|
e_out.t2 = {2};
|
||||||
|
e_out.t3 = {3};
|
||||||
|
e_out.t4 = {4};
|
||||||
|
|
||||||
Test1 t1 = {1};
|
{
|
||||||
Test2 t2 = {2};
|
std::ofstream os("out.txt");
|
||||||
Test3 t3 = {3};
|
cereal::BinaryOutputArchive archive(os);
|
||||||
test4::Test4 t4 = {4};
|
archive & e_out;
|
||||||
|
}
|
||||||
|
|
||||||
archive & t1;
|
std::cout << "----------------" << std::endl;
|
||||||
archive & t2;
|
|
||||||
archive & t3;
|
|
||||||
archive & t4;
|
|
||||||
|
|
||||||
int x = 5;
|
Everything e_in;
|
||||||
auto nvp = cereal::make_nvp("hello!", x);
|
|
||||||
|
|
||||||
archive & nvp;
|
{
|
||||||
|
std::ifstream is("out.txt");
|
||||||
|
cereal::BinaryInputArchive archive(is);
|
||||||
|
archive & e_in;
|
||||||
|
}
|
||||||
|
|
||||||
x = 6;
|
assert(e_in == e_out);
|
||||||
archive & CEREAL_NVP(x);
|
|
||||||
|
|
||||||
std::string bla = "asdf";
|
|
||||||
|
|
||||||
archive & bla;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user