RTF Logging

Published December 11, 2006
Advertisement
Based upon the RTF article hosted HERE on GameDev, I have created a simple log interface and RTF logging implementation. I'm experimenting with different types of logging and wanted to keep a unified interface. This interface can be expanded into HTML, XML, or other formats fairly easy.

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);}
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement