/*////////////////////////////////////////////////////////////////////////////// // 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 #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 hrt_iarchive; class hrt_oarchive; class log_archive; } // namespace Archive } // namespace uLib namespace boost { namespace archive { namespace detail { template class polymorphic_oarchive_route; template class polymorphic_iarchive_route; } // namespace detail } // namespace archive } // namespace boost namespace boost { namespace serialization { template struct hrp; template struct hrp_val; template struct hrp_enum; template struct hrp_enum_val; } } // namespace boost //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // ARCHIVES REGISTRATION // namespace uLib { namespace Archive { namespace detail { struct adl_tag {}; } // namespace detail } // namespace Archive } // namespace uLib 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) {} } // namespace detail } // namespace archive } // namespace boost // 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 * = nullptr) { 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); return *this->This(); } template Archive &operator>>(const boost::serialization::nvp &t) { this->This()->load_override(t); return *this->This(); } template Archive &operator>>(const boost::serialization::hrp &t) { this->This()->load_override(const_cast &>(t)); return *this->This(); } template Archive &operator>>(const boost::serialization::hrp_val &t) { this->This()->load_override(const_cast &>(t)); return *this->This(); } template Archive &operator>>(const boost::serialization::hrp_enum &t) { this->This()->load_override(const_cast &>(t)); return *this->This(); } template Archive &operator>>(const boost::serialization::hrp_enum_val &t) { this->This()->load_override(const_cast &>(t)); return *this->This(); } // the & operator template Archive &operator&(T &t) { return *(this->This()) >> t; } template Archive &operator&(const boost::serialization::nvp &t) { return *(this->This()) >> t; } template Archive &operator&(const boost::serialization::hrp &t) { return *(this->This()) >> t; } template Archive &operator&(const boost::serialization::hrp_val &t) { return *(this->This()) >> t; } template Archive &operator&(const boost::serialization::hrp_enum &t) { return *(this->This()) >> t; } template Archive &operator&(const boost::serialization::hrp_enum_val &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) { 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 * = nullptr) { 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<<(const T &t) { // to get access you must redefine save_override by typing // "using save_override" in archive impl this->This()->save_override(t); return *this->This(); } template Archive &operator<<(const boost::serialization::hrp &t) { this->This()->save_override(t); return *this->This(); } template Archive &operator<<(const boost::serialization::hrp_val &t) { this->This()->save_override(t); return *this->This(); } template Archive &operator<<(const boost::serialization::hrp_enum &t) { this->This()->save_override(t); return *this->This(); } template Archive &operator<<(const boost::serialization::hrp_enum_val &t) { this->This()->save_override(t); return *this->This(); } template Archive &operator<<(const boost::serialization::nvp &t) { this->This()->save_override(t); return *this->This(); } // the & operator template Archive &operator&(const T &t) { return *this->This() << t; } template Archive &operator&(const boost::serialization::hrp &t) { return *this->This() << t; } template Archive &operator&(const boost::serialization::hrp_val &t) { return *this->This() << t; } template Archive &operator&(const boost::serialization::hrp_enum &t) { return *this->This() << t; } template Archive &operator&(const boost::serialization::hrp_enum_val &t) { return *this->This() << t; } template Archive &operator&(const boost::serialization::nvp &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) { 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_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 {}; } // namespace detail } // namespace archive } // namespace boost //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // ARCHIVES DEFINITIONS // namespace boost { namespace archive { } // namespace archive } // namespace boost namespace uLib { namespace Archive { //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // XML // // ULIB_SERIALIZATION_VERSION should be get from the build system #ifndef ULIB_SERIALIZATION_VERSION #define ULIB_SERIALIZATION_VERSION "0.0" #endif class xml_iarchive : public boost::archive::xml_iarchive_impl { typedef xml_iarchive Archive; typedef boost::archive::xml_iarchive_impl base; unsigned int m_flags; // 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) : boost::archive::xml_iarchive_impl( is, flags | boost::archive::no_header), m_flags(flags) { if (0 == (flags & boost::archive::no_header)) { std::string line; std::getline(is, line); // std::getline(is, line); // std::getline(is, line); // } } // 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) { this->This()->load_start(t.name()); this->detail_common_iarchive::load_override(t.value()); 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 .. // Note: using base::load_override covers all basic_xml_iarchive overloads // transitively, so a separate 'using basic_xml_iarchive::load_override' // is redundant and creates ambiguity with clang. using base::load_override; void load_override(const char *str) { // StringReader sr(basic_text_iprimitive::is); // sr >> str; } virtual ~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> { public: virtual void load_override(const char *str) {} }; class xml_oarchive : public boost::archive::xml_oarchive_impl { typedef xml_oarchive Archive; typedef boost::archive::xml_oarchive_impl base; unsigned int m_flags; // 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 | boost::archive::no_header), m_flags(flags) { if (0 == (flags & boost::archive::no_header)) { this->This()->put( "\n"); this->This()->put("\n"); this->This()->put("write_attribute("version", (const char *)ULIB_SERIALIZATION_VERSION); this->This()->put(">\n"); } } virtual ~xml_oarchive() { if (0 == (m_flags & boost::archive::no_header)) { this->This()->put("\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) { this->This()->save_start(t.name()); this->detail_common_oarchive::save_override(t.const_value()); this->This()->save_end(t.name()); } void save_override(const char *str) { // Do not save any human decoration string // // basic_text_oprimitive::save(str); } }; // 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 base::load_override; void load_override(boost::archive::object_id_type &t) {} void load_override(const char *str) { StringReader sr(basic_text_iprimitive::is); sr >> str; } virtual ~text_iarchive() {} }; typedef text_iarchive naked_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) { basic_text_oprimitive::save(str); } virtual ~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 base::load_override; // hide all archive props // void load_override(boost::archive::object_id_type &t) {} void load_override(boost::archive::object_reference_type &t) {} void load_override(boost::archive::version_type &t) {} void load_override(boost::archive::class_id_type &t) {} void load_override(boost::archive::class_id_optional_type &t) {} void load_override(boost::archive::class_id_reference_type &t) {} void load_override(boost::archive::class_name_type &t) {} void load_override(boost::archive::tracking_type &t) {} void load_override(const char *str) { StringReader sr(basic_text_iprimitive::is); sr >> str; } virtual ~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) {} void save_override(const boost::archive::object_reference_type &t) {} void save_override(const boost::archive::version_type &t) {} void save_override(const boost::archive::class_id_type &t) {} void save_override(const boost::archive::class_id_optional_type &t) {} void save_override(const boost::archive::class_id_reference_type &t) {} void save_override(const boost::archive::class_name_type &t) {} void save_override(const boost::archive::tracking_type &t) {} void save_override(const char *str) { basic_text_oprimitive::save(str); } template void save_override(const boost::serialization::hrp &t) { *this << t.name() << ": "; *this << t.const_value(); *this << "\n"; } virtual ~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) { // Do not save any human decoration string // // basic_text_oprimitive::save(str); } template void save_override(const T &t) { base::save_override(boost::serialization::make_nvp(nullptr, t)); } template void save_override(const boost::serialization::nvp &t) { base::save_override(t); } template void save_override(const boost::serialization::hrp &t) { base::save_override(boost::serialization::make_nvp(t.name(), t.const_value())); } // 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) {} void save_override(const boost::archive::object_reference_type &t) {} void save_override(const boost::archive::version_type &t) {} void save_override(const boost::archive::class_id_type &t) {} void save_override(const boost::archive::class_id_optional_type &t) {} void save_override(const boost::archive::class_id_reference_type &t) {} void save_override(const boost::archive::class_name_type &t) {} void save_override(const boost::archive::tracking_type &t) {} public: log_archive(std::ostream &os, unsigned int flags = 0) : boost::archive::xml_oarchive_impl( os, flags | boost::archive::no_header) {} virtual ~log_archive() {} }; } // namespace Archive } // namespace 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) #endif // U_CORE_ARCHIVES_H