1 #ifndef BOOST_SIMPLE_LOG_ARCHIVE_HPP 2 #define BOOST_SIMPLE_LOG_ARCHIVE_HPP 3 4 // MS compatible compilers support #pragma once 5 #if defined(_MSC_VER) 6 # pragma once 7 #endif 8 9 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 10 // simple_log_archive.hpp 11 12 // (C) Copyright 2010 Robert Ramey - http://www.rrsd.com . 13 // Use, modification and distribution is subject to the Boost Software 14 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 15 // http://www.boost.org/LICENSE_1_0.txt) 16 17 // See http://www.boost.org for updates, documentation, and revision history. 18 19 #include <ostream> 20 #include <cstddef> // std::size_t 21 22 #include <boost/config.hpp> 23 #if defined(BOOST_NO_STDC_NAMESPACE) 24 namespace std{ 25 using ::size_t; 26 } // namespace std 27 #endif 28 29 #include <boost/type_traits/is_enum.hpp> 30 #include <boost/mpl/bool.hpp> 31 #include <boost/mpl/eval_if.hpp> 32 #include <boost/mpl/int.hpp> 33 #include <boost/mpl/equal_to.hpp> 34 #include <boost/serialization/nvp.hpp> 35 #include <boost/serialization/array.hpp> 36 #include <boost/serialization/string.hpp> 37 #include <boost/serialization/access.hpp> 38 39 ///////////////////////////////////////////////////////////////////////// 40 // log data to an output stream. This illustrates a simpler implemenation 41 // of text output which is useful for getting a formatted display of 42 // any serializable class. Intended to be useful as a debugging aid. 43 class simple_log_archive { 44 std::ostream & m_os; 45 unsigned int m_depth; 46 47 template<class Archive> 48 struct save_enum_type { 49 template<class T> invokesimple_log_archive::save_enum_type50 static void invoke(Archive &ar, const T &t){ 51 ar.m_os << static_cast<int>(t); 52 } 53 }; 54 template<class Archive> 55 struct save_primitive { 56 template<class T> invokesimple_log_archive::save_primitive57 static void invoke(Archive & ar, const T & t){ 58 ar.m_os << t; 59 } 60 }; 61 template<class Archive> 62 struct save_only { 63 template<class T> invokesimple_log_archive::save_only64 static void invoke(Archive & ar, const T & t){ 65 // make sure call is routed through the highest interface that might 66 // be specialized by the user. 67 boost::serialization::serialize_adl( 68 ar, 69 const_cast<T &>(t), 70 ::boost::serialization::version< T >::value 71 ); 72 } 73 }; 74 template<class T> save(const T & t)75 void save(const T &t){ 76 typedef 77 BOOST_DEDUCED_TYPENAME boost::mpl::eval_if<boost::is_enum< T >, 78 boost::mpl::identity<save_enum_type<simple_log_archive> >, 79 //else 80 BOOST_DEDUCED_TYPENAME boost::mpl::eval_if< 81 // if its primitive 82 boost::mpl::equal_to< 83 boost::serialization::implementation_level< T >, 84 boost::mpl::int_<boost::serialization::primitive_type> 85 >, 86 boost::mpl::identity<save_primitive<simple_log_archive> >, 87 // else 88 boost::mpl::identity<save_only<simple_log_archive> > 89 > >::type typex; 90 typex::invoke(*this, t); 91 } 92 #ifndef BOOST_NO_STD_WSTRING save(const std::wstring & ws)93 void save(const std::wstring &ws){ 94 m_os << "wide string types not suported in log archive"; 95 } 96 #endif 97 98 public: 99 /////////////////////////////////////////////////// 100 // Implement requirements for archive concept 101 102 typedef boost::mpl::bool_<false> is_loading; 103 typedef boost::mpl::bool_<true> is_saving; 104 105 // this can be a no-op since we ignore pointer polymorphism 106 template<class T> register_type(const T * =NULL)107 void register_type(const T * = NULL){} 108 get_library_version()109 unsigned int get_library_version(){ 110 return 0; 111 } 112 113 void save_binary(const void * address,std::size_t count)114 save_binary(const void *address, std::size_t count){ 115 m_os << "save_binary not implemented"; 116 } 117 118 // the << operators 119 template<class T> operator <<(T const & t)120 simple_log_archive & operator<<(T const & t){ 121 m_os << ' '; 122 save(t); 123 return * this; 124 } 125 template<class T> operator <<(T * const t)126 simple_log_archive & operator<<(T * const t){ 127 m_os << " ->"; 128 if(NULL == t) 129 m_os << " null"; 130 else 131 *this << * t; 132 return * this; 133 } 134 template<class T, int N> operator <<(const T (& t)[N])135 simple_log_archive & operator<<(const T (&t)[N]){ 136 return *this << boost::serialization::make_array( 137 static_cast<const T *>(&t[0]), 138 N 139 ); 140 } 141 template<class T> operator <<(const boost::serialization::nvp<T> & t)142 simple_log_archive & operator<<(const boost::serialization::nvp< T > & t){ 143 m_os << '\n'; // start line with each named object 144 // indent according to object depth 145 for(unsigned int i = 0; i < m_depth; ++i) 146 m_os << ' '; 147 ++m_depth; 148 m_os << t.name(); // output the name of the object 149 * this << t.const_value(); 150 --m_depth; 151 return * this; 152 } 153 154 // the & operator 155 template<class T> operator &(const T & t)156 simple_log_archive & operator&(const T & t){ 157 return * this << t; 158 } 159 /////////////////////////////////////////////// 160 simple_log_archive(std::ostream & os)161 simple_log_archive(std::ostream & os) : 162 m_os(os), 163 m_depth(0) 164 {} 165 }; 166 167 #endif // BOOST_SIMPLE_LOG_ARCHIVE_HPP 168