00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
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
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
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
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
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
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
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 , int ){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 , int ){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
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
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
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