lowlevellibsandfws/pluginfw/Test_Bed/test_bed/DataLogger.cpp
changeset 0 e4d67989cc36
child 44 97b0fb8a2cc2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lowlevellibsandfws/pluginfw/Test_Bed/test_bed/DataLogger.cpp	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,527 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <e32def.h>
+#include <f32file.h>
+
+#include <ecom/test_bed/datalogger.h>
+
+// KLogBufferSize is the maximum line length allowed by flogger
+const TInt KMaxTBLogEntrySize = KLogBufferSize;
+
+// Common string literals for all output formats
+_LIT(KTimeFormatStr,"%J%:1%T%:2%S%.%*C3");
+// Above string will give time in format HH:MM:SS.SSS therefore max length = 12
+const TInt KTimeBufLength = 12;
+
+// Define some string literals for HTML formatting
+_LIT(KHTMLDocumentStart,"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"><HTML><HEAD><META NAME=\"robots\" CONTENT=\"noindex\"><META NAME=\"author\" CONTENT=\"Symbian RTestBed log generator\"><TITLE>");
+// Insert title string here
+_LIT(KHTMLContentStart,"</TITLE></HEAD><BODY><P><FONT=3>");
+// Insert time string here
+_LIT(KHTMLCommentStart,"<P>");
+// Insert content here
+_LIT(KHTMLCommentEnd,"</P>");
+_LIT(KHTMLDocumentEnd,"</FONT></P></BODY></HTML>");
+
+//___________________________________________________________________________
+// Define the overflow handling classes for any log formatting methods
+// Simply record the overflow...
+//
+
+NONSHARABLE_CLASS(TLogMessageOverflow) : public TDes16Overflow
+	{
+	public:
+	
+		TLogMessageOverflow();
+	
+		void Overflow(TDes16&);	
+	
+		TInt iError;
+	};
+
+TLogMessageOverflow::TLogMessageOverflow()
+: TDes16Overflow(),
+iError(KErrNone)
+	{
+	}
+
+void TLogMessageOverflow::Overflow(TDes16&)
+	{
+	__DEBUGGER();
+	iError = KErrOverflow;
+	}
+
+
+NONSHARABLE_CLASS(TLogMessageOverflow8) : public TDes8Overflow
+	{
+	public:
+	
+		TLogMessageOverflow8();
+	
+		void Overflow(TDes8&);	
+	
+		TInt iError;
+	};
+
+TLogMessageOverflow8::TLogMessageOverflow8()
+: TDes8Overflow(),
+iError(KErrNone)
+	{
+	}
+
+void TLogMessageOverflow8::Overflow(TDes8&)
+	{
+	__DEBUGGER();
+	iError = KErrOverflow;
+	}
+
+//___________________________________________________________________________
+
+//___________________________________________________________________________
+
+CDataLogger::~CDataLogger()
+	{
+	if(iLogOutput != NULL)
+		{
+		if(iLogStyle != EText && iLogFormat.iDocumentEnd)
+			Log(iLogOutput, *(iLogFormat.iDocumentEnd));
+		iLogOutput->Close();
+		}
+
+	if(iReportOutput != NULL)
+		{
+		if(iLogStyle != EText && iLogFormat.iDocumentEnd)
+			Log(iReportOutput, *(iLogFormat.iDocumentEnd));
+		iReportOutput->Close();
+		}
+
+	delete iFormatBuf;
+	delete iDebug;
+	delete iDefaultLogOutput;
+	delete iDefaultReportOutput;
+	}
+
+
+CDataLogger::CDataLogger()
+	{
+	}
+
+CDataLogger* CDataLogger::NewLC(TLoggingInfo* aLogInfo)
+	{
+	CDataLogger* self = new (ELeave) CDataLogger();
+	CleanupStack::PushL(self);
+	self->ConstructL(aLogInfo);
+	return self;
+	}
+
+CDataLogger* CDataLogger::NewL(TLoggingInfo* aLogInfo)
+	{
+	CDataLogger* self = NewLC(aLogInfo);
+	CleanupStack::Pop();
+	return self;
+	}
+
+
+void CDataLogger::ConstructL(TLoggingInfo* aLogInfo)
+	{
+	iFormatBuf = HBufC::NewL(KMaxTBLogEntrySize);
+
+	SetupLoggingL(aLogInfo);
+
+	iLogOutput->OpenL();
+	iReportOutput->OpenL();
+
+	// Record additional information : Time
+	TTime time;
+	time.UniversalTime();
+	TBuf<KTimeBufLength> timeBuf;
+	time.FormatL(timeBuf,KTimeFormatStr);
+	if(iLogStyle != EText)
+		{
+		// Use the log format
+		Log(iLogOutput, *(iLogFormat.iDocumentStart));
+		if(aLogInfo->iTitle)
+			Log(iLogOutput, *(aLogInfo->iTitle));
+		Log(iLogOutput, *(iLogFormat.iContentStart));
+		Log(iLogOutput, timeBuf);
+
+		Log(iReportOutput, *(iLogFormat.iDocumentStart));
+		if(aLogInfo->iTitle)
+			Log(iReportOutput, *(aLogInfo->iTitle));
+		Log(iReportOutput, *(iLogFormat.iContentStart));
+		Log(iReportOutput, timeBuf);
+		}
+	else
+		{
+		if(aLogInfo && aLogInfo->iTitle)
+			{
+			Log(iLogOutput, *(aLogInfo->iTitle));
+			Log(iReportOutput, *(aLogInfo->iTitle));
+			}
+		Log(iLogOutput, timeBuf);
+		Log(iReportOutput, timeBuf);
+		}
+	}
+
+
+EXPORT_C void CDataLogger::DumpMemoryBlock(const TUint8* aAddress, TInt aLength)
+	{
+	const TInt KBytesPerRow = 16;
+	const TInt KLowestAsciiPrint = 32;
+	const TInt KHighestAsciiPrint = 127;
+
+	// The required descriptors for outputting the data
+	_LIT(KDumpLineStart, "%04x : ");
+	_LIT(KDumpHexOutput, "%02x ");
+	_LIT(KDumpHexBlank, "   ");
+	_LIT(KDumpHexEnd, ": ");
+	_LIT(KDumpCharOutput, "%c");
+	_LIT(KDumpCharUnknown, ".");
+	_LIT(KDumpCharBlank, " ");
+
+	TPtrC8 theData(aAddress, aLength);
+
+	// Iterate the supplied block of data in blocks of 16 bytes
+	TInt pos = 0;
+	TBuf<KMaxTBLogEntrySize> logLine;
+	TBuf<KMaxTBLogEntrySize> anEntry;
+	while (pos < theData.Length())
+		{
+		TInt offset = 0;
+
+		anEntry.Format(KDumpLineStart, pos);
+		logLine.Append(anEntry);
+
+		// Hex output
+		for (offset = 0; offset < KBytesPerRow; ++offset)
+			{
+			if (pos + offset < theData.Length())
+				{
+				TInt nextByte = theData[pos + offset];
+				anEntry.Format(KDumpHexOutput, nextByte);
+				logLine.Append(anEntry);
+				}
+			else
+				{
+				anEntry.Format(KDumpHexBlank);
+				logLine.Append(anEntry);
+				}
+			}
+			anEntry.Format(KDumpHexEnd);
+			logLine.Append(anEntry);
+
+		// Char output
+		for (offset = 0; offset < KBytesPerRow; ++offset)
+			{
+			if (pos + offset < theData.Length())
+				{
+				TInt nextByte = theData[pos + offset];
+				if ((nextByte >= KLowestAsciiPrint) && (nextByte <= KHighestAsciiPrint))
+					{
+					anEntry.Format(KDumpCharOutput, nextByte);
+					logLine.Append(anEntry);
+					}
+				else
+					{
+					anEntry.Format(KDumpCharUnknown);
+					logLine.Append(anEntry);
+					}
+				}
+			else
+				{
+				anEntry.Format(KDumpCharBlank);
+				logLine.Append(anEntry);
+				}
+			}
+
+		//Log this line to the file
+		if(iLogStyle != EText)
+			{
+			Log(iLogOutput, *(iLogFormat.iCommentStart));
+			Log(iLogOutput, logLine);
+			Log(iLogOutput, *(iLogFormat.iCommentEnd));
+			}
+		else
+			Log(iLogOutput, logLine);
+
+		logLine.Zero();
+
+		// Advance to next segment of size 'KBytesPerRow'
+		pos += KBytesPerRow;
+		}
+
+	}
+
+
+EXPORT_C void CDataLogger::LogInformation(const TDesC16& aComment)
+	{
+	if(iLogStyle != EText)
+		{
+		Log(iLogOutput, *(iLogFormat.iCommentStart));
+		Log(iLogOutput, aComment);
+		Log(iLogOutput, *(iLogFormat.iCommentEnd));
+		}
+	else
+		Log(iLogOutput, aComment);
+	iDebug->Print(aComment);
+	}
+
+EXPORT_C void CDataLogger::LogInformation(const TDesC8& aComment)
+	{
+	// Create a wide descriptor to copy aComment into
+	HBufC* message = HBufC::NewMax(aComment.Length());
+
+	// If the allocation failed then do nothing
+	if(message != NULL)
+		{
+		TPtr message16 = message->Des();
+
+		message16.Copy(aComment);
+		LogInformation(message16);
+		delete message;
+		}
+	}
+
+EXPORT_C void CDataLogger::LogInformationWithParameters(TRefByValue<const TDesC16> aFormat, ...)
+	{
+	// Prepare the message
+	// coverity [var_decl]
+       // VA_LIST is initialized in VA_START
+	VA_LIST list;
+	VA_START(list,aFormat);
+	
+	TPtr message = iFormatBuf->Des();
+
+	// Catch the overflow if formatting
+	TLogMessageOverflow overflowHandler;
+	message.AppendFormatList(aFormat,list,&overflowHandler);
+	VA_END(list);
+	if(overflowHandler.iError == KErrNone)
+		{
+		// Ok formatted correctly so...
+		// Wrap the logging level as the first parameter
+		if(iLogStyle != EText)
+			{
+			Log(iLogOutput, *(iLogFormat.iCommentStart));
+			Log(iLogOutput, message);
+			Log(iLogOutput, *(iLogFormat.iCommentEnd));
+			}
+		else
+			Log(iLogOutput, message);
+		iDebug->Print(message);
+		}
+
+	// Clear the message buffer
+	message.Zero();
+	}
+
+EXPORT_C void CDataLogger::LogInformationWithParameters(TRefByValue<const TDesC8> aFormat, ...)
+	{
+	// Create an 8 bit descriptor to copy aFormat into
+	HBufC8* message8 = HBufC8::New(KMaxTBLogEntrySize);
+	if(message8)
+		{
+		// Prepare the message
+		// coverity [var_decl]
+	       // VA_LIST is initialized in VA_START
+		VA_LIST list;
+		VA_START(list,aFormat);
+		TPtr8 messagePtr8 = message8->Des();
+
+		// Catch the overflow if formatting
+		TLogMessageOverflow8 overflowHandler;
+		messagePtr8.AppendFormatList(aFormat,list,&overflowHandler);
+		VA_END(list);
+		if(overflowHandler.iError == KErrNone)
+			{
+			TPtr message = iFormatBuf->Des();
+			// Copy over the fromatted message into the 16 bit descriptor
+			message.Copy(messagePtr8);
+
+			// Ok formatted correctly so...
+			// Wrap the logging level as the first parameter
+			if(iLogStyle != EText)
+				{
+				Log(iLogOutput, *(iLogFormat.iCommentStart));
+				Log(iLogOutput, message);
+				Log(iLogOutput, *(iLogFormat.iCommentEnd));
+				}
+			else
+				Log(iLogOutput, message);
+			iDebug->Print(message);
+
+			// Clear the message buffer
+			message.Zero();
+			}
+		delete message8;
+		}
+	}
+
+EXPORT_C void CDataLogger::ReportInformation(const TDesC& aComment)
+	{
+	if(iLogStyle != EText)
+		{
+		Log(iReportOutput, *(iLogFormat.iCommentStart));
+		Log(iReportOutput, aComment);
+		Log(iReportOutput, *(iLogFormat.iCommentEnd));
+		}
+	else
+		Log(iReportOutput, aComment);
+	}
+
+EXPORT_C void CDataLogger::ReportInformationWithParameters(TRefByValue<const TDesC> aFormat, ...)
+	{
+	// Prepare the message
+	// coverity [var_decl]
+       // VA_LIST is initialized in VA_START
+	VA_LIST list;
+	VA_START(list,aFormat);
+	
+	TPtr message = iFormatBuf->Des();
+
+	// Catch the overflow if formatting
+	TLogMessageOverflow overflowHandler;
+	message.AppendFormatList(aFormat,list,&overflowHandler);
+	VA_END(list);
+	if(overflowHandler.iError == KErrNone)
+		{
+		// Ok formatted correctly so...
+		// Wrap the logging level as the first parameter
+		if(iLogStyle != EText)
+			{
+			Log(iReportOutput, *(iLogFormat.iCommentStart));
+			Log(iReportOutput, message);
+			Log(iReportOutput, *(iLogFormat.iCommentEnd));
+			}
+		else
+			Log(iReportOutput, message);
+		}
+
+	// Clear the message buffer
+	message.Zero();
+	}
+
+
+void CDataLogger::SetupRDebugL(TBool aRequest) 
+	{
+	delete iDebug; 
+	if(aRequest) 
+		iDebug = new(ELeave) TDebugPrint;		// Print to RDebug
+	else 
+		iDebug = new(ELeave) TNullDebugPrint;	// Ignore prints
+	}
+
+void CDataLogger::TDebugPrint::Print(const TDesC& aMessage) 
+	{
+	_LIT(KRDebugFormatStr,"%S");
+	RDebug::Print(KRDebugFormatStr, &aMessage);
+	}
+
+void CDataLogger::Log(MLogOutput* aLogOutput, const TDesC16& aMessage)
+	{
+	// If the message is short enough then log it in one go
+	if(aMessage.Length() < KMaxTBLogEntrySize)
+		aLogOutput->Write(aMessage);
+	else
+		{
+		// Start at the beginning and log out short blocks until finished
+		TInt outIndex = 0;
+		while(outIndex < aMessage.Length())
+			{
+			if((outIndex+KMaxTBLogEntrySize) > aMessage.Length())
+				{
+				aLogOutput->Write(aMessage.Right(aMessage.Length() - outIndex));
+				outIndex = aMessage.Length();
+				}
+			else
+				{
+				// The -1 is required to ensure that the submessage is not too long
+				TPtrC subMessage = aMessage.Mid(outIndex, KMaxTBLogEntrySize - 1);
+				// Find the space nearest the end for a convenient break point
+				TInt spaceLoc = subMessage.LocateReverse(TChar(' '));
+				if(spaceLoc != KErrNotFound)
+					outIndex = spaceLoc;
+				else
+					outIndex = KMaxTBLogEntrySize - 1;
+				aLogOutput->Write(subMessage.Left(++outIndex));
+				}
+			}
+		}
+	}
+
+void CDataLogger::SetupLoggingL(TLoggingInfo* aLogInfo)
+	{
+	// The possible log filenames
+	_LIT(KTestBedLogName, "RTestBed.log");
+	_LIT(KTestBedHtmlLogName, "TestBedLog.html");
+	// The possible report file names
+	_LIT(KTestBedReportName, "RTestBed.rep");
+	_LIT(KTestBedHtmlReportName, "TestBedReport.html");
+
+	if(aLogInfo)
+		{
+		iLogStyle = aLogInfo->iStyle;
+		
+		if(aLogInfo->iLogOutput)
+			iLogOutput = aLogInfo->iLogOutput;
+		else
+			{
+			if(iLogStyle==EHtml)
+				iDefaultLogOutput = new(ELeave) CDefaultLogOutput(KTestBedHtmlLogName);
+			else
+				iDefaultLogOutput = new(ELeave) CDefaultLogOutput(KTestBedLogName);
+
+			iLogOutput = iDefaultLogOutput;
+			}
+
+		if(aLogInfo->iReportOutput)
+			iReportOutput = aLogInfo->iReportOutput;
+		else
+			{
+			if(iLogStyle==EHtml)
+				iDefaultReportOutput = new(ELeave) CDefaultLogOutput(KTestBedHtmlReportName);
+			else
+				iDefaultReportOutput = new(ELeave) CDefaultLogOutput(KTestBedReportName);
+
+			iReportOutput = iDefaultReportOutput;
+			}
+
+		SetupRDebugL(aLogInfo->iUseRDebug);
+		}
+	else
+		{
+		iLogStyle = EText;
+		iDefaultLogOutput = new(ELeave) CDefaultLogOutput(KTestBedLogName);
+		iLogOutput = iDefaultLogOutput;
+		iDefaultReportOutput = new(ELeave) CDefaultLogOutput(KTestBedReportName);
+		iReportOutput = iDefaultReportOutput;
+
+		SetupRDebugL(ETrue);
+		}
+
+	// If the user has specified a custom logging style then use their LogFormat
+	if(iLogStyle == ECustom)
+		iLogFormat = *(aLogInfo->iLogFormat);
+	else if(iLogStyle == EHtml)
+		{
+		// Output as HTML
+		iLogFormat.iDocumentStart	= &(KHTMLDocumentStart());
+		iLogFormat.iContentStart	= &(KHTMLContentStart());
+		iLogFormat.iCommentStart	= &(KHTMLCommentStart());
+		iLogFormat.iCommentEnd		= &(KHTMLCommentEnd());
+		iLogFormat.iDocumentEnd		= &(KHTMLDocumentEnd());
+		}
+	}