/*////////////////////////////////////////////////////////////////////////////// // CMT Cosmic Muon Tomography project ////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova All rights reserved Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it > ------------------------------------------------------------------ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. //////////////////////////////////////////////////////////////////////////////*/ #ifndef U_SERIALIZABLE_H #define U_SERIALIZABLE_H /* Serialization: TODO: * Problema nella serializzazione delle properties in test_archive * implementare human readable make_hrp ... non riesco.. */ #include #include #include #include #include // #include // #include // #include // #include // #include "boost/archive/polymorphic_iarchive.hpp" // #include "boost/archive/polymorphic_oarchive.hpp" #include #include #include #include #include #include "Core/Archives.h" #include "Core/Export.h" #include "Core/Mpl.h" //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // BOOST SERIALIZATION ADD-ON namespace boost { namespace serialization { // ACCESS 2 // template struct access2 {}; // NON FUNZIONA ... SISTEMARE !!!! // ------------------------------------------ template class hrp : public wrapper_traits> { const char *m_name; T *m_value; std::string *m_str; public: explicit hrp(const char *name_, T &t) : m_str(new std::string), m_name(name_), m_value(&t) {} const char *name() const { return this->m_name; } template void save(Archivex &ar, const unsigned int /* file_version */) const { //// ar.operator<<(const_value()); // std::stringstream ss; // uLib::Archive::hrt_oarchive har(ss); // har << make_nvp(m_name,*m_value); // // (*m_str) = ss.str(); //// ar.operator << (make_nvp(m_name, ss.str()); } template void load(Archivex &ar, const unsigned int /* file_version */) { // ar.operator>>(value()); } BOOST_SERIALIZATION_SPLIT_MEMBER() }; template inline #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING const #endif hrp make_hrp(const char *name, T &t) { return hrp(name, t); } #define HRP(name) boost::serialization::make_hrp(BOOST_PP_STRINGIZE(name), name) } // namespace serialization } // namespace boost //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // ULIB SERIALIZATION namespace uLib { #define _AR_OP(r, data, elem) data &BOOST_SERIALIZATION_BASE_OBJECT_NVP(elem); #define NVP(data) BOOST_SERIALIZATION_NVP(data) //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // SERIALIZTION MACROS // // !!! WARNING !!! INTRUSIVE SERIALIZATION IS ACTUALLY NOT WORKING FEATURE // SO LEAVE ULIB_CFG_INTRUSIVE_SERIALIZATION NOT DEFINED #ifdef ULIB_CFG_INTRUSIVE_SERIALIZATION_OBJECT #define ULIB_SERIALIZABLE_OBJECT _ULIB_DETAIL_INTRUSIVE_SERIALIZABLE_OBJECT #define ULIB_SERIALIZE_OBJECT(_Ob, ...) \ _ULIB_DETAIL_INTRUSIVE_SERIALIZE_OBJECT(_Ob, __VA_ARGS__) #define _AR_(_name) _ULIB_DETAIL_INTRUSIVE_AR_(_name) #else #define ULIB_SERIALIZABLE(_Ob) \ _ULIB_DETAIL_UNINTRUSIVE_SERIALIZABLE(_Ob) \ ULIB_CLASS_EXPORT_KEY(_Ob) #define ULIB_SERIALIZE(_Ob, ...) _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE(_Ob) #define ULIB_SERIALIZE_DERIVED(_Ob, ...) \ _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_DERIVED(_Ob, __VA_ARGS__) #define ULIB_SERIALIZABLE_OBJECT(_Ob) \ _ULIB_DETAIL_UNINTRUSIVE_SERIALIZABLE_OBJECT(_Ob) \ ULIB_CLASS_EXPORT_OBJECT_KEY(_Ob) #define ULIB_SERIALIZE_OBJECT(_Ob, ...) \ _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_OBJECT(_Ob, __VA_ARGS__) #define AR(_name) _ULIB_DETAIL_UNINTRUSIVE_AR_(_name) #define HR(_name) _ULIB_DETAIL_UNINTRUSIVE_AR_(_name) #endif #define ULIB_SERIALIZE_ACCESS \ friend class boost::serialization::access; \ template friend class boost::serialization::access2; #define ULIB_CLASS_EXPORT_KEY(_FullNamespaceClass) \ BOOST_CLASS_EXPORT_KEY(_FullNamespaceClass) #define ULIB_CLASS_EXPORT_OBJECT_KEY(_FullNamespaceClass) \ BOOST_CLASS_EXPORT_KEY(_FullNamespaceClass) #define _SERIALIZE_IMPL_SEQ \ (uLib::Archive::text_iarchive)(uLib::Archive::text_oarchive)( \ uLib::Archive:: \ hrt_iarchive)(uLib::Archive:: \ hrt_oarchive)(uLib::Archive:: \ xml_iarchive)(uLib::Archive:: \ xml_oarchive)(uLib::Archive:: \ log_archive) /** Solving virtual class check problem */ #define _ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE(_Base, _Derived) \ namespace boost { \ template <> \ struct is_virtual_base_of<_Base, _Derived> : public boost::mpl::true_ {}; \ } #define _ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE_OP(r, data, elem) \ _ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE(elem, data) //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // INTRUSIVE SERIALIZATION ( NOT WORKING YET !! ) // #define _ULIB_DETAIL_INTRUSIVE_AR_(name) ar &BOOST_SERIALIZATION_NVP(name); #define _ULIB_DETAIL_INTRUSIVE_SERIALIZE_FUNC(Class, Archive) \ template void Class::serialize(Archive &ar, const unsigned int); #define _ULIB_DETAIL_INTRUSIVE_SERIALIZE_FUNC_OP(r, data, elem) \ _ULIB_DETAIL_INTRUSIVE_SERIALIZE_FUNC(data, elem); #define _ULIB_DETAIL_INTRUSIVE_SERIALIZABLE_OBJECT \ typedef boost::mpl::bool_ serializable; \ typedef boost::mpl::remove_if::type \ SerilizableTypeList; \ void PrintSerializableListId() { \ boost::mpl::for_each(PrintTypeId()); \ } \ template \ void serialize(ArchiveT &ar, const unsigned int version); \ template \ void serialize_parents(ArchiveT &ar, const unsigned int version); \ template \ void save_override(ArchiveT &ar, const unsigned int version); #define _ULIB_DETAIL_INTRUSIVE_SERIALIZE_OBJECT(_Ob, ...) \ template \ void _Ob::serialize(ArchiveT &ar, const unsigned int version) { \ boost::serialization::void_cast_register<_Ob, _Ob::BaseClass>( \ static_cast<_Ob *>(NULL), static_cast<_Ob::BaseClass *>(NULL)); \ _Ob::serialize_parents(ar, version); \ _Ob::save_override(ar, version); \ } \ template \ void _Ob::serialize_parents(ArchiveT &ar, const unsigned int v) { \ BOOST_PP_SEQ_FOR_EACH(_AR_OP, ar, BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))); \ } \ BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_INTRUSIVE_SERIALIZE_FUNC_OP, _Ob, \ _SERIALIZE_IMPL_SEQ) \ BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE_OP, _Ob, \ BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))) \ ULIB_CLASS_EXPORT_IMPLEMENT(_Ob) \ namespace boost { \ namespace serialization { \ template \ inline void load_construct_data(ArchiveT &ar, _Ob *o, \ const unsigned int file_version) { \ ::new (o) _Ob(); \ o->init_parameters(); \ } \ } \ } \ template \ void _Ob::save_override(ArchiveT &ar, const unsigned int version) //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // UNINTRUSIVE SERIALIZATION #define _UNAR_OP(r, data, elem) \ ar &boost::serialization::make_nvp( \ BOOST_PP_STRINGIZE(elem), boost::serialization::base_object(ob)); #define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC(Class, Archive) \ template void boost::serialization::serialize(Archive &ar, Class &ob, \ const unsigned int i); #define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC_OP(r, data, elem) \ _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC(data, elem) // NOTE: becouse of BOOST_PP_VARIADIC_SIZE issue of some boost macro has two // different implementation #define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZABLE(_Ob) \ namespace boost { \ namespace serialization { \ template \ void serialize(ArchiveT &ar, _Ob &ob, const unsigned int version); \ template \ void serialize_parents(ArchiveT &ar, _Ob &ob, const unsigned int version); \ template <> struct access2<_Ob> { \ template \ static void save_override(ArchiveT &ar, _Ob &ob, \ const unsigned int version); \ }; \ } \ } #define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE(_Ob) \ namespace boost { \ namespace serialization { \ template \ void serialize_parents(ArchiveT &ar, _Ob &ob, const unsigned int v) {} \ template \ void serialize(ArchiveT &ar, _Ob &ob, const unsigned int version) { \ serialize_parents(ar, ob, version); \ access2<_Ob>::save_override(ar, ob, version); \ } \ } \ } \ ULIB_CLASS_EXPORT_IMPLEMENT(_Ob) \ BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC_OP, _Ob, \ _SERIALIZE_IMPL_SEQ) \ template \ void boost::serialization::access2<_Ob>::save_override( \ ArchiveT &ar, _Ob &ob, const unsigned int version) #define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_DERIVED(_Ob, ...) \ namespace boost { \ namespace serialization { \ template \ void serialize_parents(ArchiveT &ar, _Ob &ob, const unsigned int v) { \ BOOST_PP_IF(BOOST_PP_VARIADIC_SIZE((__VA_ARGS__)), \ BOOST_PP_SEQ_FOR_EACH(_UNAR_OP, ob, \ BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))); \ , ) \ } \ template \ void serialize(ArchiveT &ar, _Ob &ob, const unsigned int version) { \ serialize_parents(ar, ob, version); \ access2<_Ob>::save_override(ar, ob, version); \ } \ } \ } \ ULIB_CLASS_EXPORT_IMPLEMENT(_Ob) \ BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC_OP, _Ob, \ _SERIALIZE_IMPL_SEQ) \ BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE_OP, _Ob, \ BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))) \ template \ void boost::serialization::access2<_Ob>::save_override( \ ArchiveT &ar, _Ob &ob, const unsigned int version) #define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZABLE_OBJECT(_Ob) \ namespace boost { \ namespace serialization { \ template \ void serialize(ArchiveT &ar, _Ob &ob, const unsigned int version); \ template \ void serialize_parents(ArchiveT &ar, _Ob &ob, const unsigned int version); \ template <> struct access2<_Ob> { \ template \ static void save_override(ArchiveT &ar, _Ob &ob, \ const unsigned int version); \ }; \ } \ } #define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_OBJECT(_Ob, ...) \ namespace boost { \ namespace serialization { \ template \ void serialize_parents(ArchiveT &ar, _Ob &ob, const unsigned int v) { \ /* PP serialize */ BOOST_PP_SEQ_FOR_EACH( \ _UNAR_OP, ob, BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))); \ /* MPL serialize */ /*uLib::mpl::for_each<_Ob::BaseList>(uLib::detail::Serializable::serialize_baseobject<_Ob,ArchiveT>(ob,ar) );*/ } \ template \ inline void load_construct_data(ArchiveT &ar, _Ob *ob, \ const unsigned int file_version) { \ ::new (ob) _Ob(); \ } \ template \ void serialize(ArchiveT &ar, _Ob &ob, const unsigned int version) { \ void_cast_register<_Ob, _Ob::BaseClass>( \ static_cast<_Ob *>(NULL), \ static_cast<_Ob::BaseClass *>(NULL)); /*fix*/ \ serialize_parents(ar, ob, version); \ access2<_Ob>::save_override(ar, ob, version); \ } \ } \ } \ ULIB_CLASS_EXPORT_IMPLEMENT(_Ob) \ BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE_OP, _Ob, \ BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))) \ BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC_OP, _Ob, \ _SERIALIZE_IMPL_SEQ) \ template \ void boost::serialization::access2<_Ob>::save_override( \ ArchiveT &ar, _Ob &ob, const unsigned int version) #define _ULIB_DETAIL_UNINTRUSIVE_AR_(name) \ boost::serialization::make_nvp(BOOST_PP_STRINGIZE(name), ob.name) //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// namespace detail { struct Serializable { /** * Serializable trait to check if an object type is serializable. * This only works if UNINTRUSIVE SERIALIZATION is applyed; in intrusive * cases a has_serialize trait should be implemented */ template struct serializable_trait : mpl::bool_ {}; /** * IsA Serializable Implementation Template */ template struct IsA : serializable_trait {}; template struct serialize_baseobject { ThisClass &m_object; Archive &m_ar; serialize_baseobject(ThisClass &o, Archive &ar) : m_object(o), m_ar(ar) {} template void operator()(T &o) { m_ar &boost::serialization::make_nvp( typeid(T).name(), boost::serialization::base_object(m_object)); } }; }; } // namespace detail struct Serializable { friend class boost::serialization::access; template friend class boost::serialization::access2; virtual ~Serializable() {} protected: }; } // namespace uLib #endif // U_SERIALIZABLE_H