/*////////////////////////////////////////////////////////////////////////////// // 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_CORE_ARCHIVES_H #define U_CORE_ARCHIVES_H #include #include #include #include #include #include #include #include #include #include #include #include #include "StringReader.h" //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // FWD DECLARATIONS OF ARCHIVES // namespace uLib { namespace Archive { class xml_iarchive; class xml_oarchive; class text_iarchive; class text_oarchive; class log_archive; } } namespace boost { namespace archive { namespace detail { template class polymorphic_oarchive_route; template class polymorphic_iarchive_route; } } } namespace boost { namespace serialization { template struct hrp; } } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // ARCHIVES REGISTRATION // namespace uLib { namespace Archive { namespace detail { struct adl_tag {}; } } } namespace boost { namespace archive { namespace detail { // This function gets called, but its only purpose is to participate // in overload resolution with the functions declared by // BOOST_SERIALIZATION_REGISTER_ARCHIVE, below. template void instantiate_ptr_serialization(Serializable*, int, uLib::Archive::detail::adl_tag ) {} } } } // The function declaration generated by this macro never actually // gets called, but its return type gets instantiated, and that's // enough to cause registration of serialization functions between // Archive and any exported Serializable type. See also: // boost/serialization/export.hpp # define ULIB_SERIALIZATION_REGISTER_ARCHIVE(_Archive) \ namespace boost { namespace archive { namespace detail { \ \ template \ BOOST_DEDUCED_TYPENAME _ptr_serialization_support<_Archive, Serializable>::type \ instantiate_ptr_serialization( Serializable*, _Archive*, uLib::Archive::detail::adl_tag ); }}} //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // ARCHIVES IO INTERFACES // namespace boost { namespace archive { namespace detail { /** * Custom implementation of boost interface_iarchive to add new operators */ template class uLib_interface_iarchive { protected: uLib_interface_iarchive(){}; public: ///////////////////////////////////////////////////////// // archive public interface typedef mpl::bool_ is_loading; typedef mpl::bool_ is_saving; // return a pointer to the most derived class Archive * This(){ return static_cast(this); } template const basic_pointer_iserializer * register_type(T * = NULL){ const basic_pointer_iserializer & bpis = boost::serialization::singleton< pointer_iserializer >::get_const_instance(); this->This()->register_basic_serializer(bpis.get_basic_serializer()); return & bpis; } template Archive & operator>>(T & t){ this->This()->load_override(t, 0); return * this->This(); } // the & operator template Archive & operator&(T & t){ return *(this->This()) >> t; } // the == operator template Archive & operator == (T & t) { return this->operator &(t); } // the != operator for human readable access template Archive & operator != (T & t) { std::cerr << std::flush << "cauch string: " << t << "\n"; // REMOVE THIS ! return * this->This(); } }; /** * Custom implementation of boost interface_oarchive to add new operators */ template class uLib_interface_oarchive { protected: uLib_interface_oarchive(){}; public: ///////////////////////////////////////////////////////// // archive public interface typedef mpl::bool_ is_loading; typedef mpl::bool_ is_saving; // return a pointer to the most derived class Archive * This(){ return static_cast(this); } template const basic_pointer_oserializer * register_type(const T * = NULL){ const basic_pointer_oserializer & bpos = boost::serialization::singleton< pointer_oserializer >::get_const_instance(); this->This()->register_basic_serializer(bpos.get_basic_serializer()); return & bpos; } template Archive & operator<<(T & t){ // to get access you must redefine save_override by typing // "using save_override" in archive impl this->This()->save_override(t, 0); return * this->This(); } // the & operator template Archive & operator&(T & t){ #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING return * this->This() << const_cast(t); #else return * this->This() << t; #endif } // the == operator template Archive & operator == (T & t) { return this->operator &(t); } // the != operator for human readable access template Archive & operator != (T & t) { std::cerr << std::flush << "cauch string: " << t << "\n"; // REMOVE THIS ! return * this->This(); } }; // DECLARE INTERFACE SPECIALIZATIONS /////////////////////////////////////////// // With this declarations all uLib archive Implementation will use their own // extended interface // template <> class interface_iarchive : public uLib_interface_iarchive {}; template <> class interface_oarchive : public uLib_interface_oarchive {}; template <> class interface_iarchive : public uLib_interface_iarchive {}; template <> class interface_oarchive : public uLib_interface_oarchive {}; template <> class interface_oarchive : public uLib_interface_oarchive {}; //// Veritical repetition macro // FINIRE !!!!!!!!!!!!!!!!!!!!!!!!! //#define _DECL_INTERFACE_ARCHIVE_V(vz,vn,vdata) \ // template \ // struct inherit_nofold : \ // BOOST_PP_REPEAT(BOOST_PP_INC(vn),_INERIT_NOFOLD_H,~) \ // {}; //// Multiple size declaration // //BOOST_PP_REPEAT(ULIB_CFG_MPL_INERIT_NOFOLD_MAXSIZE,_INERIT_NOFOLD_V,~) //#undef _INERIT_NOFOLD_H //#undef _INERIT_NOFOLD_V } // detail } // archive } // boost //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // ARCHIVES DEFINITIONS // namespace boost { namespace archive { //template //inline void load_const_override(Archive & ar, const char *t ){ // typedef typename mpl::identity >::type typex; // typex::invoke(ar, t); //} //template //inline void load(Archive & ar, T &t){ // // if this assertion trips. It means we're trying to load a // // const object with a compiler that doesn't have correct // // funtion template ordering. On other compilers, this is // // handled below. // // detail::check_const_loading< T >(); // typedef // BOOST_DEDUCED_TYPENAME mpl::eval_if, // mpl::identity > // ,//else // BOOST_DEDUCED_TYPENAME mpl::eval_if, // mpl::identity > // ,//else // BOOST_DEDUCED_TYPENAME mpl::eval_if, // mpl::identity > // ,//else // mpl::identity > // > // > // >::type typex; // typex::invoke(ar, t); //} } } namespace uLib { namespace Archive { //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // POLYMORPHIC // //class polymorphic_iarchive : // public boost::archive::polymorphic_iarchive { //public: // void load_override(const char *t, BOOST_PFTO int) // { // boost::archive::load_const_override(* this->This(), const_cast(t)); // } //}; //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // XML // class xml_iarchive : public boost::archive::xml_iarchive_impl { typedef xml_iarchive Archive; typedef boost::archive::xml_iarchive_impl base; // give serialization implementation access to this class friend class boost::archive::detail::interface_iarchive; friend class boost::archive::basic_xml_iarchive; friend class boost::archive::load_access; public: xml_iarchive(std::istream & is, unsigned int flags = 0) : xml_iarchive_impl(is, flags) {} using basic_xml_iarchive::load_override; // Anything not an attribute should be a name value pair as nvp or hrp typedef boost::archive::detail::common_iarchive detail_common_iarchive; template void load_override( #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING const #endif boost::serialization::hrp< T > & t, int v ){ this->This()->load_start(t.name()); this->detail_common_iarchive::load_override(t.value(), 0); // t.stov(); this->This()->load_end(t.name()); } // class_name_type can't be handled here as it depends upon the // char type used by the stream. So require the derived implementation. // derived in this case is xml_iarchive_impl or base .. using base::load_override; void load_override(const char *str, int v) { // StringReader sr(basic_text_iprimitive::is); // sr >> str; } ~xml_iarchive(){}; }; //typedef boost::archive::detail::polymorphic_iarchive_route< //boost::archive::xml_iarchive_impl //> polymorphic_xml_iarchive; template struct polymorphic_iarchive_route : boost::archive::detail::polymorphic_iarchive_route { virtual void load(const char * t){ ArchiveImpl::load(t); } }; class polymorphic_xml_iarchive : public polymorphic_iarchive_route< boost::archive::xml_iarchive_impl > { // give serialization implementation access to this class // friend class boost::archive::detail::interface_iarchive; // friend class boost::archive::basic_xml_iarchive; // friend class boost::archive::load_access; public: virtual void load_override(const char *str, int v) { ; } }; class xml_oarchive : public boost::archive::xml_oarchive_impl { typedef xml_oarchive Archive; typedef boost::archive::xml_oarchive_impl base; // give serialization implementation access to this class friend class boost::archive::detail::interface_oarchive; friend class boost::archive::basic_xml_oarchive; friend class boost::archive::save_access; public: xml_oarchive(std::ostream & os, unsigned int flags = 0) : boost::archive::xml_oarchive_impl(os, flags) {} // example of implementing save_override for const char* // // void save_override(const char *t, int) { // std::cout << "found char: " << t << "\n"; // } using basic_xml_oarchive::save_override; // special treatment for name-value pairs. typedef boost::archive::detail::common_oarchive detail_common_oarchive; template void save_override( #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING const #endif ::boost::serialization::hrp< T > & t, int v ){ this->This()->save_start(t.name()); // t.vtos(); // this->detail_common_oarchive::save_override(t.const_value(), 0); this->This()->save_end(t.name()); } void save_override(const char *str, int v) { // Do not save any human decoration string // // basic_text_oprimitive::save(str); } ~xml_oarchive(){} }; //typedef boost::archive::detail::polymorphic_oarchive_route< //boost::archive::xml_oarchive_impl //> polymorphic_xml_oarchive; //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // TEXT // class text_iarchive : public boost::archive::text_iarchive_impl { typedef text_iarchive Archive; typedef boost::archive::text_iarchive_impl base; // give serialization implementation access to this class friend class boost::archive::detail::interface_iarchive; friend class boost::archive::basic_text_iarchive; friend class boost::archive::load_access; public: text_iarchive(std::istream & is, unsigned int flags = 0) : text_iarchive_impl(is, flags) {} using basic_text_iarchive::load_override; void load_override(boost::archive::object_id_type & t, int) {} // class_name_type can't be handled here as it depends upon the // char type used by the stream. So require the derived implementation. // derived in this case is xml_iarchive_impl or base .. using base::load_override; void load_override(const char *str, int v) { StringReader sr(basic_text_iprimitive::is); sr >> str; } ~text_iarchive() {}; }; typedef text_iarchive naked_text_iarchive; //typedef boost::archive::detail::polymorphic_iarchive_route< //naked_text_iarchive //> polymorphic_text_iarchive; class text_oarchive : public boost::archive::text_oarchive_impl { typedef text_oarchive Archive; typedef boost::archive::text_oarchive_impl base; // give serialization implementation access to this class friend class boost::archive::detail::interface_oarchive; friend class boost::archive::basic_text_oarchive; friend class boost::archive::save_access; public: text_oarchive(std::ostream & os, unsigned int flags = 0) : boost::archive::text_oarchive_impl(os, flags) {} using basic_text_oarchive::save_override; void save_override(const char *str, int v) { basic_text_oprimitive::save(str); } ~text_oarchive(){} }; //typedef boost::archive::detail::polymorphic_oarchive_route< //boost::archive::text_oarchive_impl //> polymorphic_text_oarchive; //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // SIMPLE HUMAN READABLE TEXT // class hrt_iarchive : public boost::archive::text_iarchive_impl { typedef hrt_iarchive Archive; typedef boost::archive::text_iarchive_impl base; // give serialization implementation access to this class friend class boost::archive::detail::interface_iarchive; friend class boost::archive::basic_text_iarchive; friend class boost::archive::load_access; public: hrt_iarchive(std::istream & is, unsigned int flags = 0) : base(is, flags | boost::archive::no_header ) {} using basic_text_iarchive::load_override; // hide all archive props // void load_override( boost::archive::object_id_type & t, int) {} void load_override( boost::archive::object_reference_type & t, int) {} void load_override( boost::archive::version_type & t, int) {} void load_override( boost::archive::class_id_type & t, int) {} void load_override( boost::archive::class_id_optional_type & t, int) {} void load_override( boost::archive::class_id_reference_type & t, int){} void load_override( boost::archive::class_name_type & t, int) {} void load_override( boost::archive::tracking_type & t, int) {} // class_name_type can't be handled here as it depends upon the // char type used by the stream. So require the derived implementation. // derived in this case is xml_iarchive_impl or base .. using base::load_override; void load_override(const char *str, int v) { StringReader sr(basic_text_iprimitive::is); sr >> str; } ~hrt_iarchive() {}; }; class hrt_oarchive : public boost::archive::text_oarchive_impl { typedef hrt_oarchive Archive; typedef boost::archive::text_oarchive_impl base; // give serialization implementation access to this class friend class boost::archive::detail::interface_oarchive; friend class boost::archive::basic_text_oarchive; friend class boost::archive::save_access; public: hrt_oarchive(std::ostream & os, unsigned int flags = 0) : base(os, flags | boost::archive::no_header ) {} using basic_text_oarchive::save_override; void save_override(const boost::archive::object_id_type & t, int) {} void save_override(const boost::archive::object_reference_type & t, int) {} void save_override(const boost::archive::version_type & t, int) {} void save_override(const boost::archive::class_id_type & t, int) {} void save_override(const boost::archive::class_id_optional_type & t, int) {} void save_override(const boost::archive::class_id_reference_type & t, int){} void save_override(const boost::archive::class_name_type & t, int) {} void save_override(const boost::archive::tracking_type & t, int) {} void save_override(const char *str, int v) { basic_text_oprimitive::save(str); } ~hrt_oarchive(){} }; //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // XML FOR LOG OUTPUT PURPOUSE // ///////////////////////////////////////////////////////////////////////// // log data to an output stream. This illustrates a simpler implemenation // of text output which is useful for getting a formatted display of // any serializable class. Intended to be useful as a debugging aid. class log_archive : /* protected ? */ public boost::archive::xml_oarchive_impl { typedef boost::archive::xml_oarchive_impl base; typedef log_archive Archive; // give serialization implementation access to this clas friend class boost::archive::detail::interface_oarchive; friend class boost::archive::basic_xml_oarchive; friend class boost::archive::save_access; public: void save_override(const char *str, int v) { // Do not save any human decoration string // // basic_text_oprimitive::save(str); } template void save_override(T & t, BOOST_PFTO int){ base::save_override(boost::serialization::make_nvp(NULL, t), 0); } // activate this if you want to trap non nvp objects // // template // void save_override(T & t, BOOST_PFTO int) // { // BOOST_MPL_ASSERT((boost::serialization::is_wrapper< T >)); // // this->detail_common_oarchive::save_override(t, 0); // } template void save_override(const boost::serialization::nvp & t, int){ base::save_override(t, 0); } // specific overrides for attributes - not name value pairs so we // want to trap them before the above "fall through" // since we don't want to see these in the output - make them no-ops. void save_override(const boost::archive::object_id_type & t, int) {} void save_override(const boost::archive::object_reference_type & t, int) {} void save_override(const boost::archive::version_type & t, int) {} void save_override(const boost::archive::class_id_type & t, int) {} void save_override(const boost::archive::class_id_optional_type & t, int) {} void save_override(const boost::archive::class_id_reference_type & t, int){} void save_override(const boost::archive::class_name_type & t, int) {} void save_override(const boost::archive::tracking_type & t, int) {} public: log_archive(std::ostream & os, unsigned int flags = 0) : boost::archive::xml_oarchive_impl( os, flags | boost::archive::no_header ) {} }; //typedef boost::archive::detail::polymorphic_oarchive_route< //boost::archive::xml_oarchive_impl //> polymorphic_log_archive; } // Archive } // uLib ULIB_SERIALIZATION_REGISTER_ARCHIVE(uLib::Archive::xml_iarchive) ULIB_SERIALIZATION_REGISTER_ARCHIVE(uLib::Archive::xml_oarchive) ULIB_SERIALIZATION_REGISTER_ARCHIVE(uLib::Archive::text_iarchive) ULIB_SERIALIZATION_REGISTER_ARCHIVE(uLib::Archive::text_oarchive) ULIB_SERIALIZATION_REGISTER_ARCHIVE(uLib::Archive::hrt_iarchive) ULIB_SERIALIZATION_REGISTER_ARCHIVE(uLib::Archive::hrt_oarchive) ULIB_SERIALIZATION_REGISTER_ARCHIVE(uLib::Archive::log_archive) //ULIB_SERIALIZATION_REGISTER_ARCHIVE(uLib::Archive::polymorphic_xml_iarchive) //ULIB_SERIALIZATION_REGISTER_ARCHIVE(uLib::Archive::polymorphic_xml_oarchive) //ULIB_SERIALIZATION_REGISTER_ARCHIVE(uLib::Archive::polymorphic_text_iarchive) //ULIB_SERIALIZATION_REGISTER_ARCHIVE(uLib::Archive::polymorphic_text_oarchive) //ULIB_SERIALIZATION_REGISTER_ARCHIVE(uLib::Archive::polymorphic_log_archive) #endif // U_CORE_ARCHIVES_H