/*
* Copyright (c) 2004, 2006 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 FILES
#include <hal.h>
#include <charconv.h>
#include "logfile.h"
#include "logfile.pan"
// ============================ MEMBER FUNCTIONS ==============================
// ----------------------------------------------------------------------------
// CLogFile::NewL()
// Two-phased constructor.
// Standard Symbian OS construction sequence.
// ----------------------------------------------------------------------------
//
CLogFile* CLogFile::NewL( const TDesC& aFileName, TBool aInitialiseLog )
{
CLogFile* self = NewLC( aFileName, aInitialiseLog );
CleanupStack::Pop();
return( self );
}
// ----------------------------------------------------------------------------
// CLogFile::NewLC()
// Two-phased constructor.
// Standard Symbian OS construction sequence.
// ----------------------------------------------------------------------------
//
CLogFile* CLogFile::NewLC( const TDesC& aFileName, TBool aInitialiseLog )
{
CLogFile* self = new ( ELeave ) CLogFile();
CleanupStack::PushL( self );
self->ConstructL( aFileName, aInitialiseLog );
return( self );
}
// ----------------------------------------------------------------------------
// CLogFile::CLogFile()
// Constructor.
// ----------------------------------------------------------------------------
//
CLogFile::CLogFile()
{
// No implementation required
}
// ----------------------------------------------------------------------------
// CLogFile::CLogFile()
// Destructor.
// ----------------------------------------------------------------------------
//
CLogFile::~CLogFile()
{
iLogFile.Flush();
iLogFile.Close();
iSession.Close();
delete iCharacterConverter;
iCharacterConverter = NULL;
}
// ----------------------------------------------------------------------------
// CLogFile::ConstructL()
// Symbian 2nd phase constructor can leave.
// ----------------------------------------------------------------------------
//
void CLogFile::ConstructL( const TDesC& aFileName, TBool aInitialiseLog )
{
TInt period;
User::LeaveIfError( HAL::Get( HALData::ESystemTickPeriod, period ) );
iLogMillisecsPerTick = period / 1000;
if ( iLogMillisecsPerTick == 0 )
{
iLogMillisecsPerTick = 1;
}
iSession.Connect();
if ( aInitialiseLog )
{
User::LeaveIfError( iLogFile.Replace( iSession,
aFileName,
EFileShareExclusive ) );
}
else
{
TInt err = iLogFile.Open( iSession, aFileName,
EFileShareExclusive | EFileWrite );
switch ( err )
{
case KErrNone: // Opened ok, so seek to end of file
{
TInt position = 0;
User::LeaveIfError( iLogFile.Seek( ESeekEnd, position ) );
}
break;
case KErrNotFound: // File doesn't exist, so create it
User::LeaveIfError( iLogFile.Create( iSession,
aFileName,
EFileShareExclusive |
EFileWrite ) );
break;
default: // Unexepected error
User::Leave( err );
break;
}
}
// Create character converter
iCharacterConverter = CCnvCharacterSetConverter::NewL();
CCnvCharacterSetConverter::TAvailability iConverterAvailability;
iConverterAvailability = iCharacterConverter->PrepareToConvertToOrFromL(
KCharacterSetIdentifierAscii, iSession );
}
// ----------------------------------------------------------------------------
// CLogFile::LogTime()
// Append a timestamp to the log file.
// ----------------------------------------------------------------------------
//
void CLogFile::LogTime()
{
StartWrite();
LogTimeInternal();
EndWrite();
}
// ----------------------------------------------------------------------------
// CLogFile::Log()
// Append text to the log file.
// ----------------------------------------------------------------------------
//
void CLogFile::Log( const TDesC8& aText )
{
StartWrite();
LogTextInternal( aText );
EndWrite();
}
// ----------------------------------------------------------------------------
// CLogFile::Log()
// Append text to the log file.
// ----------------------------------------------------------------------------
//
void CLogFile::Log( const TDesC& aText )
{
StartWrite();
for ( TInt i = 0; i < aText.Length(); i++ )
{
if ( aText.Mid(i).Find( KCrLf ) == 0 )
{
LogNewline();
i++;
}
else if ( iConverterAvailability ==
CCnvCharacterSetConverter::EAvailable )
{
// Convert character from unicode
TBuf<1> unicodeBuffer;
TBuf8<10> asciiBuffer;
unicodeBuffer.Append(aText[i]);
TInt status = iCharacterConverter->ConvertFromUnicode(
asciiBuffer, unicodeBuffer );
if ( status >= 0 )
{
LogTextInternal( asciiBuffer );
}
}
else // character converter not available
{
TBuf8<1> asciiBuffer;
asciiBuffer.Append( static_cast<TUint8>( aText[i] ) );
LogTextInternal( asciiBuffer );
}
}
EndWrite();
}
// ----------------------------------------------------------------------------
// CLogFile::Log()
// Append the byte to the log file.
// ----------------------------------------------------------------------------
//
void CLogFile::Log( TUint8 aByte )
{
StartWrite();
LogByteInternal( aByte );
EndWrite();
}
// ----------------------------------------------------------------------------
// CLogFile::Log()
// Append the integer to the log file.
// ----------------------------------------------------------------------------
//
void CLogFile::Log( TUint aNumber )
{
StartWrite();
LogIntInternal( aNumber );
EndWrite();
}
// ----------------------------------------------------------------------------
// CLogFile::LogBytes()
// Append the bytes to the log file.
// ----------------------------------------------------------------------------
//
void CLogFile::LogBytes( const TDesC8& aBuffer )
{
StartWrite();
for ( TInt i = 0; i < aBuffer.Length(); i++ )
{
LogByteInternal( aBuffer[i] );
}
EndWrite();
}
// ----------------------------------------------------------------------------
// CLogFile::LogTimeInternal()
// Internal function to log time.
// ----------------------------------------------------------------------------
//
void CLogFile::LogTimeInternal()
{
TBuf8<50> text;
TInt timeInMillisecs = User::TickCount() * iLogMillisecsPerTick;
TInt secs = timeInMillisecs / 1000;
TInt millisecs = timeInMillisecs % 1000;
text.Num( secs );
text.Append( '.' );
Write( text );
text.Num( millisecs );
while ( text.Length() < KNumberOfDecimalPlaces )
{
text.Insert( 0, _L8( "0" ) );
}
text.Append( '-' );
Write( text );
}
// ----------------------------------------------------------------------------
// CLogFile::LogTextInternal()
// Internal function to log text.
// ----------------------------------------------------------------------------
//
void CLogFile::LogTextInternal( const TDesC8& aText )
{
TPtrC8 tail( aText.Ptr(), aText.Length() );
TInt newLinePosition = tail.Find( KCrLf8 );
while ( newLinePosition != KErrNotFound )
{
if ( newLinePosition > 0 )
{
Write( tail.Left( newLinePosition ) );
tail.Set( aText.Ptr() + newLinePosition, tail.Length() -
newLinePosition );
}
LogNewline();
tail.Set( aText.Ptr() + KCrLf8.iTypeLength, tail.Length() -
KCrLf8.iTypeLength );
newLinePosition = tail.Find( KCrLf8 );
}
// No more newlines left so print remainder
Write( tail );
}
// ----------------------------------------------------------------------------
// CLogFile::LogByteInternal()
// internal function to log a byte.
// ----------------------------------------------------------------------------
//
void CLogFile::LogByteInternal( TUint8 aByte )
{
if ( ( aByte >= KAsciiStart ) && ( aByte < KAsciiEnd ) )
{
// Display as ASCII char
TBuf8<1> str;
str.Append( aByte );
Write( str );
}
else
{
// Display as hex number
TBuf8<4> str;
str.Append( KHexCharLeft );
str.AppendNum( ( TUint )aByte, EHex );
str.Append( KHexCharRight );
Write( str );
}
}
// ----------------------------------------------------------------------------
// CLogFile::LogIntInternal()
// Internal function to log an integer.
// ----------------------------------------------------------------------------
//
void CLogFile::LogIntInternal( TUint aNumber )
{
// Display as ASCII char
TBuf8<20> str;
str.Append( KHexCharLeft );
str.AppendNum( aNumber, EHex );
str.Append( KHexCharRight );
Write( str );
}
// ----------------------------------------------------------------------------
// CLogFile::LogNewline()
// Start a newline in the log file.
// ----------------------------------------------------------------------------
//
void CLogFile::LogNewline()
{
Write( KCrLf8 );
if ( iAutoTimestamp )
{
LogTimeInternal();
}
}
// ----------------------------------------------------------------------------
// CLogFile::StartWrite()
// Perform any initial operation before the main log operation.
// ----------------------------------------------------------------------------
//
void CLogFile::StartWrite()
{
ASSERT( iCheckNestDepth == 0 );
iCheckNestDepth++;
if ( iAutoNewline )
{
LogNewline();
}
}
// ----------------------------------------------------------------------------
// CLogFile::EndWrite()
// Perform any tidying up operations after the main log operation.
// ----------------------------------------------------------------------------
//
void CLogFile::EndWrite()
{
if ( iAutoFlush )
{
iLogFile.Flush();
}
iCheckNestDepth--;
ASSERT( iCheckNestDepth == 0 );
}
// ----------------------------------------------------------------------------
// CLogFile::Write()
// Do the actual writing, and associated error checking.
// ----------------------------------------------------------------------------
//
void CLogFile::Write( const TDesC8& aText )
{
if ( iLogFile.Write( aText ) != KErrNone )
{
// As the framework may be trapping User::Panic we need to
// produce the panic at a lower level.
RThread().Panic( KLogFilePanic, TLogFileWriteFailed );
}
}
// ----------------------------------------------------------------------------
// CLogFile::SetAutoFlush()
// Set AutoFlush on.
// ----------------------------------------------------------------------------
//
void CLogFile::SetAutoFlush( TBool aOn )
{
iAutoFlush = aOn;
}
// ----------------------------------------------------------------------------
// CLogFile::SetAutoTimeStamp()
// Set AutoTimeStamp on.
// ----------------------------------------------------------------------------
//
void CLogFile::SetAutoTimeStamp( TBool aOn )
{
iAutoTimestamp = aOn;
}
// ----------------------------------------------------------------------------
// CLogFile::SetAutoNewline()
// Set AutoNewline on.
// ----------------------------------------------------------------------------
//
void CLogFile::SetAutoNewline( TBool aOn )
{
iAutoNewline = aOn;
}
// ----------------------------------------------------------------------------
// CLogFile::StaticLogL()
// Static option to append text to the log file.
// ----------------------------------------------------------------------------
//
void CLogFile::StaticLogL( const TDesC& aFileName, const TDesC8& aText )
{
CLogFile* logFile = NewLC( aFileName, EFalse );
logFile->Log( aText );
CleanupStack::Pop( logFile );
delete logFile;
}
// ----------------------------------------------------------------------------
// CLogFile::StaticLogL()
// Static option to append text to the log file.
// ----------------------------------------------------------------------------
//
void CLogFile::StaticLogL( const TDesC& aFileName, const TDesC& aText )
{
CLogFile* logFile = NewLC( aFileName, EFalse );
logFile->Log( aText );
CleanupStack::Pop( logFile );
delete logFile;
}
// End of File