diff -r 000000000000 -r a03f92240627 stif/Logger/src/FileOutput.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stif/Logger/src/FileOutput.cpp Tue Feb 02 01:57:15 2010 +0200
@@ -0,0 +1,1212 @@
+/*
+* Copyright (c) 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: This module contains implementation of CFileOutput
+* class member functions.
+*
+*/
+
+
+// INCLUDE FILES
+#include "FileOutput.h"
+
+// EXTERNAL DATA STRUCTURES
+// None
+
+// EXTERNAL FUNCTION PROTOTYPES
+// None
+
+// CONSTANTS
+// None
+
+// MACROS
+// None
+//#define RDEBUG_FILEWRITECRASH(a) RDebug::Print(a)
+#define RDEBUG_FILEWRITECRASH(a)
+
+// LOCAL CONSTANTS AND MACROS
+// None
+
+// MODULE DATA STRUCTURES
+// None
+
+// LOCAL FUNCTION PROTOTYPES
+// None
+
+// FORWARD DECLARATIONS
+// None
+
+// ==================== LOCAL FUNCTIONS =======================================
+// None
+
+// ================= MEMBER FUNCTIONS =========================================
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CFileOutput
+
+ Method: CFileOutput
+
+ Description: Default constructor
+
+ C++ default constructor can NOT contain any code, that
+ might leave.
+
+ Parameters: TLoggerType aLoggerType: in: File type
+ TBool aWithTimeStamp: in: For timestamp
+ TBool aWithLineBreak: in: For line break
+ TBool aWithEventRanking: in: For events ranking to file
+ TBool aThreadIdToLogFile: in: Indicator to thread id adding to
+ end of the log file
+
+ Return Values: None
+
+ Errors/Exceptions: None
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CFileOutput::CFileOutput( CStifLogger::TLoggerType aLoggerType,
+ TBool aWithTimeStamp,
+ TBool aWithLineBreak,
+ TBool aWithEventRanking,
+ TBool aThreadIdToLogFile ) :
+ COutput()
+ {
+ // Indicates file type
+ iLoggerType = aLoggerType;
+
+ // Time stamp indicator
+ iWithTimeStamp = aWithTimeStamp;
+
+ // Line break indicator
+ iWithLineBreak = aWithLineBreak;
+
+ // Log event ranking indicator
+ iWithEventRanking = aWithEventRanking;
+
+ // Indicator to thread id adding to end of the log file
+ iThreadIdToLogFile = aThreadIdToLogFile;
+
+ // Is file open indicator
+ iIsFileOpen = 0;
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CFileOutput
+
+ Method: ConstructL
+
+ Description: Symbian OS second phase constructor
+
+ Symbian OS default constructor can leave.
+
+ Parameters: const TDesC& aTestPath: in: Log path
+ const TDesC& aTestFile: in: Log filename
+ TBool aOverWrite: in: For file overwrite
+ TBool aCreateLogDir: in: Indicator to directory creation
+ TInt aStaticBufferSize
+ TBool aUnicode: in: Indicator if file has to be in unicode format
+
+ Return Values: None
+
+ Errors/Exceptions: Leaves if called CreateNewFileL method fails
+ Leaves if called OpenExistingFileL method fails
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CFileOutput::ConstructL( const TDesC& aTestPath,
+ const TDesC& aTestFile,
+ TBool aOverWrite,
+ TBool aCreateLogDir,
+ TInt aStaticBufferSize,
+ TBool aUnicode)
+ {
+ iUnicode = aUnicode;
+
+ // Open file session
+ User::LeaveIfError( iFileSession.Connect() );
+
+ // Create a log directory
+ if( aCreateLogDir )
+ {
+ CreateDirectoryL( aTestPath );
+ }
+
+ // Create a new file
+ if ( aOverWrite )
+ {
+ CreateNewFileL( aTestPath, aTestFile );
+ }
+ // Open an existing file
+ else
+ {
+ OpenExistingFileL( aTestPath, aTestFile );
+ }
+
+ if( aStaticBufferSize != 0)
+ {
+ iDataHBuf8 = HBufC8::NewL( aStaticBufferSize );
+ iDataHBuf16 = HBufC::NewL(aStaticBufferSize);
+ iStaticBufferSize = aStaticBufferSize;
+ }
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CFileOutput
+
+ Method: NewL
+
+ Description: Two-phased constructor.
+
+ Parameters: const TDesC& aTestPath: in: Log path
+ const TDesC& aTestFile: in: Log filename
+ TLoggerType aLoggerType: in: File type
+ TBool aOverWrite: in: For file overwrite
+ TBool aWithTimeStamp: in: For timestamp
+ TBool aWithLineBreak: in: For line break
+ TBool aWithEventRanking: in: For events ranking to file
+ TBool aThreadIdToLogFile: in: Indicator to thread id adding to
+ end of the log file
+ TBool aCreateLogDir: in: Indicator to directory creation
+ TInt aStaticBufferSize
+ TBool aUnicode: in: Indicator if file has to be in unicode format
+
+ Return Values: CFileOutput*: pointer to CFileOutput object
+
+ Errors/Exceptions: Leaves if ConstructL leaves
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+CFileOutput* CFileOutput::NewL( const TDesC& aTestPath,
+ const TDesC& aTestFile,
+ CStifLogger::TLoggerType aLoggerType,
+ TBool aOverWrite,
+ TBool aWithTimeStamp,
+ TBool aWithLineBreak,
+ TBool aWithEventRanking,
+ TBool aThreadIdToLogFile,
+ TBool aCreateLogDir,
+ TInt aStaticBufferSize,
+ TBool aUnicode )
+ {
+ // Create CFileOutput object fileWriter
+ CFileOutput* fileWriter = new (ELeave) CFileOutput( aLoggerType,
+ aWithTimeStamp,
+ aWithLineBreak,
+ aWithEventRanking,
+ aThreadIdToLogFile );
+
+ CleanupStack::PushL( fileWriter );
+ fileWriter->ConstructL( aTestPath, aTestFile, aOverWrite, aCreateLogDir, aStaticBufferSize,
+ aUnicode );
+ CleanupStack::Pop( fileWriter );
+
+ return fileWriter;
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CFileOutput
+
+ Method: ~CFileOutput
+
+ Description: Destructor
+
+ Parameters: None
+
+ Return Values: None
+
+ Errors/Exceptions: None
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CFileOutput::~CFileOutput()
+ {
+ // Close file
+ iFile.Close();
+ // Close file session
+ iFileSession.Close();
+
+ delete iDataHBuf8;
+ delete iDataHBuf16;
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CFileOutput
+
+ Method: FileType
+
+ Description: Check file type.
+
+ Check is file type set with a aTestFile's name. If file type is not set
+ the type will set according to StifLogger's type.
+
+ Parameters: const TDesC& aTestFile: in: Log filename
+ TFileType& fileType: inout: Generated file type
+
+ Return Values: None
+
+ Errors/Exceptions: None
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CFileOutput::FileType( const TDesC& aTestFile,
+ TFileType& aFileType )
+ {
+ TBool fileTypeIsSet( EFalse ); // File type indicator
+
+ // Check is file type set to aTestFile parameter
+ TInt ret = aTestFile.Find( _L( "." ) );
+ if( ret != KErrNotFound )
+ {
+ fileTypeIsSet = ETrue;
+ }
+ // If not, add thread id name if allowed
+ else if ( iThreadIdToLogFile )
+ {
+ // Thread id maximum length is 8 in hexadesimal format
+ // Construct unique thread name
+ aFileType.Append( _L("_") );
+ RThread threadHandle; // A handle to a thread
+ TThreadId id = threadHandle.Id(); // Encapsulates the
+ // Id of a thread
+ // Appends id in hexadesimal format
+ aFileType.AppendFormat( _L( "%x" ), (TInt)id );
+ }
+
+ // Add file type after the thread id name
+ if ( iLoggerType == CStifLogger::ETxt && !fileTypeIsSet )
+ {
+ // ".txt"
+ aFileType.Append( _L( "." ) );
+ aFileType.Append( _L( "txt" ) );
+ }
+ else if ( iLoggerType == CStifLogger::EHtml && !fileTypeIsSet )
+ {
+ // ".html"
+ aFileType.Append( _L( "." ) );
+ aFileType.Append( _L( "html" ) );
+ }
+ // EData file type comes from the aTestFile name. If not the file type
+ // will be empty
+ else if ( iLoggerType == CStifLogger::EData )
+ {
+ aFileType.Append( _L( "" ) );
+ }
+ else
+ {
+ aFileType.Append( _L( "" ) );
+ }
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CFileOutput
+
+ Method: TestFileWithThreadId
+
+ Description: Generate thread id
+
+ Generate thread id name between the test file name and test file type.
+
+ Parameters: TDesC& aTestFile: in: Test file name
+ TFileName& aNewTestFile: inout: Generated test file name
+
+ Return Values: None
+
+ Errors/Exceptions: None
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CFileOutput::TestFileWithThreadId( const TDesC& aTestFile,
+ TFileName& aNewTestFile )
+ {
+ for( TInt a = 0; a < aTestFile.Length(); a++ )
+ {
+ // Find a dot
+ if( aTestFile[a] == '.' )
+ {
+ TPtrC parsedFileType = aTestFile.Mid( a ); // Take rest of the
+ // aTestFile
+ aNewTestFile.Append( _L( "_" ) );
+ RThread threadHandle; // A handle to a thread
+ TThreadId id = threadHandle.Id(); // Encapsulates the
+ // Id of a thread
+ aNewTestFile.AppendFormat( _L( "%x" ), (TInt)id );// Appends id in
+ // hexadesimal format
+ aNewTestFile.Append( parsedFileType );
+ break;
+ }
+ // Dot not found yet
+ else
+ {
+ aNewTestFile.Append( aTestFile[a] );
+ }
+ }
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CFileOutput
+
+ Method: CreateDirectoryL
+
+ Description: Create a log directory.
+
+ Method creates directory if not allready exist.
+
+ Parameters: const TDesC& aTestPath: in: Test path definition
+
+ Return Values: None
+
+ Errors/Exceptions: Leaves if directory creation fails
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CFileOutput::CreateDirectoryL( const TDesC& aTestPath )
+ {
+ __TRACE( KInfo, ( _L( "STIFLOGGER: Create a directory" ) ) );
+
+ TInt ret = iFileSession.MkDirAll( aTestPath );
+ if( ret != KErrNone && ret != KErrAlreadyExists )
+ {
+ __TRACE( KError,
+ ( _L( "STIFLOGGER: Directory creation fails with error: %d" ), ret ) );
+ User::Leave( ret );
+ }
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CFileOutput
+
+ Method: OpenExistingFileL
+
+ Description: Open an existing file.
+
+ Method is used when is need for log new information after the existing
+ log file.
+
+ Parameters: const TDesC& aTestPath: in: Test path definition
+ const TDesC& aTestFile: in: Test file name
+
+ Return Values: None
+
+ Errors/Exceptions: Leaves if path or file lengths are over KMaxFileName
+ Leaves if file Replace method fails
+ Leaves if file Open method fails
+ Leaves if file path not found
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CFileOutput::OpenExistingFileL( const TDesC& aTestPath,
+ const TDesC& aTestFile )
+ {
+ __TRACE( KInfo, ( _L( "STIFLOGGER: Opening an existing file for logging" ) ) );
+
+ // If path and file name lengths are over KMaxFileName(TFileName)
+ __ASSERT_ALWAYS(
+ ( aTestPath.Length() + aTestFile.Length() ) < KMaxFileName,
+ User::Leave( KErrArgument ) );
+
+ // Check file type and generate threat id name
+ TFileType fileType;
+ FileType( aTestFile, fileType );
+
+ // File directory name, file name and file type definitions
+ TPtrC dirNamePrt( aTestPath );
+ iFileAndDirName.Copy( dirNamePrt );
+
+ TInt isDotFound = aTestFile.Find( _L( "." ) );
+ // If dot is found and iThreadIdToLogFile is true
+ if( isDotFound != KErrNotFound && iThreadIdToLogFile )
+ {
+ TFileName testFileWithThreadId;
+ // Generate thread id name
+ TestFileWithThreadId( aTestFile, testFileWithThreadId );
+ iFileAndDirName.Insert(
+ iFileAndDirName.Length(), testFileWithThreadId );
+ }
+ else
+ {
+ TPtrC txtPrt( fileType );
+ iFileAndDirName.Insert( iFileAndDirName.Length(), aTestFile );
+ iFileAndDirName.Insert( iFileAndDirName.Length(), txtPrt );
+ }
+
+ TBool isOpen( EFalse );
+ TInt ret( KErrNone );
+
+ iIsFileOpen = iFileSession.IsFileOpen( iFileAndDirName, isOpen );
+ if( iIsFileOpen == KErrNotFound )
+ {
+ ret = iFile.Create( iFileSession, iFileAndDirName,
+ EFileWrite | EFileStreamText |
+ EFileShareAny );
+ if(iUnicode && ret == KErrNone)
+ {
+ char FF = 0xFF;
+ char FE = 0xFE;
+ TBuf8<2> beg;
+ beg.Append(FF);
+ beg.Append(FE);
+ if(iFile.Write(beg) == KErrNone)
+ iFile.Flush();
+ }
+ }
+ else if( iIsFileOpen == KErrNone )
+ {
+ ret = iFile.Open( iFileSession, iFileAndDirName,
+ EFileWrite | EFileStreamText |
+ EFileShareAny );
+ }
+ // Probably path not found
+ else
+ {
+ User::Leave( iIsFileOpen );
+ }
+
+ if ( ret != KErrNone )
+ {
+ User::Leave( ret );
+ }
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CFileOutput
+
+ Method: CreateNewFileL
+
+ Description: Create a new file.
+
+ Method creates new file to the log information.
+
+ Parameters: const TDesC& aTestPath: in: Test path definition
+ const TDesC& aTestFile: in: Test file name
+
+ Return Values: None
+
+ Errors/Exceptions: Leaves if path or file lengths are over KMaxFileName
+ Leaves if file server Connect method fails
+ Leaves if file Replace method fails
+ Leaves if file Open method fails
+ Leaves if file path not found
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CFileOutput::CreateNewFileL( const TDesC& aTestPath,
+ const TDesC& aTestFile )
+ {
+ __TRACE( KInfo, ( _L( "STIFLOGGER: Create a new file for logging" ) ) );
+
+ // If path and file name lengths are over KMaxFileName(TFileName)
+ __ASSERT_ALWAYS(
+ ( aTestPath.Length() + aTestFile.Length() ) < KMaxFileName,
+ User::Leave( KErrArgument ) );
+
+ // Check file type and generate threat id name
+ TFileType fileType;
+ FileType( aTestFile, fileType );
+
+ // File directory name, file name and file type definitions
+ TPtrC dirNamePrt( aTestPath );
+ iFileAndDirName.Copy( dirNamePrt );
+
+ TInt isDotFound = aTestFile.Find( _L( "." ) );
+ // If dot is found and iThreadIdToLogFile is true
+ if( isDotFound != KErrNotFound && iThreadIdToLogFile )
+ {
+ TFileName testFileWithThreadId;
+ // Generate thread id name
+ TestFileWithThreadId( aTestFile, testFileWithThreadId );
+ iFileAndDirName.Insert(
+ iFileAndDirName.Length(), testFileWithThreadId );
+ }
+ else
+ {
+ TPtrC txtPrt( fileType );
+ iFileAndDirName.Insert( iFileAndDirName.Length(), aTestFile );
+ iFileAndDirName.Insert( iFileAndDirName.Length(), txtPrt );
+ }
+
+ // Delete file if exist
+ iFileSession.Delete( iFileAndDirName );
+
+ TBool isOpen( EFalse );
+ TInt ret( KErrNone );
+
+ iIsFileOpen = iFileSession.IsFileOpen( iFileAndDirName, isOpen );
+ if( ( iIsFileOpen == KErrNotFound ) ||
+ ( iIsFileOpen == KErrNone ) )
+ {
+ ret = iFile.Replace( iFileSession, iFileAndDirName,
+ EFileWrite | EFileStreamText |
+ EFileShareAny );
+ if(iUnicode && ret == KErrNone)
+ {
+ char FF = 0xFF;
+ char FE = 0xFE;
+ TBuf8<2> beg;
+ beg.Append(FF);
+ beg.Append(FE);
+ if(iFile.Write(beg) == KErrNone)
+ iFile.Flush();
+ }
+ }
+ // Probably path not found
+ else
+ {
+ User::Leave( iIsFileOpen );
+ }
+
+ if ( ret != KErrNone )
+ {
+ User::Leave( ret );
+ }
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CFileOutput
+
+ Method: Write
+
+ Description: Write log information or data to the file. 16 bit.
+
+ Parameters: TBool aWithTimeStamp: in: Is time stamp flag used
+ TBool aWithLineBreak: in: Is line break flag used
+ TBool aWithEventRanking: in: Is event ranking flag used
+ const TDesC& aData: in: Logged or saved data
+
+ Return Values: TInt: Symbian error code.
+
+ Errors/Exceptions: None
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TInt CFileOutput::Write( TBool aWithTimeStamp, TBool aWithLineBreak,
+ TBool aWithEventRanking, const TDesC& aData )
+ {
+ TInt extraLength( 0 ); // Line and/or event required length
+
+ TPtr data16(0, 0);
+ TPtr8 data8(0, 0);
+
+ // Extra space calculation
+ if( iWithEventRanking && aWithEventRanking )
+ {
+ extraLength = extraLength + KMaxEventRanking + KMaxSpace;
+ }
+ if( ( iLoggerType == CStifLogger::EHtml ) && iWithLineBreak && aWithLineBreak )
+ {
+ extraLength = extraLength + KMaxHtmlLineBreak;
+ }
+ if( iWithLineBreak && aWithLineBreak )
+ {
+ extraLength = extraLength + KMaxLineBreak;
+ }
+ if( aWithTimeStamp && iWithTimeStamp )
+ {
+ extraLength = extraLength + KMaxTimeStamp;
+ }
+
+ // Calculated space
+ TInt space = aData.Length();
+
+ HBufC8* dataHBuf8 = NULL;
+ HBufC16* dataHBuf16 = NULL;
+
+ if( iDataHBuf8 != NULL )
+ {
+ // We'll use HBufC created in ConstructL
+ data8.Set(iDataHBuf8->Des());
+ data16.Set(iDataHBuf16->Des());
+ data16.Copy(_L("")); // Initialize aData buffer
+
+ if( (aData.Length() + extraLength) > iStaticBufferSize )
+ {
+ RDebug::Print(_L("Warning: buffer size too small, not able to log!"));
+ return KErrOverflow;
+ }
+ }
+ else
+ {
+ // We'll create a local HBufC, deleting it in the end of this method
+ dataHBuf8 = HBufC8::New( space + extraLength );
+ if( dataHBuf8 == NULL )
+ {
+ return KErrNoMemory;
+ }
+ dataHBuf16 = HBufC16::New(space + extraLength);
+ if(dataHBuf16 == NULL)
+ {
+ delete dataHBuf8;
+ return KErrNoMemory;
+ }
+ data8.Set(dataHBuf8->Des());
+ data16.Set(dataHBuf16->Des());
+ }
+
+ // Event ranking
+ if( iWithEventRanking && aWithEventRanking && !iWithTimeStamp )
+ {
+ EventRanking( data16 ); // Event ranking to data
+ data16.Append( aData ); // Unicode aData to normal text
+ }
+ // Time stamp
+ else if( iWithTimeStamp && aWithTimeStamp )
+ {
+ // With event ranking
+ if( iWithEventRanking && aWithEventRanking )
+ {
+ EventRanking( data16 ); // Event ranking to data
+ }
+ AddTimeStampToData( data16 );// Add time stamp
+ data16.Append( aData ); // Unicode aData to normal text
+ }
+ else
+ {
+ data16.Copy( aData ); // Unicode aData to normal text
+ }
+
+ // NOTE: If need some special line break do it with logging phase
+
+ // If html logging and line break is used add the line break.
+ if (( iLoggerType == CStifLogger::EHtml ) && iWithLineBreak && aWithLineBreak )
+ {
+ data16.Append( _L( "
" ) );
+ data16.Append( _L( "\n" ) ); // To make html file more readable
+ // with text editor
+ }
+
+ // Other cases line break is normal '\n' if logging is used
+ else if( iWithLineBreak && aWithLineBreak )
+ {
+ data16.Append( 0x0D ); // 13 or '\' in Symbian OS
+ data16.Append( 0x0A ); // 10 or 'n' in Symbian OS
+ }
+
+ // Write the data to file
+ TInt tmp = 0;
+ if( iFile.Seek( ESeekEnd, tmp ) == KErrNone )
+ {
+ RDEBUG_FILEWRITECRASH(_L("iFile.Write 1 in"));
+ TPtrC8 dataToFile(0, 0);
+ if(iUnicode)
+ {
+ dataToFile.Set((TUint8 *)(data16.Ptr()), data16.Length() * 2);
+ }
+ else
+ {
+ data8.Copy(data16);
+ dataToFile.Set(data8);
+ }
+ if(iFile.Write(dataToFile) == KErrNone)
+ iFile.Flush();
+ RDEBUG_FILEWRITECRASH(_L("iFile.Write 1 out"));
+ }
+ if( iDataHBuf8 == NULL )
+ {
+ delete dataHBuf8;
+ dataHBuf8 = 0;
+ delete dataHBuf16;
+ dataHBuf16 = 0;
+ }
+
+ return KErrNone;
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CFileOutput
+
+ Method: Write
+
+ Description: Write log information or data to the file. 8 bit.
+
+ Parameters: TBool aWithTimeStamp: in: Is time stamp flag used
+ TBool aWithLineBreak: in: Is line break flag used
+ TBool aWithEventRanking: in: Is event ranking flag used
+ const TDesC8& aData: in: Logged or saved data
+
+ Return Values: TInt: Symbian error code.
+
+ Errors/Exceptions: None
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TInt CFileOutput::Write( TBool aWithTimeStamp, TBool aWithLineBreak,
+ TBool aWithEventRanking, const TDesC8& aData )
+ {
+ TInt extraLength( 0 ); // Line and/or event required length
+
+ TPtr data16(0, 0);
+ TPtr8 data8(0, 0);
+
+ // Extra space calculation
+ if( iWithEventRanking && aWithEventRanking )
+ {
+ extraLength = extraLength + KMaxEventRanking + KMaxSpace;
+ }
+ if( ( iLoggerType == CStifLogger::EHtml ) && iWithLineBreak && aWithLineBreak )
+ {
+ extraLength = extraLength + KMaxHtmlLineBreak;
+ }
+ if( iWithLineBreak && aWithLineBreak )
+ {
+ extraLength = extraLength + KMaxLineBreak;
+ }
+ if( aWithTimeStamp && iWithTimeStamp )
+ {
+ extraLength = extraLength + KMaxTimeStamp;
+ }
+
+ // aData straight to the file
+ if ( extraLength == 0 && !iUnicode)
+ {
+ // Write the data to file
+ TInt tmp = 0;
+ if( iFile.Seek( ESeekEnd, tmp ) == KErrNone )
+ {
+ RDEBUG_FILEWRITECRASH(_L("iFile.Write 2 in"));
+ if( iFile.Write( aData ) == KErrNone )
+ iFile.Flush();
+ RDEBUG_FILEWRITECRASH(_L("iFile.Write 2 out"));
+ }
+ return KErrNone;
+ }
+
+ // Calculated space
+ TInt space = aData.Length();
+ HBufC8* dataHBuf8 = NULL;
+ HBufC* dataHBuf16 = NULL;
+
+ if( iDataHBuf8 != NULL )
+ {
+ // We'll use HBufC created in ConstructL
+ data8.Set(iDataHBuf8->Des());
+ data8.Copy(_L("")); // Initialize aData buffer
+ data16.Set(iDataHBuf16->Des());
+
+ if( (aData.Length() + extraLength) > iStaticBufferSize )
+ {
+ RDebug::Print(_L("Warning: buffer size too small, not able to log!"));
+ return KErrOverflow;
+ }
+ }
+ else
+ {
+ // We'll create a local HBufC, deleting it in the end of this method
+ dataHBuf8 = HBufC8::New( space + extraLength );
+ if( dataHBuf8 == NULL )
+ {
+ return KErrNoMemory;
+ }
+ dataHBuf16 = HBufC16::New(space + extraLength);
+ if(dataHBuf16 == NULL)
+ {
+ delete dataHBuf8;
+ return KErrNoMemory;
+ }
+ data8.Set(dataHBuf8->Des()); // Memory allocation for data
+ data16.Set(dataHBuf16->Des()); // Memory allocation for data
+ }
+
+ // Event ranking
+ if( iWithEventRanking && aWithEventRanking && !iWithTimeStamp )
+ {
+ EventRanking( data8 ); // Event ranking to data
+ data8.Append( aData ); // Unicode aData to normal text
+ }
+ // Time stamp
+ else if( iWithTimeStamp && aWithTimeStamp )
+ {
+ // With event ranking
+ if( iWithEventRanking && aWithEventRanking )
+ {
+ EventRanking( data8 ); // Event ranking to data
+ }
+ AddTimeStampToData( data8 );// Add time stamp
+ data8.Append( aData ); // Unicode aData to normal text
+ }
+ else
+ {
+ data8.Copy( aData ); // Unicode aData to normal text
+ }
+
+ // NOTE: If need some special line break do it with logging phase
+
+ // If html logging and line break is used add the line break.
+ if ( ( iLoggerType == CStifLogger::EHtml ) && iWithLineBreak && aWithLineBreak )
+ {
+ data8.Append( _L( "
" ) );
+ data8.Append( _L( "\n" ) ); // To make html file more readable
+ // with text editor
+ }
+
+ // Other cases line break is normal '\n' if logging is used
+ else if( iWithLineBreak && aWithLineBreak )
+ {
+ data8.Append( 0x0D ); // 13 or '\' in Symbian OS
+ data8.Append( 0x0A ); // 10 or 'n' in Symbian OS
+ }
+
+ // Write the data to file
+ TInt tmp = 0;
+ if( iFile.Seek( ESeekEnd, tmp ) == KErrNone )
+ {
+ RDEBUG_FILEWRITECRASH(_L("iFile.Write 3 in"));
+ TPtrC8 dataToFile(0, 0);
+ if(iUnicode)
+ {
+ data16.Copy(data8);
+ dataToFile.Set((TUint8 *)(data16.Ptr()), data16.Length() * 2);
+ }
+ else
+ {
+ dataToFile.Set(data8);
+ }
+ if(iFile.Write(dataToFile) == KErrNone)
+ iFile.Flush();
+ RDEBUG_FILEWRITECRASH(_L("iFile.Write 3 out"));
+ }
+ if( iDataHBuf8 == NULL )
+ {
+ delete dataHBuf8;
+ dataHBuf8 = 0;
+ delete dataHBuf16;
+ dataHBuf16 = 0;
+ }
+
+ return KErrNone;
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CFileOutput
+
+ Method: EventRanking
+
+ Description: For event ranking logging.
+
+ Parameters: TPtr& aData: inout: Data with event ranking
+
+ Return Values: None
+
+ Errors/Exceptions: None
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CFileOutput::EventRanking( TPtr& aData )
+ {
+ // Returns the machine's current tick count.
+ TUint tick = User::TickCount();
+ tick &= 0xffff;
+ aData.AppendNum( tick );
+ aData.Append( _L( " " ) );
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CFileOutput
+
+ Method: EventRanking
+
+ Description: For event ranking logging.
+
+ Parameters: TPtr8& aData: inout: Data with event ranking
+
+ Return Values: None
+
+ Errors/Exceptions: None
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CFileOutput::EventRanking( TPtr8& aData )
+ {
+ // Returns the machine's current tick count.
+ TUint tick = User::TickCount();
+ tick &= 0xffff;
+ aData.AppendNum( tick );
+ aData.Append( _L8( " " ) );
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CFileOutput
+
+ Method: AddTimeStampToData
+
+ Description: For date and time logging.
+
+ Parameters: TPtr& aData: inout: Data with time stamps
+
+ Return Values: None
+
+ Errors/Exceptions: None
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CFileOutput::AddTimeStampToData( TPtr& aData )
+ {
+ TStifLoggerTimeStamp timeStamp;
+ GetDateAndTime( timeStamp );
+
+ TStifLoggerTimeStamp8 tStamp16;
+ tStamp16.Copy(timeStamp);
+
+ aData.Append( tStamp16 );
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CFileOutput
+
+ Method: AddTimeStampToData
+
+ Description: For date and time logging.
+
+ Parameters: TPtr8& aData: inout: Data with time stamps
+
+ Return Values: None
+
+ Errors/Exceptions: None
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CFileOutput::AddTimeStampToData( TPtr8& aData )
+ {
+ TStifLoggerTimeStamp timeStamp;
+ GetDateAndTime( timeStamp );
+ aData.Append( timeStamp );
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CFileOutput
+
+ Method: GetDateAndTime
+
+ Description: For date and time logging.
+
+ Parameters: TStifLoggerTimeStamp& aDataAndTime: inout: Generated date and time
+
+ Return Values: None
+
+ Errors/Exceptions: None
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CFileOutput::GetDateAndTime( TStifLoggerTimeStamp& aDataAndTime )
+ {
+ TInt num( 0 );
+ TInt microseconds( 0 );
+
+ // Append date
+ TTime time;
+ time.HomeTime();
+ TDateTime dateTime( time.DateTime() );
+
+ num = dateTime.Day() + 1;
+ if( num < 10 )
+ {
+ aDataAndTime.Append( '0' );
+ }
+ // Append month
+ aDataAndTime.AppendNum( num );
+ aDataAndTime.Append( '.' );
+ num = 0;
+ num = dateTime.Month();
+ switch( num )
+ {
+ case EJanuary: // 1
+ {
+ aDataAndTime.Append( _L( "Jan" ) );
+ break;
+ }
+ case EFebruary: // 2
+ {
+ aDataAndTime.Append( _L( "Feb" ) );
+ break;
+ }
+ case EMarch: // 3
+ {
+ aDataAndTime.Append( _L( "Mar" ) );
+ break;
+ }
+ case EApril: // 4
+ {
+ aDataAndTime.Append( _L( "Apr" ) );
+ break;
+ }
+ case EMay: // 5
+ {
+ aDataAndTime.Append( _L( "May" ) );
+ break;
+ }
+ case EJune: // 6
+ {
+ aDataAndTime.Append( _L( "Jun" ) );
+ break;
+ }
+ case EJuly: // 7
+ {
+ aDataAndTime.Append( _L( "Jul" ) );
+ break;
+ }
+ case EAugust: // 8
+ {
+ aDataAndTime.Append( _L( "Aug" ) );
+ break;
+ }
+ case ESeptember: // 9
+ {
+ aDataAndTime.Append( _L( "Sep" ) );
+ break;
+ }
+ case EOctober: // 10
+ {
+ aDataAndTime.Append( _L( "Oct" ) );
+ break;
+ }
+ case ENovember: // 11
+ {
+ aDataAndTime.Append( _L( "Nov" ) );
+ break;
+ }
+ case EDecember: // 12
+ {
+ aDataAndTime.Append( _L( "Dec" ) );
+ break;
+ }
+ default:
+ {
+ aDataAndTime.Append( '-' );
+ break;
+ }
+ }
+ // Append year
+ aDataAndTime.Append( '.' );
+ aDataAndTime.AppendNum( dateTime.Year() );
+
+ // Append time
+ aDataAndTime.Append( ' ' );
+ num = dateTime.Hour();
+ if( num < 10 )
+ {
+ aDataAndTime.Append( '0' );
+ }
+ aDataAndTime.AppendNum( num );
+ aDataAndTime.Append( ':' );
+ num = dateTime.Minute();
+ if( num < 10 )
+ {
+ aDataAndTime.Append( '0' );
+ }
+ aDataAndTime.AppendNum( num );
+ aDataAndTime.Append( ':' );
+
+ num = dateTime.Second(); // Seconds
+ microseconds = dateTime.MicroSecond(); // Microseconds
+
+ // Seconds
+ if( num < 10 )
+ {
+ aDataAndTime.Append( '0' );
+ }
+ aDataAndTime.AppendNum( num );
+
+ // Milliseconds
+ aDataAndTime.Append( '.' );
+ aDataAndTime.AppendNumFixedWidth( microseconds, EDecimal, 3 );
+
+ // NOTE: If you add more spaces etc. remember increment KMaxTimeStamp size!
+
+ if ( iLoggerType == CStifLogger::EHtml )
+ {
+ aDataAndTime.Append( _L("....") );
+ }
+ else
+ {
+ aDataAndTime.Append( _L(" ") );
+ }
+
+ }
+
+// ================= OTHER EXPORTED FUNCTIONS =================================
+// None
+
+// End of File