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"
70 <<
"#include <uhal/log/log_inserters.hpp>\n"
71 <<
"#include <uhal/log/LogLevels.hpp>\n"
72 <<
"#include <uhal/log/exception.hpp>\n"
75 <<
"namespace boost { class mutex; }\n"
77 <<
"namespace uhal{\n"
79 <<
"class DebugLevel;\n"
80 <<
"class InfoLevel;\n"
81 <<
"class NoticeLevel;\n"
82 <<
"class WarningLevel;\n"
83 <<
"class ErrorLevel;\n"
84 <<
"class FatalLevel;\n"
89 <<
"#include <sstream> // for ostream, stringstream, endl\n"
90 <<
"#include <string> // for operator+, basic_string\n"
92 <<
"#include <boost/thread/lock_guard.hpp> // for lock_guard\n"
93 <<
"#include <boost/thread/mutex.hpp> // for mutex\n"
95 <<
"#include \"uhal/log/exception.hpp\" // for exception\n"
96 <<
"#include \"uhal/log/LogLevels.hpp\" // for insert, ErrorLevel, DebugL...\n"
97 <<
"#include \"uhal/log/log_inserters.quote.hpp\" // for operator<<\n"
99 <<
"namespace uhal{\n"
104 <<
"#include <stdlib.h> // for getenv\n"
106 <<
"#include <boost/thread/mutex.hpp> // for mutex\n"
108 <<
"#include \"uhal/log/LogLevels.hpp\" // for BaseLogLevel, Info, Info...\n"
109 <<
"#include \"uhal/log/log.hpp\" // for log\n"
110 <<
"#include \"uhal/log/log_inserters.quote.hpp\" // for operator<<, Quote\n"
112 <<
"namespace uhal{\n"
122 <<
"\tFunction to specify that the logging level should be retrieved from an environment variable\n"
123 <<
"\t@param aEnvVar the name of the environment variable which is used to specify the logging level\n"
125 <<
"void setLogLevelFromEnvironment ( const char* aEnvVar );\n";
126 aCppFile <<
"void setLogLevelFromEnvironment ( const char* aEnvVar )\n"
128 <<
"\tchar * lEnvVar = getenv ( aEnvVar );\n"
129 <<
"\tif( !lEnvVar )\n"
132 <<
"\t\tlog( Warning() , \"No environment variable \" , Quote( aEnvVar ) , \" set. Using level \" , Quote( \"Info\" ) , \" instead.\" );\n"
137 <<
"\t//Just comparing the first letter of the environment variable for speed!!!\n"
138 <<
"\tswitch ( lEnvVar[0] )\n"
141 for ( std::vector< std::string >::const_iterator lIt =
gLogLevels.begin() ; lIt !=
gLogLevels.end() ; ++lIt )
143 aCppFile <<
"\t\tcase '" << char ( std::tolower ( lIt->at ( 0 ) ) ) <<
"' :\n"
144 <<
"\t\tcase '" << char ( std::toupper ( lIt->at ( 0 ) ) ) <<
"' :\n"
145 <<
"\t\t\tsetLogLevelTo ( " << *lIt <<
"() );\n"
149 aCppFile <<
"\t\tdefault:\n"
151 <<
"\t\t\tlog ( Warning() , \"Environment varible has invalid value \" , Quote( lEnvVar ) , \". Using level \" , Quote ( \"Info\" ) , \" instead.\" );\n"
152 <<
"\t\t\tsetLogLevelTo ( Info() );\n"
160 <<
"\tFunction to disable all logging levels\n"
162 <<
"void disableLogging();\n";
163 aCppFile <<
"void disableLogging()\n"
166 for ( std::vector< std::string >::const_iterator lIt =
gLogLevels.begin() ; lIt !=
gLogLevels.end() ; ++lIt )
168 aCppFile <<
"\tlog_configuration::mLoggingIncludes" << *lIt <<
" = false;\n";
177 <<
"\tFunction to retrieve the mutex lock used by the logger\n"
179 <<
"boost::mutex& GetLoggingMutex();\n";
180 aCppFile <<
"boost::mutex& GetLoggingMutex()\n"
182 <<
"\treturn log_configuration::mMutex;\n"
188 std::stringstream lIfDefs, lIfDefs2, lEndIfs;
190 for ( std::vector< std::string >::const_iterator lIt =
gLogLevels.begin() ; lIt !=
gLogLevels.end() ; ++lIt )
192 lIfDefs <<
"\t#ifndef LOGGING_EXCLUDE_" << boost::to_upper_copy ( *lIt ) <<
"\n";
193 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"
194 <<
"\t\tlog_configuration::mLoggingIncludes" << *lIt <<
" = true;\n";
195 lEndIfs <<
"\t#endif\n";
206 <<
"\tFunction to specify, at runtime, that only messages with a severity level above " << *lIt <<
" should be logged\n"
208 <<
"void setLogLevelTo ( const " << *lIt <<
"Level& /**< a dummy parameter to choose the specialization of the function for the " << *lIt <<
" level */ );\n";
209 aCppFile <<
"void setLogLevelTo ( const " << *lIt <<
"Level& )\n"
213 for ( std::vector< std::string >::const_iterator lIt2 = lIt+1 ; lIt2 !=
gLogLevels.end() ; ++lIt2 )
215 aCppFile <<
"\t\tlog_configuration::mLoggingIncludes" << *lIt2 <<
" = false;\n";
218 aCppFile << lEndIfs.str()
222 <<
"\tFunction to check at runtime whether the level " << *lIt <<
" is to be included in the log output\n"
223 <<
"\t@return whether the level " << *lIt <<
" is to be included in the log output\n"
225 <<
"const bool& LoggingIncludes ( const " << *lIt <<
"Level& /**< a dummy parameter to choose the specialization of the function for the " << *lIt <<
" level */ );\n"
227 aCppFile <<
"const bool& LoggingIncludes ( const " << *lIt <<
"Level& )\n"
230 <<
"\t\treturn log_configuration::mLoggingIncludes" << *lIt <<
";\n"
232 <<
"\treturn log_configuration::mFalse;\n"
237 aHppFile <<
"//! Class to restrict access to the log configuration parameters\n"
238 <<
"class log_configuration\n"
240 <<
"\t//! Constructor\n"
241 <<
"\tlog_configuration();\n"
242 <<
"\t//! Destructor\n"
243 <<
"\tvirtual ~log_configuration();\n"
245 <<
"\tfriend void disableLogging();\n"
247 bool lIncludeLevelByDefault (
true );
249 for ( std::vector< std::string >::const_iterator lIt =
gLogLevels.begin() ; lIt !=
gLogLevels.end() ; ++lIt )
251 aHppFile <<
"\t//! static bool storing whether the " << *lIt <<
" level is to be included in the log output\n"
252 <<
"\tstatic bool mLoggingIncludes" << *lIt <<
";\n";
254 if ( lIncludeLevelByDefault )
256 aCppFile <<
"bool log_configuration::mLoggingIncludes" << *lIt <<
" = true; // No #ifdefs required here since they are implemented in all the access functions.\n";
260 aCppFile <<
"bool log_configuration::mLoggingIncludes" << *lIt <<
" = false; // No #ifdefs required here since they are implemented in all the access functions.\n";
265 lIncludeLevelByDefault =
false;
268 aHppFile <<
"\t//!Make setLogLevelTo function a friend so it can access our private members\n"
269 <<
"\tfriend void setLogLevelTo ( const " << *lIt <<
"Level& );\n"
270 <<
"\t//!Make LoggingIncludes function a friend so it can access our private members\n"
271 <<
"\tfriend const bool& LoggingIncludes ( const " << *lIt <<
"Level& );\n"
275 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"
276 <<
"\tstatic const bool mTrue;\n"
277 <<
"\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"
278 <<
"\tstatic const bool mFalse;\n"
280 <<
"\t//!Make GetLoggingMutex function a friend so it can access our private members\n"
281 <<
"\tfriend boost::mutex& GetLoggingMutex();\n"
282 <<
"\t//!Define a static Mutex lock for thread safe logging\n"
283 <<
"\tstatic boost::mutex mMutex;\n"
287 <<
"const bool log_configuration::mTrue = true;\n"
288 <<
"const bool log_configuration::mFalse = false;\n"
290 <<
"boost::mutex log_configuration::mMutex;\n"
303 if ( i > 10 && i < 20 )
308 std::string lIndices[] = {
"th" ,
"st" ,
"nd" ,
"rd" ,
"th" ,
"th" ,
"th" ,
"th" ,
"th" ,
"th" };
309 return lIndices[ i%10 ];
313 void log_functions ( std::ofstream& aHppFile , std::ofstream& aHxxFile , std::ofstream& aCppFile )
315 std::stringstream lIfDefs , lEndIfs;
317 for ( std::vector< std::string >::const_iterator lIt =
gLogLevels.begin() ; lIt !=
gLogLevels.end() ; ++lIt )
319 lIfDefs <<
"\t#ifndef LOGGING_EXCLUDE_" << boost::to_upper_copy ( *lIt ) <<
"\n";
320 lEndIfs <<
"\t#endif\n";
321 std::stringstream lTemplates;
322 std::stringstream lArgs;
323 std::stringstream lInstructions;
324 std::stringstream lDoxygen;
325 lDoxygen <<
"\t\tFunction to add a log entry at " << *lIt <<
" level\n"
326 <<
"\t\t@param a" << *lIt <<
" a dummy parameter to choose the specialization of the function for the " << *lIt <<
" level\n";
328 for ( uint32_t i = 0 ; i!=MAX_NUM_ARGS ; ++i )
330 lTemplates <<
" typename T" << i <<
" ,";
331 std::string lTemplatesStr ( lTemplates.str() );
332 lTemplatesStr.resize ( lTemplatesStr.size()-1 );
333 lArgs <<
" const T" << i <<
"& aArg" << i <<
" ,";
334 std::string lArgsStr ( lArgs.str() );
335 lArgsStr.resize ( lArgsStr.size()-1 );
336 lInstructions <<
"\t\t\tinsert( lStr , aArg" << i <<
" );\n";
337 lDoxygen <<
"\t\t@param aArg" << i <<
" a templated argument to be added to the log " << ( i+1 ) <<
suffix ( i+1 ) <<
"\n";
338 aHppFile <<
"\t/**\n"
341 <<
"\ttemplate<" << lTemplatesStr <<
">\n"
343 <<
"\tvoid log ( " <<*lIt <<
"Level& a" << *lIt <<
" ," << lArgsStr <<
");\n"
345 aHxxFile <<
"template<" << lTemplatesStr <<
">\n"
347 <<
"void log ( " <<*lIt <<
"Level& a" << *lIt <<
" ," << lArgsStr <<
" )\n"
350 <<
"\t\tif( LoggingIncludes( a" << *lIt <<
" ) ){\n"
351 <<
"\t\t\tboost::lock_guard<boost::mutex> lLock ( GetLoggingMutex() );\n"
352 <<
"\t\t\tstd::ostream& lStr( a" << *lIt <<
".stream() );\n"
353 <<
"\t\t\ta" << *lIt <<
".head();\n"
354 << lInstructions.str()
355 <<
"\t\t\ta" << *lIt <<
".tail();\n"
369 std::stringstream lTemplates;
370 std::stringstream lArgs;
371 std::stringstream lInstructions;
372 std::stringstream lDoxygen;
374 for ( uint32_t i = 0 ; i!=MAX_NUM_ARGS ; ++i )
376 lTemplates <<
" typename T" << i <<
" ,";
377 std::string lTemplatesStr ( lTemplates.str() );
378 lTemplatesStr.resize ( lTemplatesStr.size()-1 );
379 lArgs <<
" const T" << i <<
"& aArg" << i <<
" ,";
380 std::string lArgsStr ( lArgs.str() );
381 lArgsStr.resize ( lArgsStr.size()-1 );
382 lInstructions <<
"\t\t\tinsert( lStr , aArg" << i <<
" );\n";
383 lDoxygen <<
"\t\t@param aArg" << i <<
" a templated argument to be added to the log " << ( i+1 ) <<
suffix ( i+1 ) <<
"\n";
384 aHppFile <<
"\t/**\n"
387 <<
"\ttemplate<" << lTemplatesStr <<
">\n"
389 <<
"\tvoid log ( exception::exception& aExc ," << lArgsStr <<
");\n"
391 aHxxFile <<
"template<" << lTemplatesStr <<
">\n"
393 <<
"void log ( exception::exception& aExc ," << lArgsStr <<
" )\n"
395 <<
"\t\t\tstd::stringstream lStr;\n"
397 <<
"\t\t\tboost::lock_guard<boost::mutex> lLock ( GetLoggingMutex() );\n"
398 << lInstructions.str()
399 <<
"\t\t\taExc.append( ( lStr.str() + \"\\n\" ).c_str() );\n"
401 <<
"\t\t\tlog ( Error() , lStr.str() );\n"
414 void fileFooters ( std::ofstream& aHppFile , std::ofstream& aHxxFile , std::ofstream& aCppFile )
417 <<
"#include \"uhal/log/log.hxx\"\n"
427 int main (
int argc ,
char* argv[] )
431 std::ofstream lHppFile (
"include/uhal/log/log.hpp" );
433 if ( !lHppFile.is_open() )
435 std::cout <<
"Unable to open HPP file" << std::endl;
439 std::ofstream lHxxFile (
"include/uhal/log/log.hxx" );
441 if ( !lHxxFile.is_open() )
443 std::cout <<
"Unable to open HXX file" << std::endl;
447 std::ofstream lCppFile (
"src/common/log.cpp" );
449 if ( !lCppFile.is_open() )
451 std::cout <<
"Unable to open CPP file" << std::endl;
463 catch (
const std::exception& aExc )
465 std::cerr <<
"ERROR: Caught exception : " << aExc.what() << std::endl;