From 5d24d9f06600a6029df52ca4408daaebeb495a35 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Wed, 12 Jun 2013 17:50:30 -0700 Subject: [PATCH] Basic deserialization now working --- binary_archive.hpp | 94 ++++++++++++++++++++++++++++++++-------------- cereal.hpp | 92 +++++++++++++++++++++++++++++++++++++++------ test.cpp | 74 ++++++++++++++++++++++++++---------- 3 files changed, 201 insertions(+), 59 deletions(-) diff --git a/binary_archive.hpp b/binary_archive.hpp index 37a1d67f..be2bf60f 100644 --- a/binary_archive.hpp +++ b/binary_archive.hpp @@ -3,13 +3,14 @@ namespace cereal { -class BinaryOutputArchive : public OutputArchive -{ - public: + // ###################################################################### + class BinaryOutputArchive : public OutputArchive + { + public: BinaryOutputArchive(std::ostream & stream) : OutputArchive(this), itsStream(stream) - { } + { } //! Writes size bytes of data to the output stream void save_binary( const void * data, size_t size ) @@ -22,42 +23,79 @@ class BinaryOutputArchive : public OutputArchive private: std::ostream & itsStream; -}; + }; + + // ###################################################################### + class BinaryInputArchive : public InputArchive + { + public: + BinaryInputArchive(std::istream & stream) : + InputArchive(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( data ), size ); + + if(readSize != size) + throw 1; // TODO: something terrible + + } + + private: + std::istream & itsStream; + }; //! Serialization for POD types to binary template - typename std::enable_if::value, void>::type - save(BinaryOutputArchive & ar, T const & t) - { - ar.save_binary(std::addressof(t), sizeof(t)); - std::cout << "Serializing POD size: " << sizeof(T) << " [" << t << "]" << std::endl; - } + typename std::enable_if::value, void>::type + save(BinaryOutputArchive & ar, T const & t) + { + ar.save_binary(std::addressof(t), sizeof(t)); + std::cout << "Saving POD size: " << sizeof(T) << " [" << t << "]" << std::endl; + } + + template + typename std::enable_if::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 template - typename std::enable_if::value, void>::type - save(BinaryOutputArchive & ar, T const & t) - { - std::cout << "Serializing NVP: " << t.name << " " << t.value << std::endl; - ar & t.value; - } + void save(BinaryOutputArchive & ar, NameValuePair const & t) + { + std::cout << "Saving NVP: " << t.name << std::endl; + ar & t.value; + } + + template + void load(BinaryInputArchive & ar, NameValuePair t) + { + std::cout << "Loading NVP... " << std::endl; + ar & t.value; + } //! Serialization for basic_string types to binary template - void save(BinaryOutputArchive & ar, std::basic_string const & str) - { - // Save number of chars + the data - ar & str.size(); - ar.save_binary(str.data(), str.size() * sizeof(CharT)); + void save(BinaryOutputArchive & ar, std::basic_string const & str) + { + // Save number of chars + the data + ar & str.size(); + 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 template - void load(BinaryOutputArchive & ar, std::basic_string & str) - { - std::cout << "Loading string: " << str << std::endl; - } + void load(BinaryInputArchive & ar, std::basic_string & str) + { + std::cout << "Loading string: " << str << std::endl; + } } diff --git a/cereal.hpp b/cereal.hpp index 21bce373..93fcb557 100644 --- a/cereal.hpp +++ b/cereal.hpp @@ -4,24 +4,19 @@ namespace cereal { - namespace detail - { - struct NameValuePairCore {}; - } - //! For holding name value pairs template - 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; - T value; + T & value; }; //! Creates a name value pair template inline - NameValuePair make_nvp( std::string const & name, T const & value ) + NameValuePair make_nvp( std::string const & name, T & value ) { return {name, value}; } @@ -29,6 +24,7 @@ namespace cereal //! Creates a name value pair for the variable T, using the same name #define CEREAL_NVP(T) ::cereal::make_nvp(#T, T); + // ###################################################################### template class OutputArchive { @@ -56,7 +52,7 @@ namespace cereal { std::cout << "Non member serialize" << std::endl; - serialize(*self, t); + serialize(*self, std::forward(t)); return *self; } @@ -88,7 +84,7 @@ namespace cereal typename std::enable_if(), ArchiveType &>::type operator & (T const & t) { - static_assert(traits::is_output_serializable(), "Trying to serialize an unserializable type.\n\n" + static_assert(traits::is_output_serializable(), "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" "Serialize functions generally have the following signature:\n\n" "template\n" @@ -102,4 +98,78 @@ namespace cereal private: ArchiveType * const self; }; // class OutputArchive + + // ###################################################################### + template + class InputArchive + { + public: + InputArchive(ArchiveType * const self) : self(self) { } + + //! Member serialization + template + typename std::enable_if() && traits::has_member_serialize(), + ArchiveType &>::type + operator & (T && t) + { + std::cout << "Member serialize" << std::endl; + + t.serialize(*self); + return *self; + } + + //! Non member serialization + template + typename std::enable_if() && traits::has_non_member_serialize(), + ArchiveType &>::type + operator & (T && t) + { + std::cout << "Non member serialize" << std::endl; + + serialize(*self, t); + return *self; + } + + //! Member split (load) + template + typename std::enable_if() && traits::has_member_load(), + ArchiveType &>::type + operator & (T && t) + { + std::cout << "Member split" << std::endl; + + t.load(*self); + return *self; + } + + //! Non member split (load) + template + typename std::enable_if() && traits::has_non_member_load(), + ArchiveType &>::type + operator & (T && t) + { + std::cout << "Non member split" << std::endl; + load(*self, std::forward(t)); + return *self; + } + + //! No matching serialization + template + typename std::enable_if(), ArchiveType &>::type + operator & (T & t) + { + static_assert(traits::is_input_serializable(), "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\n" + " void serialize(int & ar)\n" + " {\n" + " ar & member1 & member2 & member3;\n" + " }\n\n" ); + return *self; + } + + private: + ArchiveType * const self; + }; // class InputArchive } diff --git a/test.cpp b/test.cpp index 277752c8..7131224b 100644 --- a/test.cpp +++ b/test.cpp @@ -3,6 +3,7 @@ #include #include #include +#include // ################################### struct Test1 @@ -67,34 +68,67 @@ namespace test4 } } +struct Everything +{ + int x; + int y; + Test1 t1; + Test2 t2; + Test3 t3; + test4::Test4 t4; + + template + 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() { - //std::ostringstream os; - std::ofstream os("out.txt"); - cereal::BinaryOutputArchive archive(os); + Everything e_out; + e_out.x = 99; + 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}; - Test3 t3 = {3}; - test4::Test4 t4 = {4}; + { + std::ofstream os("out.txt"); + cereal::BinaryOutputArchive archive(os); + archive & e_out; + } - archive & t1; - archive & t2; - archive & t3; - archive & t4; + std::cout << "----------------" << std::endl; - int x = 5; - auto nvp = cereal::make_nvp("hello!", x); + Everything e_in; - archive & nvp; + { + std::ifstream is("out.txt"); + cereal::BinaryInputArchive archive(is); + archive & e_in; + } - x = 6; - archive & CEREAL_NVP(x); - - std::string bla = "asdf"; - - archive & bla; + assert(e_in == e_out); return 0; }