Basic deserialization now working

This commit is contained in:
Shane Grant
2013-06-12 17:50:30 -07:00
parent 3210a2b3c3
commit 5d24d9f066
3 changed files with 201 additions and 59 deletions

View File

@@ -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;
} }
} }

View File

@@ -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
} }

View File

@@ -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;
} }