c++ - Boost serialization : read varying type of data -
i have c++ / cli project uses boost serialization serialize 3 different classes. know if possible parse first line of boost serialization archive in order know class serialized in archive, , create object of appropriate class , deserialize archive object. line contain id (maybe int or value of enum class) identify class serialized.
the file format handled choice of archive implementation.
in practice boost::archive::text_oarchive
, boost::archive::binary_oarchive
, boost::archive::xml_oarchive
.
as long archive type doesn't vary, can use boost variant distinguish payloads. in other words, make serialization framework work you, instead of "duct taping" around it:
here's demo serializes 3 different (compound) payloads , roundtrips fine without external knowledge of payload there:
#include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/variant.hpp> #include <boost/serialization/vector.hpp> #include <boost/serialization/string.hpp> #include <boost/serialization/access.hpp> struct { int simple; private: friend class boost::serialization::access; template <typename ar> void serialize(ar& ar, unsigned) { ar & simple; } }; struct b { std::string text; private: friend class boost::serialization::access; template <typename ar> void serialize(ar& ar, unsigned) { ar & text; } }; struct c { composed_a; b composed_b; private: friend class boost::serialization::access; template <typename ar> void serialize(ar& ar, unsigned) { ar & composed_a & composed_b; } }; struct filecontents { // conventions... boost::variant<a, b, c> payload; private: friend class boost::serialization::access; template <typename ar> void serialize(ar& ar, unsigned) { ar & payload; } }; #include <sstream> #include <boost/lexical_cast.hpp> ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // our roundtrip test, implement streaming can independently check equivalence inline static std::ostream& operator<<(std::ostream& os, const& v) { return os << "a{" << v.simple << "}"; } inline static std::ostream& operator<<(std::ostream& os, b const& v) { return os << "b{" << v.text << "}"; } inline static std::ostream& operator<<(std::ostream& os, c const& v) { return os << "c{" << v.composed_a << ", " << v.composed_b << "}"; } void roundtrip_test(filecontents const& original) { std::stringstream ss; { boost::archive::text_oarchive oa(ss); oa << original; } { boost::archive::text_iarchive ia(ss); filecontents clone; ia >> clone; std::string const before = boost::lexical_cast<std::string>(original.payload); std::string const after = boost::lexical_cast<std::string>(clone.payload); std::cout << "roundtrip '" << before << "': " << std::boolalpha << (before == after) << "\n"; } } int main() { roundtrip_test({ { 42 } }); roundtrip_test({ b { "life universe , everything" } }); roundtrip_test({ c { {42}, { "life universe , everything" } } }); }
the output being:
roundtrip 'a{42}': true roundtrip 'b{life universe , everything}': true roundtrip 'c{a{42}, b{life universe , everything}}': true
Comments
Post a Comment