#include #include #include #include #include "Debug.h" /** @mainpage C++ stream debugging */ /** @file: Debug.cpp * @brief A simple C++ class for debugging * * @details This class provides a mechanism for adding debugging output * to C++ code using a stream syntax. The user does not use the class directly. * Rather, the macros debug, lDebug(), vDebug() are used. These * expand into use of the class. The macros rely on the preprocessor to * provide meta information (file name, line nmber, function name); In order * for the macro to operate a -DDEBUG must be included when compiling * the code. Otherwise, all debug code may be optimized out. */ /** A global controlling the amount of debug output. It may be * set in the Debug::init() method. A value 0 means * no output. Higher values mean more output. Used in conjunction with * lDebug(). */ int Debug::debugLevel = 0; /** a pointer to the stream used for output. It defaults to * std::cerr. Based on suggestion and code found * here. */ std::ostream* Debug::dbOS = 0; /** The prefix of the debug flag (must be in argv[1] passed to the * init() function. The flag may be optionally followed by a number * (e.g. -debug5 to sets the debugLevel to the value 5. * If not specified, it is set to 1. */ static const char* prefix = "-debug"; /** Initialize the variable Debug::debugLevel depending on the value * of argv[1]. Normally called from main with the program * arguments. If argv[1] is or begins with -debug, the * value of Debug::debugLevel is set and argc, argv are * modified appropriately. An entry of -debug5 sets the level to 5. * If the function is not called, the user is responsible for setting * Debug::debugLevel in other code. * @param argc the number of command line arguments * @param argv the array of command line arguments. */ void Debug::init(int& argc, const char*argv[]) { Debug::dbOS = &std::cerr; if (argc > 1) { const char* arg1 = argv[1]; size_t len = strlen(prefix); if (strncmp(arg1, prefix, len) == 0) { Debug::debugLevel = 1; if (strlen(arg1) > len) Debug::debugLevel = atoi(arg1 + len); argc--; // decrement number of arguments for (int i = 1; i < argc; i++) // remove first argument argv[i] = argv[i+1]; } } } /** Send debugging output to a file. * @param fileName name of file to send output to */ void Debug::toFile (const char* fileName) { Debug::close(); Debug::dbOS = new std::ofstream(fileName); } /** Close the output file if it was set in Debug::toFile() */ void Debug::close(void) { if (Debug::dbOS != &std::cerr) { delete Debug::dbOS; Debug::dbOS = &std::cerr; } } /** Constructor for the Debug class. * It sends the file name, line number and function name to the debug stream. * This is based on code by Alberto Lepe found * * here. An anonymous instance of the class is created and used for the * debugging output and the destructor adds the endl. * @param file name of file (supplied by __FILE__) * @param line line number in file (supplied by __LINE__) * @param func name of method (supplied by __func__) */ Debug::Debug (const char* file, int line, const char* func) { if (! Debug::dbOS) // guarantee initialized, removes need to call init() Debug::dbOS = &std::cerr; (*Debug::dbOS) << "DEBUG " << file << "[" << line << "] " << func << "() "; } /** The destructor automatically sends an endl to the output stream * The constructor created an anonymous instance which is destructed at the end * of the debug statement. */ Debug::~Debug() { (*Debug::dbOS) << std::endl; }