44 #include <boost/algorithm/string/case_conv.hpp> 47 static const std::string
gLogLevelsChar[] = {
"Fatal" ,
"Error" ,
"Warning" ,
"Notice" ,
"Info" ,
"Debug" };
56 std::string
gDivider (
"// " + std::string ( 150,
'=' ) +
"\n" +
57 "// WARNING! This file is automatically generated! Do not modify it! Any changes will be overwritten!\n" +
58 "// " + std::string ( 150,
'=' ) +
"\n" );
62 void fileHeaders ( std::ofstream& aHppFile , std::ofstream& aHxxFile , std::ofstream& aCppFile )
65 <<
"#ifndef _uhal_log_log_hpp_\n" 66 <<
"#define _uhal_log_log_hpp_\n" 68 <<
"#include <iosfwd> // for ostream\n" 69 <<
"#include <boost/thread/mutex.hpp>\n" 70 <<
"#include <boost/thread/lock_guard.hpp>\n" 71 <<
"#include <uhal/log/log_inserters.hpp>\n" 72 <<
"#include <uhal/log/LogLevels.hpp>\n" 73 <<
"#include <uhal/log/exception.hpp>\n" 76 <<
"#define logging()\n" 78 <<
"namespace boost { class mutex; }\n" 80 <<
"namespace uhal{\n" 82 <<
"class DebugLevel;\n" 83 <<
"class InfoLevel;\n" 84 <<
"class NoticeLevel;\n" 85 <<
"class WarningLevel;\n" 86 <<
"class ErrorLevel;\n" 87 <<
"class FatalLevel;\n" 92 <<
"#include <sstream> // for ostream, stringstream, endl\n" 93 <<
"#include <string> // for operator+, basic_string\n" 95 <<
"#include <boost/thread/lock_guard.hpp> // for lock_guard\n" 96 <<
"#include <boost/thread/mutex.hpp> // for mutex\n" 98 <<
"#include \"uhal/log/exception.hpp\" // for exception\n" 99 <<
"#include \"uhal/log/LogLevels.hpp\" // for insert, ErrorLevel, DebugL...\n" 100 <<
"#include \"uhal/log/log_inserters.quote.hpp\" // for operator<<\n" 102 <<
"namespace uhal{\n" 107 <<
"#include <stdlib.h> // for getenv\n" 108 <<
"#include <boost/thread/mutex.hpp> // for mutex\n" 109 <<
"#include \"uhal/log/LogLevels.hpp\" // for BaseLogLevel, Info, Info...\n" 110 <<
"#include \"uhal/log/log.hpp\" // for log\n" 111 <<
"#include \"uhal/log/log_inserters.quote.hpp\" // for operator<<, Quote\n" 113 <<
"namespace uhal{\n" 123 <<
"\tFunction to specify that the logging level should be retrieved from an environment variable\n" 124 <<
"\t@param aEnvVar the name of the environment variable which is used to specify the logging level\n" 126 <<
"void setLogLevelFromEnvironment ( const char* aEnvVar );\n";
127 aCppFile <<
"void setLogLevelFromEnvironment ( const char* aEnvVar )\n" 129 <<
"\tchar * lEnvVar = getenv ( aEnvVar );\n" 130 <<
"\tif( !lEnvVar )\n" 133 <<
"\t\tlog( Warning() , \"No environment variable \" , Quote( aEnvVar ) , \" set. Using level \" , Quote( \"Info\" ) , \" instead.\" );\n" 138 <<
"\t//Just comparing the first letter of the environment variable for speed!!!\n" 139 <<
"\tswitch ( lEnvVar[0] )\n" 142 for ( std::vector< std::string >::const_iterator lIt =
gLogLevels.begin() ; lIt !=
gLogLevels.end() ; ++lIt )
144 aCppFile <<
"\t\tcase '" << char ( std::tolower ( lIt->at ( 0 ) ) ) <<
"' :\n" 145 <<
"\t\tcase '" << char ( std::toupper ( lIt->at ( 0 ) ) ) <<
"' :\n" 146 <<
"\t\t\tsetLogLevelTo ( " << *lIt <<
"() );\n" 150 aCppFile <<
"\t\tdefault:\n" 152 <<
"\t\t\tlog ( Warning() , \"Environment varible has invalid value \" , Quote( lEnvVar ) , \". Using level \" , Quote ( \"Info\" ) , \" instead.\" );\n" 153 <<
"\t\t\tsetLogLevelTo ( Info() );\n" 161 <<
"\tFunction to disable all logging levels\n" 163 <<
"void disableLogging();\n";
164 aCppFile <<
"void disableLogging()\n" 167 for ( std::vector< std::string >::const_iterator lIt =
gLogLevels.begin() ; lIt !=
gLogLevels.end() ; ++lIt )
169 aCppFile <<
"\tlog_configuration::mLoggingIncludes" << *lIt <<
" = false;\n";
178 <<
"\tFunction to retrieve the mutex lock used by the logger\n" 180 <<
"boost::mutex& GetLoggingMutex();\n";
181 aCppFile <<
"boost::mutex& GetLoggingMutex()\n" 183 <<
"\treturn log_configuration::mMutex;\n" 189 std::stringstream lIfDefs, lIfDefs2, lEndIfs;
191 for ( std::vector< std::string >::const_iterator lIt =
gLogLevels.begin() ; lIt !=
gLogLevels.end() ; ++lIt )
193 lIfDefs <<
"\t#ifndef LOGGING_EXCLUDE_" << boost::to_upper_copy ( *lIt ) <<
"\n";
194 lIfDefs2 <<
"\t#ifndef LOGGING_EXCLUDE_" << boost::to_upper_copy ( *lIt ) <<
" // A waste of time to change any level below this if it is going to disabled by compile-time checking anyway... \n" 195 <<
"\t\tlog_configuration::mLoggingIncludes" << *lIt <<
" = true;\n";
196 lEndIfs <<
"\t#endif\n";
207 <<
"\tFunction to specify, at runtime, that only messages with a severity level above " << *lIt <<
" should be logged\n" 209 <<
"void setLogLevelTo ( const " << *lIt <<
"Level& /**< a dummy parameter to choose the specialization of the function for the " << *lIt <<
" level */ );\n";
210 aCppFile <<
"void setLogLevelTo ( const " << *lIt <<
"Level& )\n" 214 for ( std::vector< std::string >::const_iterator lIt2 = lIt+1 ; lIt2 !=
gLogLevels.end() ; ++lIt2 )
216 aCppFile <<
"\t\tlog_configuration::mLoggingIncludes" << *lIt2 <<
" = false;\n";
219 aCppFile << lEndIfs.str()
223 <<
"\tFunction to check at runtime whether the level " << *lIt <<
" is to be included in the log output\n" 224 <<
"\t@return whether the level " << *lIt <<
" is to be included in the log output\n" 226 <<
"const bool& LoggingIncludes ( const " << *lIt <<
"Level& /**< a dummy parameter to choose the specialization of the function for the " << *lIt <<
" level */ );\n" 228 aCppFile <<
"const bool& LoggingIncludes ( const " << *lIt <<
"Level& )\n" 231 <<
"\t\treturn log_configuration::mLoggingIncludes" << *lIt <<
";\n" 233 <<
"\treturn log_configuration::mFalse;\n" 238 aHppFile <<
"//! Class to restrict access to the log configuration parameters\n" 239 <<
"class log_configuration\n" 241 <<
"\t//! Constructor\n" 242 <<
"\tlog_configuration();\n" 243 <<
"\t//! Destructor\n" 244 <<
"\tvirtual ~log_configuration();\n" 246 <<
"\tfriend void disableLogging();\n" 248 bool lIncludeLevelByDefault (
true );
250 for ( std::vector< std::string >::const_iterator lIt =
gLogLevels.begin() ; lIt !=
gLogLevels.end() ; ++lIt )
252 aHppFile <<
"\t//! static bool storing whether the " << *lIt <<
" level is to be included in the log output\n" 253 <<
"\tstatic bool mLoggingIncludes" << *lIt <<
";\n";
255 if ( lIncludeLevelByDefault )
257 aCppFile <<
"bool log_configuration::mLoggingIncludes" << *lIt <<
" = true; // No #ifdefs required here since they are implemented in all the access functions.\n";
261 aCppFile <<
"bool log_configuration::mLoggingIncludes" << *lIt <<
" = false; // No #ifdefs required here since they are implemented in all the access functions.\n";
264 if ( *lIt == gDefaultLevel )
266 lIncludeLevelByDefault =
false;
269 aHppFile <<
"\t//!Make setLogLevelTo function a friend so it can access our private members\n" 270 <<
"\tfriend void setLogLevelTo ( const " << *lIt <<
"Level& );\n" 271 <<
"\t//!Make LoggingIncludes function a friend so it can access our private members\n" 272 <<
"\tfriend const bool& LoggingIncludes ( const " << *lIt <<
"Level& );\n" 276 aHppFile <<
"\t//!Define a static const member variable to have a value of true so that we can safely return a const reference to true\n" 277 <<
"\tstatic const bool mTrue;\n" 278 <<
"\t//!Define a static const member variable to have a value of false so that we can safely return a const reference to false\n" 279 <<
"\tstatic const bool mFalse;\n" 281 <<
"\t//!Make GetLoggingMutex function a friend so it can access our private members\n" 282 <<
"\tfriend boost::mutex& GetLoggingMutex();\n" 283 <<
"\t//!Define a static Mutex lock for thread safe logging\n" 284 <<
"\tstatic boost::mutex mMutex;\n" 288 <<
"const bool log_configuration::mTrue = true;\n" 289 <<
"const bool log_configuration::mFalse = false;\n" 291 <<
"boost::mutex log_configuration::mMutex;\n" 304 if ( i > 10 && i < 20 )
309 std::string lIndices[] = {
"th" ,
"st" ,
"nd" ,
"rd" ,
"th" ,
"th" ,
"th" ,
"th" ,
"th" ,
"th" };
310 return lIndices[ i%10 ];
314 void log_functions ( std::ofstream& aHppFile , std::ofstream& aHxxFile , std::ofstream& aCppFile )
316 std::stringstream lIfDefs , lEndIfs;
318 for ( std::vector< std::string >::const_iterator lIt =
gLogLevels.begin() ; lIt !=
gLogLevels.end() ; ++lIt )
320 lIfDefs <<
"\t#ifndef LOGGING_EXCLUDE_" << boost::to_upper_copy ( *lIt ) <<
"\n";
321 lEndIfs <<
"\t#endif\n";
322 std::stringstream lTemplates;
323 std::stringstream lArgs;
324 std::stringstream lInstructions;
325 std::stringstream lDoxygen;
326 lDoxygen <<
"\t\tFunction to add a log entry at " << *lIt <<
" level\n" 327 <<
"\t\t@param a" << *lIt <<
" a dummy parameter to choose the specialization of the function for the " << *lIt <<
" level\n";
329 for ( uint32_t i = 0 ; i!=MAX_NUM_ARGS ; ++i )
331 lTemplates <<
" typename T" << i <<
" ,";
332 std::string lTemplatesStr ( lTemplates.str() );
333 lTemplatesStr.resize ( lTemplatesStr.size()-1 );
334 lArgs <<
" const T" << i <<
"& aArg" << i <<
" ,";
335 std::string lArgsStr ( lArgs.str() );
336 lArgsStr.resize ( lArgsStr.size()-1 );
337 lInstructions <<
"\t\t\tinsert( lStr , aArg" << i <<
" );\n";
338 lDoxygen <<
"\t\t@param aArg" << i <<
" a templated argument to be added to the log " << ( i+1 ) <<
suffix ( i+1 ) <<
"\n";
339 aHppFile <<
"\t/**\n" 342 <<
"\ttemplate<" << lTemplatesStr <<
">\n" 344 <<
"\tvoid log ( " <<*lIt <<
"Level& a" << *lIt <<
" ," << lArgsStr <<
");\n" 346 aHxxFile <<
"template<" << lTemplatesStr <<
">\n" 348 <<
"void log ( " <<*lIt <<
"Level& a" << *lIt <<
" ," << lArgsStr <<
" )\n" 351 <<
"\t\tif( LoggingIncludes( a" << *lIt <<
" ) ){\n" 352 <<
"\t\t\tboost::lock_guard<boost::mutex> lLock ( GetLoggingMutex() );\n" 353 <<
"\t\t\tstd::ostream& lStr( a" << *lIt <<
".stream() );\n" 354 <<
"\t\t\ta" << *lIt <<
".head();\n" 355 << lInstructions.str()
356 <<
"\t\t\ta" << *lIt <<
".tail();\n" 370 std::stringstream lTemplates;
371 std::stringstream lArgs;
372 std::stringstream lInstructions;
373 std::stringstream lDoxygen;
375 for ( uint32_t i = 0 ; i!=MAX_NUM_ARGS ; ++i )
377 lTemplates <<
" typename T" << i <<
" ,";
378 std::string lTemplatesStr ( lTemplates.str() );
379 lTemplatesStr.resize ( lTemplatesStr.size()-1 );
380 lArgs <<
" const T" << i <<
"& aArg" << i <<
" ,";
381 std::string lArgsStr ( lArgs.str() );
382 lArgsStr.resize ( lArgsStr.size()-1 );
383 lInstructions <<
"\t\t\tinsert( lStr , aArg" << i <<
" );\n";
384 lDoxygen <<
"\t\t@param aArg" << i <<
" a templated argument to be added to the log " << ( i+1 ) <<
suffix ( i+1 ) <<
"\n";
385 aHppFile <<
"\t/**\n" 388 <<
"\ttemplate<" << lTemplatesStr <<
">\n" 390 <<
"\tvoid log ( exception::exception& aExc ," << lArgsStr <<
");\n" 392 aHxxFile <<
"template<" << lTemplatesStr <<
">\n" 394 <<
"void log ( exception::exception& aExc ," << lArgsStr <<
" )\n" 396 <<
"\t\t\tstd::stringstream lStr;\n" 398 <<
"\t\t\tboost::lock_guard<boost::mutex> lLock ( GetLoggingMutex() );\n" 399 << lInstructions.str()
400 <<
"\t\t\taExc.append( ( lStr.str() + \"\\n\" ).c_str() );\n" 402 <<
"\t\t\tlog ( Error() , lStr.str() );\n" 414 std::stringstream lTemplates;
415 std::stringstream lArgs;
416 std::stringstream lInstructions;
417 std::stringstream lDoxygen;
419 for ( uint32_t i = 0 ; i!=MAX_NUM_ARGS ; ++i )
421 lTemplates <<
" typename T" << i <<
" ,";
422 std::string lTemplatesStr ( lTemplates.str() );
423 lTemplatesStr.resize ( lTemplatesStr.size()-1 );
424 lArgs <<
" const T" << i <<
"& aArg" << i <<
" ,";
425 std::string lArgsStr ( lArgs.str() );
426 lArgsStr.resize ( lArgsStr.size()-1 );
427 lInstructions <<
"\t\t\tinsert( aStr , aArg" << i <<
" );\n";
428 lDoxygen <<
"\t\t@param aArg" << i <<
" a templated argument to be added to the log " << ( i+1 ) <<
suffix ( i+1 ) <<
"\n";
429 aHppFile <<
"\t/**\n" 432 <<
"\ttemplate<" << lTemplatesStr <<
">\n" 434 <<
"\tvoid log ( std::ostream& aStr ," << lArgsStr <<
");\n" 436 aHxxFile <<
"template<" << lTemplatesStr <<
">\n" 438 <<
"void log ( std::ostream& aStr ," << lArgsStr <<
" )\n" 440 <<
"\t\t\tboost::lock_guard<boost::mutex> lLock ( GetLoggingMutex() );\n" 441 << lInstructions.str()
442 <<
"\t\t\taStr << std::endl;\n" 458 void fileFooters ( std::ofstream& aHppFile , std::ofstream& aHxxFile , std::ofstream& aCppFile )
461 <<
"#include \"uhal/log/log.hxx\"\n" 471 int main (
int argc ,
char* argv[] )
475 std::ofstream lHppFile (
"include/uhal/log/log.hpp" );
477 if ( !lHppFile.is_open() )
479 std::cout <<
"Unable to open HPP file" << std::endl;
483 std::ofstream lHxxFile (
"include/uhal/log/log.hxx" );
485 if ( !lHxxFile.is_open() )
487 std::cout <<
"Unable to open HXX file" << std::endl;
491 std::ofstream lCppFile (
"src/common/log.cpp" );
493 if ( !lCppFile.is_open() )
495 std::cout <<
"Unable to open CPP file" << std::endl;
507 catch (
const std::exception& aExc )
509 std::cerr <<
"ERROR: Caught exception : " << aExc.what() << std::endl;
std::string gDivider("// "+std::string(150,'=')+"\+"//WARNING! This file is automatically generated! Do not modify it! Any changes will be overwritten!\"+"//"+std::string(150,'=')+"\")
void log_configuration_functions(std::ofstream &aHppFile, std::ofstream &aHxxFile, std::ofstream &aCppFile)
std::string suffix(uint32_t i)
static const std::string gLogLevelsChar[]
void fileFooters(std::ofstream &aHppFile, std::ofstream &aHxxFile, std::ofstream &aCppFile)
static const uint32_t gNumberEntries(6)
int main(int argc, char *argv[])
static const std::string gDefaultLevel("Info")
void fileHeaders(std::ofstream &aHppFile, std::ofstream &aHxxFile, std::ofstream &aCppFile)
void log_functions(std::ofstream &aHppFile, std::ofstream &aHxxFile, std::ofstream &aCppFile)
static const std::vector< std::string > gLogLevels(gLogLevelsChar, gLogLevelsChar+gNumberEntries)