44#include <boost/algorithm/string/case_conv.hpp>
47static const std::string
gLogLevelsChar[] = {
"Fatal" ,
"Error" ,
"Warning" ,
"Notice" ,
"Info" ,
"Debug" };
56std::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" );
62void 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 <mutex> // for lock_guard, mutex\n"
71 <<
"#include <uhal/log/log_inserters.hpp>\n"
72 <<
"#include <uhal/log/LogLevels.hpp>\n"
73 <<
"#include <uhal/log/exception.hpp>\n"
76 <<
"namespace uhal{\n"
78 <<
"class DebugLevel;\n"
79 <<
"class InfoLevel;\n"
80 <<
"class NoticeLevel;\n"
81 <<
"class WarningLevel;\n"
82 <<
"class ErrorLevel;\n"
83 <<
"class FatalLevel;\n"
88 <<
"#include <mutex> // for lock_guard, mutex\n"
89 <<
"#include <sstream> // for ostream, stringstream, endl\n"
90 <<
"#include <string> // for operator+, basic_string\n"
92 <<
"#include \"uhal/log/exception.hpp\" // for exception\n"
93 <<
"#include \"uhal/log/LogLevels.hpp\" // for insert, ErrorLevel, DebugL...\n"
94 <<
"#include \"uhal/log/log_inserters.quote.hpp\" // for operator<<\n"
96 <<
"namespace uhal{\n"
101 <<
"#include <mutex> // for lock_guard, mutex\n"
102 <<
"#include <stdlib.h> // for getenv\n"
104 <<
"#include \"uhal/log/LogLevels.hpp\" // for BaseLogLevel, Info, Info...\n"
105 <<
"#include \"uhal/log/log.hpp\" // for log\n"
106 <<
"#include \"uhal/log/log_inserters.quote.hpp\" // for operator<<, Quote\n"
108 <<
"namespace uhal{\n"
118 <<
"\tFunction to specify that the logging level should be retrieved from an environment variable\n"
119 <<
"\t@param aEnvVar the name of the environment variable which is used to specify the logging level\n"
121 <<
"void setLogLevelFromEnvironment ( const char* aEnvVar );\n";
122 aCppFile <<
"void setLogLevelFromEnvironment ( const char* aEnvVar )\n"
124 <<
"\tchar * lEnvVar = getenv ( aEnvVar );\n"
125 <<
"\tif( !lEnvVar )\n"
128 <<
"\t\tlog( Warning() , \"No environment variable \" , Quote( aEnvVar ) , \" set. Using level \" , Quote( \"Info\" ) , \" instead.\" );\n"
133 <<
"\t//Just comparing the first letter of the environment variable for speed!!!\n"
134 <<
"\tswitch ( lEnvVar[0] )\n"
139 aCppFile <<
"\t\tcase '" << char ( std::tolower ( lLevel.at ( 0 ) ) ) <<
"' :\n"
140 <<
"\t\tcase '" << char ( std::toupper ( lLevel.at ( 0 ) ) ) <<
"' :\n"
141 <<
"\t\t\tsetLogLevelTo ( " << lLevel <<
"() );\n"
145 aCppFile <<
"\t\tdefault:\n"
147 <<
"\t\t\tlog ( Warning() , \"Environment varible has invalid value \" , Quote( lEnvVar ) , \". Using level \" , Quote ( \"Info\" ) , \" instead.\" );\n"
148 <<
"\t\t\tsetLogLevelTo ( Info() );\n"
156 <<
"\tFunction to disable all logging levels\n"
158 <<
"void disableLogging();\n";
159 aCppFile <<
"void disableLogging()\n"
164 aCppFile <<
"\tlog_configuration::mLoggingIncludes" << lLevel <<
" = false;\n";
173 <<
"\tFunction to retrieve the mutex lock used by the logger\n"
175 <<
"std::mutex& GetLoggingMutex();\n";
176 aCppFile <<
"std::mutex& GetLoggingMutex()\n"
178 <<
"\treturn log_configuration::mMutex;\n"
184 std::stringstream lIfDefs, lIfDefs2, lEndIfs;
186 for ( std::vector< std::string >::const_iterator lIt =
gLogLevels.begin() ; lIt !=
gLogLevels.end() ; ++lIt )
188 lIfDefs <<
"\t#ifndef LOGGING_EXCLUDE_" << boost::to_upper_copy ( *lIt ) <<
"\n";
189 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"
190 <<
"\t\tlog_configuration::mLoggingIncludes" << *lIt <<
" = true;\n";
191 lEndIfs <<
"\t#endif\n";
202 <<
"\tFunction to specify, at runtime, that only messages with a severity level above " << *lIt <<
" should be logged\n"
204 <<
"void setLogLevelTo ( const " << *lIt <<
"Level& /**< a dummy parameter to choose the specialization of the function for the " << *lIt <<
" level */ );\n";
205 aCppFile <<
"void setLogLevelTo ( const " << *lIt <<
"Level& )\n"
209 for ( std::vector< std::string >::const_iterator lIt2 = lIt+1 ; lIt2 !=
gLogLevels.end() ; ++lIt2 )
211 aCppFile <<
"\t\tlog_configuration::mLoggingIncludes" << *lIt2 <<
" = false;\n";
214 aCppFile << lEndIfs.str()
218 <<
"\tFunction to check at runtime whether the level " << *lIt <<
" is to be included in the log output\n"
219 <<
"\t@return whether the level " << *lIt <<
" is to be included in the log output\n"
221 <<
"const bool& LoggingIncludes ( const " << *lIt <<
"Level& /**< a dummy parameter to choose the specialization of the function for the " << *lIt <<
" level */ );\n"
223 aCppFile <<
"const bool& LoggingIncludes ( const " << *lIt <<
"Level& )\n"
226 <<
"\t\treturn log_configuration::mLoggingIncludes" << *lIt <<
";\n"
228 <<
"\treturn log_configuration::mFalse;\n"
233 aHppFile <<
"//! Class to restrict access to the log configuration parameters\n"
234 <<
"class log_configuration\n"
236 <<
"\t//! Constructor\n"
237 <<
"\tlog_configuration();\n"
238 <<
"\t//! Destructor\n"
239 <<
"\tvirtual ~log_configuration();\n"
241 <<
"\tfriend void disableLogging();\n"
243 bool lIncludeLevelByDefault (
true );
247 aHppFile <<
"\t//! static bool storing whether the " << lLevel <<
" level is to be included in the log output\n"
248 <<
"\tstatic bool mLoggingIncludes" << lLevel <<
";\n";
250 if ( lIncludeLevelByDefault )
252 aCppFile <<
"bool log_configuration::mLoggingIncludes" << lLevel <<
" = true; // No #ifdefs required here since they are implemented in all the access functions.\n";
256 aCppFile <<
"bool log_configuration::mLoggingIncludes" << lLevel <<
" = false; // No #ifdefs required here since they are implemented in all the access functions.\n";
261 lIncludeLevelByDefault =
false;
264 aHppFile <<
"\t//!Make setLogLevelTo function a friend so it can access our private members\n"
265 <<
"\tfriend void setLogLevelTo ( const " << lLevel <<
"Level& );\n"
266 <<
"\t//!Make LoggingIncludes function a friend so it can access our private members\n"
267 <<
"\tfriend const bool& LoggingIncludes ( const " << lLevel <<
"Level& );\n"
271 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"
272 <<
"\tstatic const bool mTrue;\n"
273 <<
"\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"
274 <<
"\tstatic const bool mFalse;\n"
276 <<
"\t//!Make GetLoggingMutex function a friend so it can access our private members\n"
277 <<
"\tfriend std::mutex& GetLoggingMutex();\n"
278 <<
"\t//!Define a static Mutex lock for thread safe logging\n"
279 <<
"\tstatic std::mutex mMutex;\n"
283 <<
"const bool log_configuration::mTrue = true;\n"
284 <<
"const bool log_configuration::mFalse = false;\n"
286 <<
"std::mutex log_configuration::mMutex;\n"
299 if ( i > 10 && i < 20 )
304 std::string lIndices[] = {
"th" ,
"st" ,
"nd" ,
"rd" ,
"th" ,
"th" ,
"th" ,
"th" ,
"th" ,
"th" };
305 return lIndices[ i%10 ];
309void log_functions ( std::ofstream& aHppFile , std::ofstream& aHxxFile , std::ofstream& aCppFile )
311 std::stringstream lIfDefs , lEndIfs;
315 lIfDefs <<
"\t#ifndef LOGGING_EXCLUDE_" << boost::to_upper_copy ( lLevel ) <<
"\n";
316 lEndIfs <<
"\t#endif\n";
317 std::stringstream lTemplates;
318 std::stringstream lArgs;
319 std::stringstream lInstructions;
320 std::stringstream lDoxygen;
321 lDoxygen <<
"\t\tFunction to add a log entry at " << lLevel <<
" level\n"
322 <<
"\t\t@param a" << lLevel <<
" a dummy parameter to choose the specialization of the function for the " << lLevel <<
" level\n";
324 for ( uint32_t i = 0 ; i!=MAX_NUM_ARGS ; ++i )
326 lTemplates <<
" typename T" << i <<
" ,";
327 std::string lTemplatesStr ( lTemplates.str() );
328 lTemplatesStr.resize ( lTemplatesStr.size()-1 );
329 lArgs <<
" const T" << i <<
"& aArg" << i <<
" ,";
330 std::string lArgsStr ( lArgs.str() );
331 lArgsStr.resize ( lArgsStr.size()-1 );
332 lInstructions <<
"\t\t\tinsert( lStr , aArg" << i <<
" );\n";
333 lDoxygen <<
"\t\t@param aArg" << i <<
" a templated argument to be added to the log " << ( i+1 ) <<
suffix ( i+1 ) <<
"\n";
334 aHppFile <<
"\t/**\n"
337 <<
"\ttemplate<" << lTemplatesStr <<
">\n"
339 <<
"\tvoid log ( " <<lLevel <<
"Level& a" << lLevel <<
" ," << lArgsStr <<
");\n"
341 aHxxFile <<
"template<" << lTemplatesStr <<
">\n"
343 <<
"void log ( " <<lLevel <<
"Level& a" << lLevel <<
" ," << lArgsStr <<
" )\n"
346 <<
"\t\tif( LoggingIncludes( a" << lLevel <<
" ) ){\n"
347 <<
"\t\t\tstd::lock_guard<std::mutex> lLock ( GetLoggingMutex() );\n"
348 <<
"\t\t\tstd::ostream& lStr( a" << lLevel <<
".stream() );\n"
349 <<
"\t\t\ta" << lLevel <<
".head();\n"
350 << lInstructions.str()
351 <<
"\t\t\ta" << lLevel <<
".tail();\n"
365 std::stringstream lTemplates;
366 std::stringstream lArgs;
367 std::stringstream lInstructions;
368 std::stringstream lDoxygen;
370 for ( uint32_t i = 0 ; i!=MAX_NUM_ARGS ; ++i )
372 lTemplates <<
" typename T" << i <<
" ,";
373 std::string lTemplatesStr ( lTemplates.str() );
374 lTemplatesStr.resize ( lTemplatesStr.size()-1 );
375 lArgs <<
" const T" << i <<
"& aArg" << i <<
" ,";
376 std::string lArgsStr ( lArgs.str() );
377 lArgsStr.resize ( lArgsStr.size()-1 );
378 lInstructions <<
"\t\t\tinsert( lStr , aArg" << i <<
" );\n";
379 lDoxygen <<
"\t\t@param aArg" << i <<
" a templated argument to be added to the log " << ( i+1 ) <<
suffix ( i+1 ) <<
"\n";
380 aHppFile <<
"\t/**\n"
383 <<
"\ttemplate<" << lTemplatesStr <<
">\n"
385 <<
"\tvoid log ( exception::exception& aExc ," << lArgsStr <<
");\n"
387 aHxxFile <<
"template<" << lTemplatesStr <<
">\n"
389 <<
"void log ( exception::exception& aExc ," << lArgsStr <<
" )\n"
391 <<
"\t\t\tstd::stringstream lStr;\n"
393 <<
"\t\t\tstd::lock_guard<std::mutex> lLock ( GetLoggingMutex() );\n"
394 << lInstructions.str()
395 <<
"\t\t\taExc.append( ( lStr.str() + \"\\n\" ).c_str() );\n"
397 <<
"\t\t\tlog ( Error() , lStr.str() );\n"
410void fileFooters ( std::ofstream& aHppFile , std::ofstream& aHxxFile , std::ofstream& aCppFile )
413 <<
"#include \"uhal/log/log.hxx\"\n"
423int main (
int argc ,
char* argv[] )
427 std::ofstream lHppFile (
"include/uhal/log/log.hpp" );
429 if ( !lHppFile.is_open() )
431 std::cout <<
"Unable to open HPP file" << std::endl;
435 std::ofstream lHxxFile (
"include/uhal/log/log.hxx" );
437 if ( !lHxxFile.is_open() )
439 std::cout <<
"Unable to open HXX file" << std::endl;
443 std::ofstream lCppFile (
"src/common/log.cpp" );
445 if ( !lCppFile.is_open() )
447 std::cout <<
"Unable to open CPP file" << std::endl;
459 catch (
const std::exception& aExc )
461 std::cerr <<
"ERROR: Caught exception : " << aExc.what() << std::endl;
int main(int argc, char *argv[])
std::string gDivider("// "+std::string(150,'=')+"\n"+"// WARNING! This file is automatically generated! Do not modify it! Any changes will be overwritten!\n"+"// "+std::string(150,'=')+"\n")
void fileHeaders(std::ofstream &aHppFile, std::ofstream &aHxxFile, std::ofstream &aCppFile)
void fileFooters(std::ofstream &aHppFile, std::ofstream &aHxxFile, std::ofstream &aCppFile)
static const std::string gDefaultLevel("Info")
void log_configuration_functions(std::ofstream &aHppFile, std::ofstream &aHxxFile, std::ofstream &aCppFile)
static const std::vector< std::string > gLogLevels(gLogLevelsChar, gLogLevelsChar+gNumberEntries)
std::string suffix(uint32_t i)
static const uint32_t gNumberEntries(6)
static const std::string gLogLevelsChar[]
void log_functions(std::ofstream &aHppFile, std::ofstream &aHxxFile, std::ofstream &aCppFile)