Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

logging.h

Go to the documentation of this file.
00001 /*
00002 *
00003 * templog library
00004 *
00005 * Copyright Hendrik Schober
00006 * Distributed under the Boost Software License, Version 1.0.
00007 *    (See accompanying file LICENSE_1_0.txt or copy at
00008 *     http://www.boost.org/LICENSE_1_0.txt)
00009 *
00010 * see http://templog.sourceforge.net/ for more info
00011 *
00012 */
00013 
00116 #if !defined(TEMPLOG_LOGGING_H)
00117 #define TEMPLOG_LOGGING_H
00118 
00119 /**********************************************************************************************/
00120 #include "config.h"
00121 
00122 /**********************************************************************************************/
00123 #include <typeinfo>
00124 #include <iostream>
00125 #include <string>
00126 #include <sstream>
00127 #include <vector>
00128 
00129 /**********************************************************************************************/
00130 #include "type_lists.h"
00131 #include "tuples.h"
00132 
00133 /**********************************************************************************************/
00134 
00135 namespace templog {
00136 
00137     /******************************************************************************************/
00138     /* source information */
00139 
00140 #   define TEMPLOG_SOURCE                                __FILE__, __LINE__                                             
00141 #   define TEMPLOG_SOURCE_SIGN                           const char* const file_, const unsigned long line_             
00142 #   define TEMPLOG_SOURCE_SIGN_IGNORE                    const char* const , const unsigned long                        
00143 #   define TEMPLOG_SOURCE_PASS                           file_, line_                                                   
00144 #   define TEMPLOG_SOURCE_INIT                           file_data_(file_), line_data_(line_)                           
00145 #   define TEMPLOG_SOURCE_ASSIGN(Obj_)                   file_data_=Obj_.file_data_; line_data_=Obj_.line_data_         
00146 
00147 #   define TEMPLOG_SOURCE_FILE                           file_                                                          
00148 #   define TEMPLOG_SOURCE_LINE                           line_                                                          
00149 
00150 #   define TEMPLOG_SOURCE_DATA                           const char* const file_data_; const unsigned long line_data_   
00151 #   define TEMPLOG_SOURCE_DATA_PASS                      file_data_, line_data_                                         
00152 #   define TEMPLOG_SOURCE_DATA_FILE                      file_data_                                                     
00153 #   define TEMPLOG_SOURCE_DATA_LINE                      line_data_                                                     
00154 
00155 #   define TEMPLOG_SOURCE_ACCESS(Obj_)                   Obj_.file_data_, Obj_.line_data_                               
00156 #   define TEMPLOG_SOURCE_ACCESS_FILE(Obj_)              Obj_.file_data_                                                
00157 #   define TEMPLOG_SOURCE_ACCESS_LINE(Obj_)              Obj_.line_data_                                                
00158 
00159     /******************************************************************************************/
00160     /* severities and audiences */
00161 
00168     enum severity { sev_debug   = 1 
00169                   , sev_info        
00170                   , sev_message     
00171                   , sev_warning     
00172                   , sev_error       
00173                   , sev_fatal       
00174                   };
00175 
00182     enum audience { aud_developer = 1 
00183                   , aud_support       
00184                   , aud_user          
00185                   };
00186 
00192     template< int Aud1_, int Aud2_ = 0, int Aud3_ = 0 >
00193     struct audience_list : public templ_meta::int_type_list_generator< 0
00194                                                                        , Aud1_
00195                                                                        , Aud2_
00196                                                                        , Aud3_
00197                                                                        >::result_type
00198     {
00199         typedef typename templ_meta::int_type_list_generator< 0
00200                                                             , Aud1_
00201                                                             , Aud2_
00202                                                             , Aud3_
00203                                                             >::result_type
00204                                                         result_type;
00205     };
00206 
00210     const char* get_name(severity sev);
00211 
00215     const char* get_short_name(severity sev);
00216 
00220     const char* get_name(audience aud);
00221 
00225     const char* get_short_name(audience aud);
00226 
00227     /******************************************************************************************/
00228     /* log intermediate */
00229 
00235     template< int Sev_, int Aud_, bool Forward_, class Params_ >
00236     struct log_intermediate {
00237         typedef Params_                                 parameters_type;
00238 
00239         parameters_type                     parameters;
00240 
00241         log_intermediate( const parameters_type& p = parameters_type() )
00242             : parameters(p) {}
00243 
00244     };
00245 
00251     template< int Sev_, int Aud_, class ParamList_, typename Param_ >
00252     inline
00253     log_intermediate< Sev_, Aud_, false, templ_meta::nil >
00254     operator<<( const log_intermediate<Sev_,Aud_,false,ParamList_>&, const Param_& )
00255     {
00256         typedef log_intermediate< Sev_, Aud_
00257                                 , false
00258                                 , templ_meta::nil >     log_intermediate_t;
00259         return log_intermediate_t();
00260     }
00261 
00267     template< int Sev_, int Aud_, class ParamList_, typename Param_ >
00268     inline
00269     log_intermediate< Sev_, Aud_, true, templ_meta::tuple<const Param_*,ParamList_> >
00270     operator<<( const log_intermediate<Sev_,Aud_,true,ParamList_>& lim, const Param_& p )
00271     {
00272         typedef log_intermediate< Sev_, Aud_
00273                                 , true
00274                                 , templ_meta::tuple<const Param_*,ParamList_> >
00275                                                         log_intermediate_t;
00276         return log_intermediate_t( templ_meta::tuple<const Param_*,ParamList_>(&p,lim.parameters) );
00277     }
00278 
00279     /******************************************************************************************/
00280     /* log forwarder */
00281 
00288     template< class Logger_ >
00289     struct log_forwarder {
00290         TEMPLOG_SOURCE_DATA;
00291 
00292         log_forwarder(TEMPLOG_SOURCE_SIGN)
00293             : TEMPLOG_SOURCE_INIT {}
00294 
00295         template< int Sev_, int Aud_, bool Forward_, class Params_ >
00296         void operator=(const log_intermediate<Sev_,Aud_,Forward_,Params_>& li)
00297         { Logger_::fwd(TEMPLOG_SOURCE_DATA_PASS,li); }
00298 
00299         log_forwarder& operator=(const log_forwarder& rhs)
00300         { TEMPLOG_SOURCE_ASSIGN(rhs); return *this; }
00301 
00302     };
00303 
00304     /******************************************************************************************/
00305     /* logger */
00306 
00322     template< class Logger_
00323             , int MinSeverity_
00324             , class AudienceList_ >
00325     class logger;
00326 
00327     template< class Logger_
00328             , int MinSeverity_
00329             , int Aud1_, int Aud2_, int Aud3_ >
00330     class logger< Logger_, MinSeverity_, audience_list<Aud1_,Aud2_,Aud3_> > {
00331     private:
00332         typedef typename audience_list<Aud1_,Aud2_,Aud3_>::result_type
00333                                                         audience_list_type;
00334         template< int S_, int A_ >
00335         struct evaluate_params {
00336             enum { sev = ( MinSeverity_ <= S_ )
00337                  , aud = templ_meta::int_type_list_includes<audience_list_type,A_>::result
00338                  , result = (sev && aud) };
00339         };
00340     public:
00344         typedef logger< Logger_, MinSeverity_, audience_list<Aud1_,Aud2_,Aud3_> >
00345                                                         logger_type;
00349         typedef Logger_                                 forward_logger_type;
00350 
00354         static
00355         log_forwarder<logger_type>
00356         get_forwarder(TEMPLOG_SOURCE_SIGN)
00357         { return log_forwarder<logger_type>(TEMPLOG_SOURCE_PASS); }
00358 
00364         template< int Sev_, int Aud_ >
00365         static 
00366         log_intermediate<Sev_,Aud_,evaluate_params<Sev_,Aud_>::result,templ_meta::nil>
00367         get_intermediate()
00368         { return log_intermediate< Sev_, Aud_, evaluate_params<Sev_,Aud_>::result, templ_meta::nil >(); }
00369 
00373         template< int Sev_, int Aud_, class Params_ >
00374         static void fwd( TEMPLOG_SOURCE_SIGN_IGNORE, const log_intermediate< Sev_, Aud_, false, Params_ >& )
00375         {}
00376 
00380         template< int Sev_, int Aud_, class Params_ >
00381         static void fwd( TEMPLOG_SOURCE_SIGN       , const log_intermediate< Sev_, Aud_, true , Params_ >& lim )
00382         { forward_logger_type::fwd(TEMPLOG_SOURCE_PASS,lim); }
00383     };
00384 
00385     /******************************************************************************************/
00386     /* formatting policies */
00387 
00410     template< typename FormattingPolicy_ >
00411     class formating_policy_base {
00412     public:
00416         template< class WritePolicy_, int Sev_, int Aud_, class ParamList_ >
00417         static void write_msg(TEMPLOG_SOURCE_SIGN, const ParamList_& parameters)
00418         {
00419             typedef typename WritePolicy_::incremental_write_support
00420                                                           incremental_write_support;
00421             do_write<WritePolicy_,Sev_,Aud_>(TEMPLOG_SOURCE_PASS, parameters, incremental_write_support());
00422         }
00423 
00424     protected:
00429         template< class WritePolicy_, class WriteToken_, typename T >
00430         static void write_obj(WriteToken_& token, const T& obj)
00431         { do_write_obj<WritePolicy_>(token,obj); }
00432 
00436         template< class WritePolicy_, class WriteToken_, class Param_, class ParamList_ >
00437         static void write_params( WriteToken_& token 
00438                                 , const templ_meta::tuple<const Param_*,ParamList_>& parameters )
00439         { do_write_params_<WritePolicy_>(token,parameters); }
00440 
00441     private:
00442         template< class WritePolicy_, int Sev_, int Aud_, class ParamList_ >
00443         static void do_write(TEMPLOG_SOURCE_SIGN, const ParamList_& parameters, templ_meta::boolean<true>)
00444         {
00445             templ_meta::nil dummy;
00446             WritePolicy_::begin_write();
00447             FormattingPolicy_::template write<WritePolicy_,Sev_,Aud_>(dummy,TEMPLOG_SOURCE_PASS,parameters);
00448             do_write_endl<WritePolicy_>(dummy,typename WritePolicy_::needs_endl());
00449             WritePolicy_::end_write();
00450         }
00451 
00452         template< class WritePolicy_, int Sev_, int Aud_, class ParamList_ >
00453         static void do_write(TEMPLOG_SOURCE_SIGN, const ParamList_& parameters, templ_meta::boolean<false>)
00454         {
00455             std::ostringstream oss;
00456             FormattingPolicy_::template write<WritePolicy_,Sev_,Aud_>(oss,TEMPLOG_SOURCE_PASS,parameters);
00457             do_write_endl<WritePolicy_>(oss,typename WritePolicy_::needs_endl());
00458             WritePolicy_::write_str(oss.str());
00459         }
00460 
00461         template< class WritePolicy_, typename T >
00462         static void do_write_obj(templ_meta::nil&, const T& obj)
00463         { WritePolicy_::write_obj(obj); }
00464 
00465         template< class WritePolicy_, typename T >
00466         static void do_write_obj(std::ostream& os, const T& obj)
00467         { os << obj; }
00468 
00469         template< class WritePolicy_, class WriteToken_, class Param_, class ParamList_ >
00470         static void do_write_params_( WriteToken_& token 
00471                                     , const templ_meta::tuple<const Param_*,ParamList_>& parameters )
00472         {
00473             do_write_params_<WritePolicy_>(token,parameters.tail);
00474             do_write_params_<WritePolicy_>(token,parameters.head);
00475         }
00476 
00477         template< class WritePolicy_, class WriteToken_, class Param_ >
00478         static void do_write_params_( WriteToken_& token 
00479                                     , const Param_* pparameter )
00480         { write_obj<WritePolicy_>(token,*pparameter); }
00481 
00482         template< class WritePolicy_, class WriteToken_ >
00483         static void do_write_params_( WriteToken_& 
00484                                     , templ_meta::nil  )
00485         {}
00486 
00487         template< class WritePolicy_, class WriteToken_ >
00488         static void do_write_endl( WriteToken_& token 
00489                                  , templ_meta::boolean<true> )
00490         { write_obj<WritePolicy_>(token,'\n'); }
00491 
00492         template< class WritePolicy_, class WriteToken_ >
00493         static void do_write_endl( WriteToken_& token 
00494                                  , templ_meta::boolean<false> )
00495         {}
00496     };
00497 
00503     class sev_aud_formating_policy : public formating_policy_base<sev_aud_formating_policy> {
00504     public:
00505         template< class WritePolicy_, int Sev_, int Aud_, class WriteToken_, class ParamList_ >
00506         static void write(WriteToken_& token, TEMPLOG_SOURCE_SIGN_IGNORE, const ParamList_& parameters)
00507         {
00508             write_obj<WritePolicy_>( token, '<' );
00509             write_obj<WritePolicy_>( token, get_short_name(static_cast<severity>(Sev_)) );
00510             write_obj<WritePolicy_>( token, '|' );
00511             write_obj<WritePolicy_>( token, get_short_name(static_cast<audience>(Aud_)) );
00512             write_obj<WritePolicy_>( token, ">: " );
00513             write_params<WritePolicy_>(token, parameters);
00514         }
00515     };
00516 
00527     template< class FwdFormattingPolicy_ >
00528     class visual_studio_formating_policy : public formating_policy_base< visual_studio_formating_policy<FwdFormattingPolicy_> > {
00529     public:
00530         template< class WritePolicy_, int Sev_, int Aud_, class WriteToken_, class ParamList_ >
00531         static void write(WriteToken_& token, TEMPLOG_SOURCE_SIGN, const ParamList_& parameters)
00532         {
00533             typedef formating_policy_base< visual_studio_formating_policy<FwdFormattingPolicy_> > base;
00534             base::template write_obj<WritePolicy_>( token, TEMPLOG_SOURCE_FILE );
00535             base::template write_obj<WritePolicy_>( token, '(' );
00536             base::template write_obj<WritePolicy_>( token, TEMPLOG_SOURCE_LINE );
00537             base::template write_obj<WritePolicy_>( token, ") : " );
00538             FwdFormattingPolicy_::template write<WritePolicy_,Sev_,Aud_>( token, TEMPLOG_SOURCE_PASS, parameters );
00539         }
00540     };
00541 
00542     /******************************************************************************************/
00543     /* writing policies */
00544 
00563     template< class WritePolicy_, bool Endl_, bool Incremental_ >
00564     class write_policy_base {
00565     public:
00566         typedef templ_meta::boolean<Incremental_>         incremental_write_support;
00567         typedef templ_meta::boolean<Endl_>                needs_endl;
00568 
00569         template< class FormattingPolicy_, int Sev_, int Aud_, class ParamList_ >
00570         static void write_msg(TEMPLOG_SOURCE_SIGN, const ParamList_& parameters)
00571         { FormattingPolicy_::template write_msg<WritePolicy_,Sev_,Aud_>(TEMPLOG_SOURCE_PASS, parameters); }
00572     };
00573 
00598     template< class WritePolicy_, bool Endl_ >
00599     class incremental_write_policy_base : public write_policy_base<WritePolicy_,Endl_,true > {};
00600 
00620     template< class WritePolicy_, bool Endl_ >
00621     class non_incremental_write_policy_base : public write_policy_base<WritePolicy_,Endl_,false> {};
00622 
00628     class stderr_write_policy : public incremental_write_policy_base<stderr_write_policy,true> {
00629     public:
00630         template< int Sev_, int Aud_ >
00631         struct writes { enum { result = true }; };
00632 
00633         static bool is_writing(int /*sev*/, int /*aud*/){return true;}
00634 
00635         static void begin_write()                       {}
00636 
00637         template< typename T >
00638         static void write_obj(const T& obj)             {std::cerr << obj;}
00639 
00640         static void end_write()                         {}
00641 
00642     };
00643 
00652 #   if defined(_WIN32)
00653         class windbg_write_policy : public non_incremental_write_policy_base<windbg_write_policy,true> {
00654         public:
00655             template< int Sev_, int Aud_ >
00656             struct writes { enum { result = true }; };
00657 
00658             static bool is_writing(int /*sev*/, int /*aud*/){return true;}
00659 
00660             static void write_str(const std::string& str);
00661         };
00662 #   endif //defined(_WIN32)
00663 
00674     class dynamic_write_policy : public non_incremental_write_policy_base<dynamic_write_policy,true> {
00675     public:
00679         class writer_base {
00680         public:
00681             virtual bool is_writing(int, int) const        {return true;}
00682             virtual void write_str(const std::string& str) const = 0;
00683             //virtual ~writer_base() {} // virtual dtor not needed, no dynamic instances
00684         };
00685 
00691         template< class WritePolicy_ >
00692         class writer : public writer_base {
00693         public:
00694             virtual void write_str(const std::string& str) const
00695             { do_write_str(str,typename WritePolicy_::incremental_write_support()); }
00696         private:
00697             static void do_write_str(const std::string& str, templ_meta::boolean<true > )
00698             { WritePolicy_::write_obj(str); }
00699             static void do_write_str(const std::string& str, templ_meta::boolean<false> )
00700             { WritePolicy_::write_str(str); }
00701         };
00702 
00703         template< int Sev_, int Aud_ >
00704         struct writes { enum { result = true }; };
00705 
00706         static bool is_writing(int sev, int aud)
00707         { const writer_base* ptr=get(); return ptr ? ptr->is_writing(sev,aud) : false; }
00708 
00709         static void write_str(const std::string& str)
00710         { const writer_base* ptr=get(); if(ptr) ptr->write_str(str);  }
00711 
00717         static const writer_base* set_writer(const writer_base* pw)
00718         { std::swap(pw,get()); return pw; }
00719 
00726         template< class WritePolicy_ >
00727         class auto_writer : public writer<WritePolicy_> {
00728         public:
00729             auto_writer()                                 {set_writer(this);}
00730             ~auto_writer()                                {set_writer(NULL);}
00731         };
00732 
00733     private:
00734         static const writer_base*& get()
00735         { static const writer_base* ptr_=NULL; return ptr_; }
00736     };
00737 
00738     /******************************************************************************************/
00739     /* default formatting and write policies*/
00740 
00741 #   if defined(_WIN32)
00742         typedef visual_studio_formating_policy<sev_aud_formating_policy>  std_formating_policy;
00743         typedef windbg_write_policy                                       std_write_policy;
00744 #   else //defined(_WIN32)
00745         typedef sev_aud_formating_policy                                  std_formating_policy;
00746         typedef stderr_write_policy                                       std_write_policy;
00747 #   endif //defined(_WIN32)
00748 
00749     /******************************************************************************************/
00750     /* global logger */
00751 
00760     template< class FormattingPolicy_, class WritePolicy_ >
00761     class non_filtering_logger {
00762     public:
00763         template< int Sev_, int Aud_, class Params_ >
00764         static void fwd( TEMPLOG_SOURCE_SIGN, const log_intermediate< Sev_, Aud_, false , Params_ >& )
00765         {}
00766 
00767         template< int Sev_, int Aud_, class Params_ >
00768         static void fwd( TEMPLOG_SOURCE_SIGN, const log_intermediate< Sev_, Aud_, true , Params_ >& lim )
00769         { WritePolicy_::template write_msg<FormattingPolicy_,Sev_,Aud_>(TEMPLOG_SOURCE_PASS, lim.parameters); }
00770     };
00771 
00779     typedef non_filtering_logger< std_formating_policy
00780                                 , std_write_policy>   global_logger;
00781 
00782     /******************************************************************************************/
00783 
00784 }
00785 
00786 using templog::sev_debug;
00787 using templog::sev_info;
00788 using templog::sev_message;
00789 using templog::sev_warning;
00790 using templog::sev_error;
00791 using templog::sev_fatal;
00792 
00793 using templog::aud_developer;
00794 using templog::aud_support;
00795 using templog::aud_user;
00796 
00805 #define TEMPLOG_LOG(TLogger_,Sev_,Aud_) TLogger_::get_forwarder(TEMPLOG_SOURCE) = \
00806                                         TLogger_::template get_intermediate<Sev_,Aud_>()
00807 
00808 /**********************************************************************************************/
00809 
00810 #endif //defined(TEMPLOG_LOGGING_H)
00811 
00812 /**********************************************************************************************/
00813 /* EOF */

Generated on Sun Jan 11 15:57:20 2009 for templog library by  doxygen 1.4.2