videoeditorengine/audioeditorengine/util/src/Logfile.cpp
author Mikael Laine <mikael.laine@ixonos.com>
Fri, 29 Jan 2010 14:08:33 +0200
changeset 0 951a5db380a0
permissions -rw-r--r--
Committing the Video Editor package under the Eclipse Public License

/*
* Copyright (c) 2010 Ixonos Plc.
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the "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:
* Ixonos Plc
*
* Description:  
*
*/


#include <hal.h>
#include <charconv.h>
#include "logfile.h"
#include "logfilepanics.h"

_LIT8(KCrLf8, "\r\n");
_LIT(KCrLf, "\r\n");

const TInt KAsciiStart = 0x20;
const TInt KAsciiEnd = 0x7f;
const TInt KHexCharLeft = '<';
const TInt KHexCharRight = '>';

const TInt KNumberOfDecimalPlaces = 3;

CLogFile* CLogFile::NewL(const TDesC& aFileName, TBool aInitialiseLog)
    {
    CLogFile* self = NewLC(aFileName, aInitialiseLog);
    CleanupStack::Pop();
    return(self);
    }


CLogFile* CLogFile::NewLC(const TDesC& aFileName, TBool aInitialiseLog)
    {
    CLogFile* self = new (ELeave) CLogFile();
    CleanupStack::PushL(self);
    self->ConstructL(aFileName, aInitialiseLog);
    return(self);
    }


CLogFile::CLogFile()
    {
    // No implementation required
    }


CLogFile::~CLogFile()
    {
    iLogFile.Flush();
    iLogFile.Close();
    iSession.Close();

    delete iCharacterConverter;
    iCharacterConverter = NULL;
    }


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;
        }


    User::LeaveIfError(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);
    }


void CLogFile::LogTime()
    {
    StartWrite();
    LogTimeInternal();
    EndWrite();
    }


void CLogFile::Log(const TDesC8& aText)
    {
    StartWrite();
    LogTextInternal(aText);
    EndWrite();
    }


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();
    }


void CLogFile::Log(TUint8 aByte)
    {
    StartWrite();
    LogByteInternal(aByte);
    EndWrite();        
    }


void CLogFile::Log(TUint aNumber)
    {
    StartWrite();
    LogIntInternal(aNumber);
    EndWrite();        
    }


void CLogFile::LogBytes(const TDesC8& aBuffer, TBool fastWrite)
    {
    StartWrite();

    if(fastWrite)
      Write(aBuffer);
    else
    {
      for (TInt i = 0; i < aBuffer.Length(); i++)
      {
        LogByteInternal(aBuffer[i], ETrue);
      }
    }

    EndWrite();
    }


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);
    }


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);

    }


void CLogFile::LogByteInternal(TUint8 aByte, TBool acsiiMode)
    {
    if ((aByte >= KAsciiStart) && (aByte < KAsciiEnd) || acsiiMode)
        {
        // 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(static_cast<TUint>(aByte), EHex);
        str.Append(KHexCharRight);
        Write(str);
        }
    }


void CLogFile::LogIntInternal(TUint aNumber)
    {
    // Display as ASCII char
    TBuf8<20> str;
    str.Append(KHexCharLeft);
    str.AppendNum(aNumber/*, EHex*/);
    str.Append(KHexCharRight);
    Write(str);
    }


void CLogFile::LogNewline()
    {
    Write(KCrLf8);

    if (iAutoTimestamp)
        {
        LogTimeInternal();
        }
    }


void CLogFile::StartWrite()
    {
    ASSERT(iCheckNestDepth == 0);
    iCheckNestDepth++;

    if (iAutoNewline)
        {
        LogNewline();
        }
    }


void CLogFile::EndWrite()
    {
    if (iAutoFlush)
        {
        iLogFile.Flush();
        }

    iCheckNestDepth--;
    ASSERT(iCheckNestDepth == 0);
    }

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);
        }
    }

void CLogFile::SetAutoFlush(TBool aOn)
    {
    iAutoFlush = aOn;
    }


void CLogFile::SetAutoTimeStamp(TBool aOn)
    {
    iAutoTimestamp = aOn;
    }


void CLogFile::SetAutoNewline(TBool aOn)
    {
    iAutoNewline = aOn;
    }


void CLogFile::StaticLogL(const TDesC& aFileName, const TDesC8& aText)
    {
    CLogFile* logFile = NewLC(aFileName, EFalse);
    logFile->Log(aText);
    CleanupStack::Pop(logFile);
    delete logFile;
    }


void CLogFile::StaticLogL(const TDesC& aFileName, const TDesC& aText)
    {
    CLogFile* logFile = NewLC(aFileName, EFalse);
    logFile->Log(aText);
    CleanupStack::Pop(logFile);
    delete logFile;
    }