The current incarnation supports rudimentary logging thresholds based on message types and supports macro interfaces. Any constructive criticism and suggestions is welcome.
Download zip of source, or check it out below.
app_log.h
#ifndef APP_LOG_H#define APP_LOG_H/******************************************************************************* LOG INTERFACE OBJECT ** Written by: Jonathan Bender ** Last update: December 11, 2006 ** ** Usage: This is the interface object for logging objects. You can ** implement custom logging objects on top of this interface to ** provide a common interface for you projects to plug in different ** types of logging systems. ** ** Disclaimer: This code is free for use in personal projects for ** learning purposes. This code is not intended for ** commercial use and is not final nor free of bugs. This code ** is provided as is and maintains no warranty. If you have any ** questions, contact Daishim @ GameDev.net. *******************************************************************************/#include // STL stringsusing std::string;// Functionality#define LOG_ERRORS 1#define LOG_WARNINGS 1#define LOG_TRACES 1#define LOG_INFOS 1#define LOG_DEBUGS 1//// Type def UInt if not already#ifndef UINT_DEFtypedef unsigned int UInt;#endif//// Log pointer alias#define LOG_ALIAS Logger//// Log objectclass App_Log; // Class definition is comingextern App_Log *LOG_ALIAS; // Pointer to log is external//// Macro functions for quicker use#ifdef LOG_ERRORS#define LOG_ERROR(Message) LOG_ALIAS->Insert(GLMT_ERROR, __FUNCTION__, Message)#else#define LOG_ERROR(Message)#endif#ifdef LOG_WARNINGS#define LOG_WARNING(Message) LOG_ALIAS->Insert(GLMT_WARNING, __FUNCTION__, Message)#else#define LOG_WARNING(Message)#endif#ifdef LOG_TRACES#define LOG_TRACE(Message) LOG_ALIAS->Insert(GLMT_TRACE, __FUNCTION__, Message)#else#define LOG_TRACE(Message)#endif#ifdef LOG_INFOS#define LOG_INFO(Message) LOG_ALIAS->Insert(GLMT_INFO, __FUNCTION__, Message)#else#define LOG_INFO(Message)#endif#ifdef LOG_DEBUGS#define LOG_DEBUG(Message) LOG_ALIAS->Insert(GLMT_DEBUG, __FUNCTION__, Message)#else#define LOG_DEBUG(Message)#endif#define LOG_INIT(File) LOG_ALIAS->Initialize(File)///*#define Log(Type, Message) LOG_ALIAS->Insert(Type, __FUNCTION__, Message)#define LogNO(Type, Message) LOG_ALIAS->Insert(Type, Message)#define LogV(Type, Message, Value) LOG_ALIAS->InsertV(Type, __FUNCTION__, Message, Value)#define LogVNO(Type, Message, Value) LOG_ALIAS->InsertV(Type, Message, Value)*///// Log message typesenum App_Log_Type {GLMT_REGULAR, GLMT_TRACE, GLMT_ATTEMPT, GLMT_SUCCESS, GLMT_ERROR, GLMT_WARNING, GLMT_INFO, GLMT_DEBUG};//// Log interface objectclass App_Log{ protected: App_Log(void) { /* Empty */ } // Constructor ~App_Log(void) { /* Empty */ } // Destructor public: // External initialization/shutdown methods virtual bool Initialize(const string &Filename) = 0; // Open the log file virtual void Close(void) = 0; // Close the log file // // External insertion methods virtual void Insert(string &Text) = 0; // Insert line of text into log virtual void Insert(const char *Text) = 0; // Insert line of text into log virtual void Insert(App_Log_Type Type, string &Text) = 0; // Insert line text of type with origin virtual void Insert(App_Log_Type Type, const char *Text) = 0; // Insert line text of type with origin virtual void Insert(App_Log_Type Type, string &Origin, string &Text) = 0; // Insert line of text into log with origin virtual void Insert(App_Log_Type Type, const char *Origin, const char *Text) = 0; // Insert line of text into log with origin virtual void InsertV(App_Log_Type Type, string &Text, int Value) = 0; // Insert line of text with signed integer value virtual void InsertV(App_Log_Type Type, const char *Text, int Value) = 0; // Insert line of text with signed integer value virtual void InsertV(App_Log_Type Type, string &Origin, string &Text, int Value) = 0; // Insert line of text with origin and signed integer value virtual void InsertV(App_Log_Type Type, const char *Origin, const char *Text, int Value) = 0; // Insert line of text with origin and signed integer value virtual void InsertV(App_Log_Type Type, string &Text, UInt Value) = 0; // Insert line of text with unsigned integer value virtual void InsertV(App_Log_Type Type, const char *Text, UInt Value) = 0; // Insert line of text with unsigned integer value virtual void InsertV(App_Log_Type Type, string &Origin, string &Text, UInt Value) = 0; // Insert line of text with origin and unsigned integer value virtual void InsertV(App_Log_Type Type, const char *Origin, const char *Text, UInt Value) = 0; // Insert line of text with origin and unsigned integer value virtual void InsertV(App_Log_Type Type, string &Text, string &Value) = 0; // Insert line of text with string value virtual void InsertV(App_Log_Type Type, const char *Text, const char *Value) = 0; // Insert line of text with string value virtual void InsertV(App_Log_Type Type, string &Origin, string &Text, string &Value) = 0; // Insert line of text with origin and string value virtual void InsertV(App_Log_Type Type, const char *Origin, const char *Text, const char *Value) = 0; // Insert line of text with origin and string value //};#endif /* APP_LOG_H */
app_log_rtf.h
#ifndef APP_LOG_RTF_H#define APP_LOG_RTF_H/******************************************************************************* RTF LOG OBJECT ** Written by: Jonathan Bender ** Last update: December 11, 2006 ** ** Usage: This object extends the App_Log object to provide an rich text ** logger. Include the source and header, along with the interface ** header, in your project. You may then use this log object with ** the macros in the interface object header. ** ** Desctription: This log was designed for functionality and formatted ** output text, not speed. For a faster logging system, use a ** plain text logger (not included yet). ** ** Disclaimer: This code is free for use in personal projects for ** learning purposes. This code is not intended for ** commercial use and is not final nor free of bugs. This code ** is provided as is and maintains no warranty. If you have any ** questions, contact Daishim @ GameDev.net. *******************************************************************************/#include // STL file streams#include "app_log.h" // Log interaceusing std::ofstream;class App_Log_RTF : public App_Log{ private: // Log data string m_Filename; // Log filename ofstream *m_File; // File stream of log file // // File output methods void Write_To_Log(const string &Text); // Commit a string of text to the log file void Write_Header(void); // Write the RTF file header // // Internal insertion methods void Insert_Value(string &Text, int Value); // Insert signed integer value into string void Insert_Value(string &Text, UInt Value); // Insert unsigned integer value into string void Insert_Value(string &Text, string &Value); // Insert string value into string // // Formatting methods void Swap_Tags(string &Text, const string &Clean_Tag, const string &RTF_Tag); // Swaps clean tags for RTF tags void Format(string &Text); // Formatting instructions // public: App_Log_RTF(void); // Constructor ~App_Log_RTF(void); // Destructor // External initialization/shutdown methods bool Initialize(const string &Filename = "log.rtf"); // Open the log file void Close(void); // Close the log file // // External insertion methods void Insert(string &Text); // Insert line of text into log void Insert(const char *Text); // Insert line of text into log void Insert(App_Log_Type Type, string &Text); // Insert line text of type with origin void Insert(App_Log_Type Type, const char *Text); // Insert line text of type with origin void Insert(App_Log_Type Type, string &Origin, string &Text); // Insert line of text into log with origin void Insert(App_Log_Type Type, const char *Origin, const char *Text); // Insert line of text into log with origin void InsertV(App_Log_Type Type, string &Text, int Value); // Insert line of text with signed integer value void InsertV(App_Log_Type Type, const char *Text, int Value); // Insert line of text with signed integer value void InsertV(App_Log_Type Type, string &Origin, string &Text, int Value); // Insert line of text with origin and signed integer value void InsertV(App_Log_Type Type, const char *Origin, const char *Text, int Value); // Insert line of text with origin and signed integer value void InsertV(App_Log_Type Type, string &Text, UInt Value); // Insert line of text with unsigned integer value void InsertV(App_Log_Type Type, const char *Text, UInt Value); // Insert line of text with unsigned integer value void InsertV(App_Log_Type Type, string &Origin, string &Text, UInt Value); // Insert line of text with origin and unsigned integer value void InsertV(App_Log_Type Type, const char *Origin, const char *Text, UInt Value); // Insert line of text with origin and unsigned integer value void InsertV(App_Log_Type Type, string &Text, string &Value); // Insert line of text with string value void InsertV(App_Log_Type Type, const char *Text, const char *Value); // Insert line of text with string value void InsertV(App_Log_Type Type, string &Origin, string &Text, string &Value); // Insert line of text with origin and string value void InsertV(App_Log_Type Type, const char *Origin, const char *Text, const char *Value); // Insert line of text with origin and string value //};#endif /* APP_LOG_RTF_H */
app_log_rtf.cpp
/******************************************************************************* RTF LOG OBJECT ** Written by: Jonathan Bender ** Last update: December 11, 2006 ** ** Usage: This object extends the App_Log object to provide an rich text ** logger. Include the source and header, along with the interface ** header, in your project. You may then use this log object with ** the macros in the interface object header. ** ** Desctription: This log was designed for functionality and formatted ** output text, not speed. For a faster logging system, use a ** plain text logger (not included yet). ** ** Disclaimer: This code is free for use in personal projects for ** learning purposes. This code is not intended for ** commercial use and is not final nor free of bugs. This code ** is provided as is and maintains no warranty. If you have any ** questions, contact Daishim @ GameDev.net. *******************************************************************************/#include // STL file streams#include // STL strings#include // STL string streams#include "app_log_rtf.h" // App log objectusing std::string;using std::ofstream;using std::stringstream;// Log objectApp_Log_RTF RTF_Log;App_Log *Logger = reinterpret_cast(&RTF_Log);//// Constructor, set log file andApp_Log_RTF::App_Log_RTF(void){ // Initialize all members to NULL/0 m_File = NULL;}// DestructorApp_Log_RTF::~App_Log_RTF(void){ // If log is open if(m_File) Close(); // Close it}/////////////////////////// File output methods ///////////////////////////// Commit a string of text to the log filevoid App_Log_RTF::Write_To_Log(const string &Text){ // Write text to file m_File->write(Text.c_str(), (std::streamsize) Text.length()); m_File->flush();}// Write the RTF file headervoid App_Log_RTF::Write_Header(void){ // Write RTF header Write_To_Log("{\\rtf1\\ansi\\deff0{\\fonttbl{\\f0 Times New Roman;}}\\fs20\n"); // Write color table Write_To_Log("{\\colortbl;\n"); // Black Write_To_Log("\\red255\\green255\\blue255;\n"); // White Write_To_Log("\\red128\\green128\\blue128;\n"); // Grey Write_To_Log("\\red255\\green0\\blue0;\n"); // Red Write_To_Log("\\red0\\green255\\blue0;\n"); // Green Write_To_Log("\\red0\\green0\\blue255;\n"); // Blue Write_To_Log("\\red0\\green128\\blue0;\n"); // Dark green Write_To_Log("\\red255\\green128\\blue0;\n"); // Orange Write_To_Log("\\red0\\green200\\blue200;\n"); // Blue-green Write_To_Log("}\n"); // Write logging started message Insert("== Start Log ==\n\n"); // Blank line spacer Insert("\n");}////////////////////////////////// Internal insertion methods //////////////////////////////////// Insert signed integer value into stringvoid App_Log_RTF::Insert_Value(string &Text, int Value){ unsigned int Position = 0; string Text_Value; stringstream Stream; Stream << Value; Text_Value = Stream.str(); if((Position = (unsigned int) Text.find("%i", 0)) != string::npos) Text.replace(Position, 2, Stream.str());}// Insert unsigned integer value into stringvoid App_Log_RTF::Insert_Value(string &Text, UInt Value){ unsigned int Position = 0; string Text_Value; stringstream Stream; Stream << Value; Text_Value = Stream.str(); if((Position = (unsigned int) Text.find("%i", 0)) != string::npos) Text.replace(Position, 2, Stream.str());}// Insert string value into stringvoid App_Log_RTF::Insert_Value(string &Text, string &Value){ unsigned int Position = 0; if((Position = (unsigned int) Text.find("%s", 0)) != string::npos) Text.replace(Position, 2, Value.c_str());}////////////////////////// Formatting methods //////////////////////////// Swaps clean tags for RTF tagsvoid App_Log_RTF::Swap_Tags(string &Text, const string &Clean_Tag, const string &RTF_Tag){ unsigned int Position = 0; // Find each occurance of the clean tag while((Position = (unsigned int) Text.find(Clean_Tag, (size_t) Position)) != string::npos) { Text.replace(Position, Clean_Tag.length(), RTF_Tag); // Replace clean tag with RTF tag Position += (unsigned int) (Clean_Tag.length() > RTF_Tag.length() ? Clean_Tag.length() + 1 : RTF_Tag.length()); // Set position to after the clean tag }}// Formatting instructionsvoid App_Log_RTF::Format(string &Text){ // Special formatting Swap_Tags(Text, "\\", "\\\\"); // Convert slash to single slash Swap_Tags(Text, "{", "\\{"); // Convert open brace to RTF open brace Swap_Tags(Text, "}", "\\}"); // Convert close brace to RTF close brace // Text coloring Swap_Tags(Text, "[BLACK]", "\\cf0 "); // Black Swap_Tags(Text, "[WHITE]", "\\cf1 "); // White Swap_Tags(Text, "[GREY]", "\\cf2 "); // Grey Swap_Tags(Text, "[RED]", "\\cf3 "); // Red Swap_Tags(Text, "[GREEN]", "\\cf4 "); // Green Swap_Tags(Text, "[BLUE]", "\\cf5 "); // Blue Swap_Tags(Text, "[DKGREEN]", "\\cf6 "); // Dark green Swap_Tags(Text, "[ORANGE]", "\\cf7 "); // Orange Swap_Tags(Text, "[CYAN]", "\\cf8 "); // Blue-green // Type formatting Swap_Tags(Text, "", "\\b "); // Bold start Swap_Tags(Text, "", "\\b0 "); // Bold end Swap_Tags(Text, "", "\\i "); // Italicized start Swap_Tags(Text, "", "\\i0 "); // Italicized end // Object formatting Swap_Tags(Text, "<", "\\b <"); // Convert object open carrot to bold object open carrot Swap_Tags(Text, ">", ">\\b0 "); // Convert object close carrot to not bold then close carrot // General formatting Text.insert(0, "{\\pard "); // Prepend line starter if(Text[Text.length() - 1] == '\n') { Text.replace(Text.length() - 1, 6, "\\par}\n"); // Append line ender with newline //Text.insert(Text.length(), "\\par}\n"); } else { Text.insert(Text.length(), "}\n"); // Append line ender without newline }}//////////////////////////////////////////////// External initialization/shutdown methods ////////////////////////////////////////////////// Open the log filebool App_Log_RTF::Initialize(const string &Filename){ bool Success = true; m_Filename = Filename; // Copy filename to local container // Attempt to create new file stream m_File = new ofstream(Filename.c_str()); if(!(*m_File)) { // Failed to open file Success = false; // Destroy the file stream delete m_File; m_File = NULL; } else { // Write log file header Write_Header(); } return Success;}// Close the log filevoid App_Log_RTF::Close(void){ // If file is open if(m_File) { Insert("\n"); // Write blank line as spacer Insert("== End Of Log ==\n"); // Write end of log file message Write_To_Log("}"); // Write RTF footer // Close file m_File->close(); // Destroy file stream delete m_File; m_File = NULL; }}////////////////////////////////// External insertion methods //////////////////////////////////// Insert text into logvoid App_Log_RTF::Insert(string &Text){ // If file is open if(m_File) { Format(Text); // Format incoming text RTF style Write_To_Log(Text); // Write text to file }}// Insert text into logvoid App_Log_RTF::Insert(const char *Text){ string SText(Text); // If file is open if(m_File) { Format(SText); // Format incoming text RTF style Write_To_Log(SText); // Write text to file }}// Insert line of text of type into log (newline after text)void App_Log_RTF::Insert(App_Log_Type Type, string &Text){ // If file is open if(m_File) { if(Type == GLMT_TRACE) { Text.insert(0, "[GREY]"); // Trace messages are grey } else if(Type == GLMT_ATTEMPT) { Text.insert(0, "[BLUE]"); // Code attempt messages are blue if(Text[Text.length() - 1] != '\n') Text.insert(Text.length(), ": "); } else if(Type == GLMT_SUCCESS) { Text.insert(0, "[BLUE]"); // Success messages are bolded blue } else if(Type == GLMT_ERROR) { Text.insert(0, "[RED]"); // Error messages are red } else if(Type == GLMT_WARNING) { Text.insert(0, "[ORANGE]"); // Warning messages are orange } else if(Type == GLMT_INFO) { Text.insert(0, "[DKGREEN]"); // Info messages are dark green } else if(Type == GLMT_DEBUG) { Text.insert(0, "[CYAN]"); // Debug messages are blue-green } else { Text.insert(0, "[BLACK]"); // Plain/no type messages are black } Format(Text); // Format incoming text RTF style Write_To_Log(Text); // Write text to file }}// Insert line of text of type into log (newline after text)void App_Log_RTF::Insert(App_Log_Type Type, const char *Text){ string SText(Text); // If file is open if(m_File) { if(Type == GLMT_TRACE) { SText.insert(0, "[GREY]"); // Trace messages are grey } else if(Type == GLMT_ATTEMPT) { SText.insert(0, "[BLUE]"); // Code attempt messages are blue // Attempt message follows with : and then the message if(SText[SText.length() - 1] != '\n') SText.insert(SText.length(), ": "); } else if(Type == GLMT_SUCCESS) { SText.insert(0, "[BLUE]"); // Success messages are bolded blue } else if(Type == GLMT_ERROR) { SText.insert(0, "[RED]"); // Error messages are red } else if(Type == GLMT_WARNING) { SText.insert(0, "[ORANGE]"); // Warning messages are orange } else if(Type == GLMT_INFO) { SText.insert(0, "[DKGREEN]"); // Info messages are dark green } else { SText.insert(0, "[BLACK]"); // Plain/no type messages are black } Format(SText); // Format incoming text RTF style Write_To_Log(SText); // Write text to file }}// Insert line of text into log with originvoid App_Log_RTF::Insert(App_Log_Type Type, string &Origin, string &Text){ Origin.insert(0, "<"); Origin.insert(Origin.length(), "> "); Text.insert(0, Origin); Insert(Type, Text);}// Insert line of text into log with originvoid App_Log_RTF::Insert(App_Log_Type Type, const char *Origin, const char *Text){ string SOrigin(Origin); string SText(Text); SOrigin.insert(0, "<"); SOrigin.insert(SOrigin.length(), "> "); SText.insert(0, SOrigin); Insert(Type, SText);}// Insert line of text with signed integer value void App_Log_RTF::InsertV(App_Log_Type Type, string &Text, int Value){ Insert_Value(Text, Value); Insert(Type, Text);}// Insert line of text with signed integer value void App_Log_RTF::InsertV(App_Log_Type Type, const char *Text, int Value){ string SText(Text); Insert_Value(SText, Value); Insert(Type, SText);}// Insert line of text with origin and signed integer valuevoid App_Log_RTF::InsertV(App_Log_Type Type, string &Origin, string &Text, int Value){ Insert_Value(Text, Value); Insert(Type, Origin, Text);}// Insert line of text with origin and signed integer valuevoid App_Log_RTF::InsertV(App_Log_Type Type, const char *Origin, const char *Text, int Value){ string SOrigin(Origin); string SText(Text); Insert_Value(SText, Value); Insert(Type, SOrigin, SText);}// Insert line of text with unsigned integer valuevoid App_Log_RTF::InsertV(App_Log_Type Type, string &Text, UInt Value){ Insert_Value(Text, Value); Insert(Type, Text);}// Insert line of text with unsigned integer valuevoid App_Log_RTF::InsertV(App_Log_Type Type, const char *Text, UInt Value){ string SText(Text); Insert_Value(SText, Value); Insert(Type, SText);}// Insert line of text with origin and unsigned integer valuevoid App_Log_RTF::InsertV(App_Log_Type Type, string &Origin, string &Text, UInt Value){ Insert_Value(Text, Value); Insert(Type, Origin, Text);}// Insert line of text with origin and unsigned integer valuevoid App_Log_RTF::InsertV(App_Log_Type Type, const char *Origin, const char *Text, UInt Value){ string SOrigin(Origin); string SText(Text); Insert_Value(SText, Value); Insert(Type, SOrigin, SText);}// Insert line of text with string valuevoid App_Log_RTF::InsertV(App_Log_Type Type, string &Text, string &Value){ Insert_Value(Text, Value); //Format(Text); Insert(Type, Text);}// Insert line of text with string valuevoid App_Log_RTF::InsertV(App_Log_Type Type, const char *Text, const char *Value){ string SText(Text); string SValue(Value); Insert_Value(SText, SValue); //Format(Text); Insert(Type, SText);}// Insert line of text with origin and string valuevoid App_Log_RTF::InsertV(App_Log_Type Type, string &Origin, string &Text, string &Value){ Insert_Value(Text, Value); //Format(Text); Insert(Type, Origin, Text);}// Insert line of text with origin and string valuevoid App_Log_RTF::InsertV(App_Log_Type Type, const char *Origin, const char *Text, const char *Value){ string SOrigin(Origin); string SText(Text); string SValue(Value); Insert_Value(SText, SValue); //Format(Text); Insert(Type, SOrigin, SText);}