stif/Logger/src/FileOutput.cpp
branchRCL_3
changeset 59 8ad140f3dd41
equal deleted inserted replaced
49:7fdc9a71d314 59:8ad140f3dd41
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 * 
       
    14 * Description: This module contains implementation of CFileOutput 
       
    15 * class member functions.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include "FileOutput.h"
       
    22 
       
    23 // EXTERNAL DATA STRUCTURES
       
    24 // None
       
    25 
       
    26 // EXTERNAL FUNCTION PROTOTYPES  
       
    27 // None
       
    28 
       
    29 // CONSTANTS
       
    30 // None
       
    31 
       
    32 // MACROS
       
    33 // None
       
    34 //#define RDEBUG_FILEWRITECRASH(a) RDebug::Print(a)
       
    35 #define RDEBUG_FILEWRITECRASH(a)
       
    36 
       
    37 // LOCAL CONSTANTS AND MACROS
       
    38 // None
       
    39 
       
    40 // MODULE DATA STRUCTURES
       
    41 // None
       
    42 
       
    43 // LOCAL FUNCTION PROTOTYPES
       
    44 // None
       
    45 
       
    46 // FORWARD DECLARATIONS
       
    47 // None
       
    48 
       
    49 // ==================== LOCAL FUNCTIONS =======================================
       
    50 // None
       
    51 
       
    52 // ================= MEMBER FUNCTIONS =========================================
       
    53 
       
    54 /*
       
    55 -------------------------------------------------------------------------------
       
    56 
       
    57     Class: CFileOutput
       
    58 
       
    59     Method: CFileOutput
       
    60 
       
    61     Description: Default constructor
       
    62 
       
    63     C++ default constructor can NOT contain any code, that
       
    64     might leave.
       
    65 
       
    66     Parameters: TLoggerType aLoggerType: in: File type
       
    67                 TBool aWithTimeStamp: in: For timestamp
       
    68                 TBool aWithLineBreak: in: For line break
       
    69                 TBool aWithEventRanking: in: For events ranking to file
       
    70                 TBool aThreadIdToLogFile: in: Indicator to thread id adding to
       
    71                                               end of the log file
       
    72 
       
    73     Return Values: None
       
    74 
       
    75     Errors/Exceptions: None
       
    76 
       
    77     Status: Approved
       
    78 
       
    79 -------------------------------------------------------------------------------
       
    80 */
       
    81 CFileOutput::CFileOutput( CStifLogger::TLoggerType aLoggerType,
       
    82                             TBool aWithTimeStamp,
       
    83                             TBool aWithLineBreak,
       
    84                             TBool aWithEventRanking,
       
    85                             TBool aThreadIdToLogFile ) :
       
    86     COutput()
       
    87     {
       
    88     // Indicates file type
       
    89     iLoggerType = aLoggerType;
       
    90 
       
    91     // Time stamp indicator
       
    92     iWithTimeStamp = aWithTimeStamp;
       
    93 
       
    94     // Line break indicator
       
    95     iWithLineBreak = aWithLineBreak;
       
    96 
       
    97     // Log event ranking indicator
       
    98     iWithEventRanking = aWithEventRanking;
       
    99 
       
   100     // Indicator to thread id adding to end of the log file
       
   101     iThreadIdToLogFile = aThreadIdToLogFile;
       
   102 
       
   103     // Is file open indicator
       
   104     iIsFileOpen = 0;
       
   105 
       
   106     }
       
   107 
       
   108 /*
       
   109 -------------------------------------------------------------------------------
       
   110 
       
   111     Class: CFileOutput
       
   112 
       
   113     Method: ConstructL
       
   114 
       
   115     Description: Symbian OS second phase constructor
       
   116 
       
   117     Symbian OS default constructor can leave.
       
   118 
       
   119     Parameters: const TDesC& aTestPath: in: Log path
       
   120                 const TDesC& aTestFile: in: Log filename
       
   121                 TBool aOverWrite: in: For file overwrite
       
   122                 TBool aCreateLogDir: in: Indicator to directory creation
       
   123                 TInt  aStaticBufferSize
       
   124                 TBool aUnicode: in: Indicator if file has to be in unicode format
       
   125 
       
   126     Return Values: None
       
   127 
       
   128     Errors/Exceptions:  Leaves if called CreateNewFileL method fails
       
   129                         Leaves if called OpenExistingFileL method fails
       
   130 
       
   131     Status: Proposal
       
   132 
       
   133 -------------------------------------------------------------------------------
       
   134 */
       
   135 void CFileOutput::ConstructL( const TDesC& aTestPath,
       
   136                                 const TDesC& aTestFile,
       
   137                                 TBool aOverWrite,
       
   138                                 TBool aCreateLogDir,
       
   139                                 TInt aStaticBufferSize,
       
   140                                 TBool aUnicode)
       
   141     {
       
   142     iUnicode = aUnicode;
       
   143 
       
   144     // Open file session
       
   145     User::LeaveIfError( iFileSession.Connect() );
       
   146 
       
   147     // Create a log directory
       
   148     if( aCreateLogDir )
       
   149         {
       
   150         CreateDirectoryL( aTestPath );
       
   151         }
       
   152 
       
   153     // Create a new file
       
   154     if ( aOverWrite )
       
   155         {
       
   156         CreateNewFileL( aTestPath, aTestFile );
       
   157         }
       
   158     // Open an existing file
       
   159     else 
       
   160         {
       
   161         OpenExistingFileL( aTestPath, aTestFile );
       
   162         }
       
   163         
       
   164     if( aStaticBufferSize != 0)
       
   165         {
       
   166         iDataHBuf8 = HBufC8::NewL( aStaticBufferSize );
       
   167         iDataHBuf16 = HBufC::NewL(aStaticBufferSize);
       
   168         iStaticBufferSize = aStaticBufferSize;
       
   169         }
       
   170     }
       
   171 
       
   172 /*
       
   173 -------------------------------------------------------------------------------
       
   174 
       
   175     Class: CFileOutput
       
   176 
       
   177     Method: NewL
       
   178 
       
   179     Description: Two-phased constructor.
       
   180 
       
   181     Parameters: const TDesC& aTestPath: in: Log path
       
   182                 const TDesC& aTestFile: in: Log filename
       
   183                 TLoggerType aLoggerType: in: File type
       
   184                 TBool aOverWrite: in: For file overwrite
       
   185                 TBool aWithTimeStamp: in: For timestamp
       
   186                 TBool aWithLineBreak: in: For line break
       
   187                 TBool aWithEventRanking: in: For events ranking to file
       
   188                 TBool aThreadIdToLogFile: in: Indicator to thread id adding to
       
   189                                               end of the log file
       
   190                 TBool aCreateLogDir: in: Indicator to directory creation
       
   191                 TInt  aStaticBufferSize
       
   192                 TBool aUnicode: in: Indicator if file has to be in unicode format
       
   193 
       
   194     Return Values: CFileOutput*: pointer to CFileOutput object
       
   195 
       
   196     Errors/Exceptions: Leaves if ConstructL leaves
       
   197 
       
   198     Status: Proposal
       
   199 
       
   200 -------------------------------------------------------------------------------
       
   201 */
       
   202 CFileOutput* CFileOutput::NewL( const TDesC& aTestPath,
       
   203                                 const TDesC& aTestFile,
       
   204                                 CStifLogger::TLoggerType aLoggerType,
       
   205                                 TBool aOverWrite,
       
   206                                 TBool aWithTimeStamp,
       
   207                                 TBool aWithLineBreak,
       
   208                                 TBool aWithEventRanking,
       
   209                                 TBool aThreadIdToLogFile,
       
   210                                 TBool aCreateLogDir,
       
   211                                 TInt  aStaticBufferSize,
       
   212                                 TBool aUnicode )
       
   213     {
       
   214     // Create CFileOutput object fileWriter
       
   215     CFileOutput* fileWriter = new (ELeave) CFileOutput( aLoggerType,
       
   216                                                         aWithTimeStamp,
       
   217                                                         aWithLineBreak,
       
   218                                                         aWithEventRanking,
       
   219                                                         aThreadIdToLogFile );
       
   220 
       
   221     CleanupStack::PushL( fileWriter );
       
   222     fileWriter->ConstructL( aTestPath, aTestFile, aOverWrite, aCreateLogDir, aStaticBufferSize,
       
   223                             aUnicode );
       
   224     CleanupStack::Pop( fileWriter );
       
   225 
       
   226     return fileWriter;
       
   227 
       
   228     }
       
   229 
       
   230 /*
       
   231 -------------------------------------------------------------------------------
       
   232 
       
   233     Class: CFileOutput
       
   234 
       
   235     Method: ~CFileOutput
       
   236 
       
   237     Description: Destructor
       
   238 
       
   239     Parameters: None
       
   240 
       
   241     Return Values: None
       
   242 
       
   243     Errors/Exceptions: None
       
   244 
       
   245     Status: Approved
       
   246 
       
   247 -------------------------------------------------------------------------------
       
   248 */
       
   249 CFileOutput::~CFileOutput()
       
   250     {
       
   251     // Close file
       
   252     iFile.Close();
       
   253     // Close file session
       
   254     iFileSession.Close();
       
   255 
       
   256     delete iDataHBuf8;
       
   257     delete iDataHBuf16;
       
   258     }
       
   259 
       
   260 /*
       
   261 -------------------------------------------------------------------------------
       
   262 
       
   263     Class: CFileOutput
       
   264 
       
   265     Method: FileType
       
   266 
       
   267     Description: Check file type.
       
   268 
       
   269     Check is file type set with a aTestFile's name. If file type is not set
       
   270     the type will set according to StifLogger's type.
       
   271 
       
   272     Parameters: const TDesC& aTestFile: in: Log filename
       
   273                 TFileType& fileType: inout: Generated file type
       
   274 
       
   275     Return Values: None
       
   276 
       
   277     Errors/Exceptions: None
       
   278 
       
   279     Status: Approved
       
   280 
       
   281 -------------------------------------------------------------------------------
       
   282 */    
       
   283 void CFileOutput::FileType( const TDesC& aTestFile,
       
   284                             TFileType& aFileType )
       
   285     {
       
   286     TBool fileTypeIsSet( EFalse ); // File type indicator
       
   287 
       
   288     // Check is file type set to aTestFile parameter
       
   289     TInt ret = aTestFile.Find( _L( "." ) );
       
   290     if( ret != KErrNotFound )
       
   291         {
       
   292         fileTypeIsSet = ETrue;
       
   293         }
       
   294     // If not, add thread id name if allowed
       
   295     else if ( iThreadIdToLogFile )
       
   296         {
       
   297         // Thread id maximum length is 8 in hexadesimal format
       
   298         // Construct unique thread name
       
   299         aFileType.Append( _L("_") );
       
   300         RThread threadHandle;                   // A handle to a thread
       
   301         TThreadId id = threadHandle.Id();       // Encapsulates the 
       
   302                                                 // Id of a thread
       
   303         // Appends id in hexadesimal format             
       
   304         aFileType.AppendFormat( _L( "%x" ), (TInt)id );
       
   305         }
       
   306 
       
   307     // Add file type after the thread id name
       
   308     if ( iLoggerType == CStifLogger::ETxt && !fileTypeIsSet )
       
   309         {
       
   310         // ".txt"
       
   311         aFileType.Append( _L( "." ) );
       
   312         aFileType.Append( _L( "txt" ) );
       
   313         }
       
   314     else if ( iLoggerType == CStifLogger::EHtml && !fileTypeIsSet )
       
   315         {
       
   316         // ".html"
       
   317         aFileType.Append( _L( "." ) );
       
   318         aFileType.Append( _L( "html" ) );
       
   319         }
       
   320     // EData file type comes from the aTestFile name. If not the file type 
       
   321     // will be empty
       
   322     else if ( iLoggerType == CStifLogger::EData )
       
   323         {
       
   324         aFileType.Append( _L( "" ) );
       
   325         }
       
   326     else
       
   327         {
       
   328         aFileType.Append( _L( "" ) );
       
   329         }
       
   330 
       
   331     }
       
   332 
       
   333 /*
       
   334 -------------------------------------------------------------------------------
       
   335 
       
   336     Class: CFileOutput
       
   337 
       
   338     Method: TestFileWithThreadId
       
   339 
       
   340     Description: Generate thread id
       
   341 
       
   342     Generate thread id name between the test file name and test file type.
       
   343 
       
   344     Parameters: TDesC& aTestFile: in: Test file name
       
   345                 TFileName& aNewTestFile: inout: Generated test file name 
       
   346 
       
   347     Return Values: None
       
   348 
       
   349     Errors/Exceptions: None
       
   350 
       
   351     Status: Approved
       
   352 
       
   353 -------------------------------------------------------------------------------
       
   354 */
       
   355 void CFileOutput::TestFileWithThreadId( const TDesC& aTestFile, 
       
   356                                         TFileName& aNewTestFile )
       
   357     {
       
   358     for( TInt a = 0; a < aTestFile.Length(); a++ )
       
   359         {
       
   360         // Find a dot
       
   361         if( aTestFile[a] == '.' )
       
   362             {
       
   363             TPtrC parsedFileType = aTestFile.Mid( a );  // Take rest of the 
       
   364                                                         // aTestFile
       
   365             aNewTestFile.Append( _L( "_" ) );
       
   366             RThread threadHandle;                       // A handle to a thread
       
   367             TThreadId id = threadHandle.Id();           // Encapsulates the 
       
   368                                                         // Id of a thread
       
   369             aNewTestFile.AppendFormat( _L( "%x" ), (TInt)id );// Appends id in
       
   370                                                         // hexadesimal format
       
   371             aNewTestFile.Append( parsedFileType );
       
   372             break;
       
   373             }
       
   374         // Dot not found yet
       
   375         else
       
   376             {
       
   377             aNewTestFile.Append( aTestFile[a] );
       
   378             }
       
   379         }
       
   380 
       
   381     }
       
   382 
       
   383 /*
       
   384 -------------------------------------------------------------------------------
       
   385 
       
   386     Class: CFileOutput
       
   387 
       
   388     Method: CreateDirectoryL
       
   389 
       
   390     Description: Create a log directory.
       
   391 
       
   392     Method creates directory if not allready exist.
       
   393 
       
   394     Parameters: const TDesC& aTestPath: in: Test path definition
       
   395 
       
   396     Return Values: None
       
   397 
       
   398     Errors/Exceptions: Leaves if directory creation fails
       
   399 
       
   400     Status: Proposal
       
   401 
       
   402 -------------------------------------------------------------------------------
       
   403 */
       
   404 void CFileOutput::CreateDirectoryL( const TDesC& aTestPath )
       
   405     {
       
   406     __TRACE( KInfo, ( _L( "STIFLOGGER: Create a directory" ) ) );
       
   407 
       
   408     TInt ret = iFileSession.MkDirAll( aTestPath );
       
   409 	if( ret != KErrNone && ret != KErrAlreadyExists )
       
   410         {
       
   411         __TRACE( KError, 
       
   412             ( _L( "STIFLOGGER: Directory creation fails with error: %d" ), ret ) );
       
   413 		User::Leave( ret );
       
   414         }
       
   415 
       
   416     }
       
   417 
       
   418 /*
       
   419 -------------------------------------------------------------------------------
       
   420 
       
   421     Class: CFileOutput
       
   422 
       
   423     Method: OpenExistingFileL
       
   424 
       
   425     Description: Open an existing file.
       
   426 
       
   427     Method is used when is need for log new information after the existing
       
   428     log file.
       
   429 
       
   430     Parameters: const TDesC& aTestPath: in: Test path definition
       
   431                 const TDesC& aTestFile: in: Test file name
       
   432 
       
   433     Return Values: None
       
   434 
       
   435     Errors/Exceptions:  Leaves if path or file lengths are over KMaxFileName
       
   436                         Leaves if file Replace method fails
       
   437                         Leaves if file Open method fails
       
   438                         Leaves if file path not found
       
   439 
       
   440     Status: Proposal
       
   441 
       
   442 -------------------------------------------------------------------------------
       
   443 */
       
   444 void CFileOutput::OpenExistingFileL( const TDesC& aTestPath, 
       
   445                                         const TDesC& aTestFile )
       
   446     {
       
   447     __TRACE( KInfo, ( _L( "STIFLOGGER: Opening an existing file for logging" ) ) );
       
   448 
       
   449     // If path and file name lengths are over KMaxFileName(TFileName)
       
   450     __ASSERT_ALWAYS(
       
   451         ( aTestPath.Length() + aTestFile.Length() ) < KMaxFileName,
       
   452         User::Leave( KErrArgument ) );
       
   453 
       
   454     // Check file type and generate threat id name
       
   455     TFileType fileType;
       
   456     FileType( aTestFile, fileType );
       
   457 
       
   458     // File directory name, file name and file type definitions
       
   459     TPtrC dirNamePrt( aTestPath );
       
   460     iFileAndDirName.Copy( dirNamePrt );
       
   461 
       
   462     TInt isDotFound = aTestFile.Find( _L( "." ) );
       
   463     // If dot is found and iThreadIdToLogFile is true
       
   464     if( isDotFound != KErrNotFound && iThreadIdToLogFile )
       
   465         {
       
   466         TFileName testFileWithThreadId;
       
   467         // Generate thread id name
       
   468         TestFileWithThreadId( aTestFile, testFileWithThreadId );
       
   469         iFileAndDirName.Insert( 
       
   470             iFileAndDirName.Length(), testFileWithThreadId );
       
   471         }
       
   472     else
       
   473         {
       
   474         TPtrC txtPrt( fileType );
       
   475         iFileAndDirName.Insert( iFileAndDirName.Length(), aTestFile );
       
   476         iFileAndDirName.Insert( iFileAndDirName.Length(), txtPrt );
       
   477         }
       
   478 
       
   479 //  TBool isOpen( EFalse );
       
   480     TInt ret( KErrNone );
       
   481 
       
   482   
       
   483     iIsFileOpen=iFile.Open( iFileSession, iFileAndDirName,
       
   484             EFileWrite | EFileStreamText |
       
   485                     EFileShareAny );
       
   486     if( iIsFileOpen == KErrNotFound )
       
   487         {
       
   488         ret =  iFile.Create( iFileSession, iFileAndDirName, 
       
   489                                     EFileWrite | EFileStreamText |
       
   490                                     EFileShareAny );
       
   491         if(iUnicode && ret == KErrNone)
       
   492             {
       
   493             char FF = 0xFF;
       
   494             char FE = 0xFE;
       
   495             TBuf8<2> beg;
       
   496             beg.Append(FF);
       
   497             beg.Append(FE);
       
   498             if(iFile.Write(beg) == KErrNone)
       
   499                 iFile.Flush();
       
   500             }
       
   501         }
       
   502     else if( iIsFileOpen == KErrNone )
       
   503         {
       
   504       
       
   505         ret=KErrNone;
       
   506         }
       
   507     // Probably path not found
       
   508     else
       
   509         {
       
   510         User::Leave( iIsFileOpen );
       
   511         }
       
   512 
       
   513     if ( ret != KErrNone )
       
   514         {
       
   515         User::Leave( ret );
       
   516         }
       
   517 
       
   518     }
       
   519 
       
   520 /*
       
   521 -------------------------------------------------------------------------------
       
   522 
       
   523     Class: CFileOutput
       
   524 
       
   525     Method: CreateNewFileL
       
   526 
       
   527     Description: Create a new file.
       
   528 
       
   529     Method creates new file to the log information.
       
   530 
       
   531     Parameters: const TDesC& aTestPath: in: Test path definition
       
   532                 const TDesC& aTestFile: in: Test file name
       
   533 
       
   534     Return Values: None
       
   535 
       
   536     Errors/Exceptions:  Leaves if path or file lengths are over KMaxFileName
       
   537                         Leaves if file server Connect method fails
       
   538                         Leaves if file Replace method fails
       
   539                         Leaves if file Open method fails
       
   540                         Leaves if file path not found
       
   541 
       
   542     Status: Proposal
       
   543 
       
   544 -------------------------------------------------------------------------------
       
   545 */
       
   546 void CFileOutput::CreateNewFileL( const TDesC& aTestPath,
       
   547                                     const TDesC& aTestFile )
       
   548     {
       
   549     __TRACE( KInfo, ( _L( "STIFLOGGER: Create a new file for logging" ) ) );
       
   550 
       
   551     // If path and file name lengths are over KMaxFileName(TFileName)
       
   552     __ASSERT_ALWAYS(
       
   553         ( aTestPath.Length() + aTestFile.Length() ) < KMaxFileName,
       
   554         User::Leave( KErrArgument ) );
       
   555 
       
   556     // Check file type and generate threat id name
       
   557     TFileType fileType;
       
   558     FileType( aTestFile, fileType );
       
   559 
       
   560     // File directory name, file name and file type definitions
       
   561     TPtrC dirNamePrt( aTestPath );
       
   562     iFileAndDirName.Copy( dirNamePrt );
       
   563 
       
   564     TInt isDotFound = aTestFile.Find( _L( "." ) );
       
   565     // If dot is found and iThreadIdToLogFile is true
       
   566     if( isDotFound != KErrNotFound && iThreadIdToLogFile )
       
   567         {
       
   568         TFileName testFileWithThreadId;
       
   569         // Generate thread id name
       
   570         TestFileWithThreadId( aTestFile, testFileWithThreadId );
       
   571         iFileAndDirName.Insert( 
       
   572             iFileAndDirName.Length(), testFileWithThreadId );
       
   573         }
       
   574     else
       
   575         {
       
   576         TPtrC txtPrt( fileType );
       
   577         iFileAndDirName.Insert( iFileAndDirName.Length(), aTestFile );
       
   578         iFileAndDirName.Insert( iFileAndDirName.Length(), txtPrt );
       
   579         }
       
   580 
       
   581     // Delete file if exist
       
   582     iFileSession.Delete( iFileAndDirName );
       
   583 
       
   584     TBool isOpen( EFalse );
       
   585     TInt ret( KErrNone );
       
   586 
       
   587     iIsFileOpen = iFileSession.IsFileOpen( iFileAndDirName, isOpen );
       
   588     if( ( iIsFileOpen == KErrNotFound ) ||
       
   589         ( iIsFileOpen == KErrNone ) )
       
   590         {
       
   591         ret = iFile.Replace( iFileSession, iFileAndDirName,
       
   592                                     EFileWrite | EFileStreamText |
       
   593                                     EFileShareAny );
       
   594         if(iUnicode && ret == KErrNone)
       
   595             {
       
   596             char FF = 0xFF;
       
   597             char FE = 0xFE;
       
   598             TBuf8<2> beg;
       
   599             beg.Append(FF);
       
   600             beg.Append(FE);
       
   601             if(iFile.Write(beg) == KErrNone)
       
   602                 iFile.Flush();
       
   603             }
       
   604         }
       
   605     // Probably path not found
       
   606     else
       
   607         {
       
   608         User::Leave( iIsFileOpen );
       
   609         }
       
   610 
       
   611     if ( ret != KErrNone )
       
   612         {
       
   613         User::Leave( ret );
       
   614         }
       
   615 
       
   616     }
       
   617 
       
   618 /*
       
   619 -------------------------------------------------------------------------------
       
   620 
       
   621     Class: CFileOutput
       
   622 
       
   623     Method: Write
       
   624 
       
   625     Description: Write log information or data to the file. 16 bit.
       
   626 
       
   627     Parameters: TBool aWithTimeStamp: in: Is time stamp flag used
       
   628                 TBool aWithLineBreak: in: Is line break flag used
       
   629                 TBool aWithEventRanking: in: Is event ranking flag used
       
   630                 const TDesC& aData: in: Logged or saved data
       
   631 
       
   632     Return Values: TInt: Symbian error code.
       
   633 
       
   634     Errors/Exceptions: None
       
   635 
       
   636     Status: Approved
       
   637 
       
   638 -------------------------------------------------------------------------------
       
   639 */
       
   640 TInt CFileOutput::Write( TBool aWithTimeStamp, TBool aWithLineBreak,
       
   641                             TBool aWithEventRanking, const TDesC& aData )
       
   642     {
       
   643     TInt extraLength( 0 );  // Line and/or event required length
       
   644 
       
   645     TPtr data16(0, 0);
       
   646     TPtr8 data8(0, 0);
       
   647 
       
   648     // Extra space calculation
       
   649     if( iWithEventRanking && aWithEventRanking )
       
   650         {
       
   651         extraLength = extraLength + KMaxEventRanking + KMaxSpace;
       
   652         }
       
   653     if( ( iLoggerType == CStifLogger::EHtml ) && iWithLineBreak && aWithLineBreak )
       
   654         {
       
   655         extraLength = extraLength + KMaxHtmlLineBreak;
       
   656         }
       
   657     if( iWithLineBreak && aWithLineBreak )
       
   658         {
       
   659         extraLength = extraLength + KMaxLineBreak;
       
   660         }
       
   661     if( aWithTimeStamp && iWithTimeStamp )
       
   662         {
       
   663         extraLength = extraLength + KMaxTimeStamp;
       
   664         }
       
   665 
       
   666     // Calculated space
       
   667     TInt space = aData.Length();
       
   668 
       
   669     HBufC8* dataHBuf8 = NULL;
       
   670     HBufC16* dataHBuf16 = NULL;
       
   671 
       
   672     if( iDataHBuf8 != NULL )
       
   673         {
       
   674         // We'll use HBufC created in ConstructL
       
   675         data8.Set(iDataHBuf8->Des());
       
   676         data16.Set(iDataHBuf16->Des());
       
   677         data16.Copy(_L("")); // Initialize aData buffer
       
   678         
       
   679         if( (aData.Length() + extraLength) > iStaticBufferSize )
       
   680             {
       
   681              RDebug::Print(_L("Warning: buffer size too small, not able to log!"));
       
   682              return KErrOverflow;
       
   683             }        
       
   684         }
       
   685     else
       
   686         {        
       
   687         // We'll create a local HBufC, deleting it in the end of this method
       
   688         dataHBuf8 = HBufC8::New( space + extraLength );
       
   689         if( dataHBuf8 == NULL )
       
   690             {
       
   691             return KErrNoMemory;
       
   692             }
       
   693         dataHBuf16 = HBufC16::New(space + extraLength);
       
   694         if(dataHBuf16 == NULL)
       
   695             {
       
   696             delete dataHBuf8;
       
   697             return KErrNoMemory;
       
   698             }
       
   699         data8.Set(dataHBuf8->Des());
       
   700         data16.Set(dataHBuf16->Des());
       
   701         }
       
   702 
       
   703     // Event ranking
       
   704     if( iWithEventRanking && aWithEventRanking && !iWithTimeStamp )
       
   705         {
       
   706         EventRanking( data16 );      // Event ranking to data
       
   707         data16.Append( aData );      // Unicode aData to normal text
       
   708         }
       
   709     // Time stamp
       
   710     else if( iWithTimeStamp && aWithTimeStamp )
       
   711         {
       
   712         // With event ranking
       
   713         if( iWithEventRanking && aWithEventRanking )
       
   714             {
       
   715             EventRanking( data16 );  // Event ranking to data
       
   716             }
       
   717         AddTimeStampToData( data16 );// Add time stamp
       
   718         data16.Append( aData );      // Unicode aData to normal text
       
   719         }
       
   720     else
       
   721         {
       
   722         data16.Copy( aData );        // Unicode aData to normal text
       
   723         }
       
   724 
       
   725     // NOTE: If need some special line break do it with logging phase
       
   726 
       
   727     // If html logging and line break is used add the line break.
       
   728     if (( iLoggerType == CStifLogger::EHtml ) && iWithLineBreak && aWithLineBreak )
       
   729         {
       
   730         data16.Append( _L( "<BR>" ) );
       
   731         data16.Append( _L( "\n" ) );  // To make html file more readable
       
   732                                     // with text editor
       
   733         }
       
   734 
       
   735     // Other cases line break is normal '\n' if logging is used
       
   736     else if( iWithLineBreak && aWithLineBreak )
       
   737         {
       
   738         data16.Append( 0x0D ); // 13 or '\' in Symbian OS
       
   739         data16.Append( 0x0A ); // 10 or 'n' in Symbian OS
       
   740         }
       
   741 
       
   742     // Write the data to file
       
   743     TInt tmp = 0;
       
   744     if( iFile.Seek( ESeekEnd, tmp ) == KErrNone )
       
   745         {
       
   746         RDEBUG_FILEWRITECRASH(_L("iFile.Write 1 in"));
       
   747         TPtrC8 dataToFile(0, 0);
       
   748         if(iUnicode)
       
   749             {
       
   750             dataToFile.Set((TUint8 *)(data16.Ptr()), data16.Length() * 2);
       
   751             }
       
   752         else
       
   753             {
       
   754             data8.Copy(data16);
       
   755             dataToFile.Set(data8);
       
   756             }
       
   757         if(iFile.Write(dataToFile) == KErrNone)
       
   758             iFile.Flush();
       
   759         RDEBUG_FILEWRITECRASH(_L("iFile.Write 1 out"));
       
   760         }
       
   761     if( iDataHBuf8 == NULL )
       
   762         {
       
   763         delete dataHBuf8;
       
   764         dataHBuf8 = 0;
       
   765         delete dataHBuf16;
       
   766         dataHBuf16 = 0;
       
   767         }
       
   768 
       
   769     return KErrNone;
       
   770 
       
   771     }
       
   772 
       
   773 /*
       
   774 -------------------------------------------------------------------------------
       
   775 
       
   776     Class: CFileOutput
       
   777 
       
   778     Method: Write
       
   779 
       
   780     Description: Write log information or data to the file. 8 bit.
       
   781 
       
   782     Parameters: TBool aWithTimeStamp: in: Is time stamp flag used
       
   783                 TBool aWithLineBreak: in: Is line break flag used
       
   784                 TBool aWithEventRanking: in: Is event ranking flag used
       
   785                 const TDesC8& aData: in: Logged or saved data
       
   786 
       
   787     Return Values: TInt: Symbian error code.
       
   788 
       
   789     Errors/Exceptions: None
       
   790 
       
   791     Status: Approved
       
   792 
       
   793 -------------------------------------------------------------------------------
       
   794 */
       
   795 TInt CFileOutput::Write( TBool aWithTimeStamp, TBool aWithLineBreak,
       
   796                             TBool aWithEventRanking, const TDesC8& aData )
       
   797     {
       
   798     TInt extraLength( 0 );  // Line and/or event required length
       
   799 
       
   800     TPtr data16(0, 0);
       
   801     TPtr8 data8(0, 0);
       
   802 
       
   803     // Extra space calculation
       
   804     if( iWithEventRanking && aWithEventRanking )
       
   805         {
       
   806         extraLength = extraLength + KMaxEventRanking + KMaxSpace;
       
   807         }
       
   808     if( ( iLoggerType == CStifLogger::EHtml ) && iWithLineBreak && aWithLineBreak )
       
   809         {
       
   810         extraLength = extraLength + KMaxHtmlLineBreak;
       
   811         }
       
   812     if( iWithLineBreak && aWithLineBreak )
       
   813         {
       
   814         extraLength = extraLength + KMaxLineBreak;
       
   815         }
       
   816     if( aWithTimeStamp && iWithTimeStamp )
       
   817         {
       
   818         extraLength = extraLength + KMaxTimeStamp;
       
   819         }
       
   820 
       
   821     // aData straight to the file
       
   822     if ( extraLength == 0 && !iUnicode)
       
   823         {
       
   824         // Write the data to file
       
   825         TInt tmp = 0;
       
   826         if( iFile.Seek( ESeekEnd, tmp ) == KErrNone )
       
   827             {
       
   828             RDEBUG_FILEWRITECRASH(_L("iFile.Write 2 in"));
       
   829             if( iFile.Write( aData ) == KErrNone )
       
   830                 iFile.Flush();
       
   831             RDEBUG_FILEWRITECRASH(_L("iFile.Write 2 out"));
       
   832             }
       
   833         return KErrNone;
       
   834         }
       
   835 
       
   836     // Calculated space
       
   837     TInt space = aData.Length();
       
   838     HBufC8* dataHBuf8 = NULL;
       
   839     HBufC* dataHBuf16 = NULL;
       
   840 
       
   841     if( iDataHBuf8 != NULL )
       
   842         {
       
   843         // We'll use HBufC created in ConstructL
       
   844         data8.Set(iDataHBuf8->Des());
       
   845         data8.Copy(_L("")); // Initialize aData buffer
       
   846         data16.Set(iDataHBuf16->Des());
       
   847         
       
   848         if( (aData.Length() + extraLength) > iStaticBufferSize )
       
   849             {
       
   850              RDebug::Print(_L("Warning: buffer size too small, not able to log!"));
       
   851              return KErrOverflow;
       
   852             }        
       
   853         }
       
   854     else
       
   855         {        
       
   856         // We'll create a local HBufC, deleting it in the end of this method
       
   857         dataHBuf8 = HBufC8::New( space + extraLength );
       
   858         if( dataHBuf8 == NULL )
       
   859             {
       
   860             return KErrNoMemory;
       
   861             }
       
   862         dataHBuf16 = HBufC16::New(space + extraLength);
       
   863         if(dataHBuf16 == NULL)
       
   864             {
       
   865             delete dataHBuf8;
       
   866             return KErrNoMemory;
       
   867             }
       
   868         data8.Set(dataHBuf8->Des());  // Memory allocation for data
       
   869         data16.Set(dataHBuf16->Des());  // Memory allocation for data
       
   870         }
       
   871 
       
   872     // Event ranking
       
   873     if( iWithEventRanking && aWithEventRanking && !iWithTimeStamp )
       
   874         {
       
   875         EventRanking( data8 );      // Event ranking to data
       
   876         data8.Append( aData );      // Unicode aData to normal text
       
   877         }
       
   878     // Time stamp
       
   879     else if( iWithTimeStamp && aWithTimeStamp )
       
   880         {
       
   881         // With event ranking
       
   882         if( iWithEventRanking && aWithEventRanking )
       
   883             {
       
   884             EventRanking( data8 );  // Event ranking to data
       
   885             }
       
   886         AddTimeStampToData( data8 );// Add time stamp
       
   887         data8.Append( aData );      // Unicode aData to normal text
       
   888         }
       
   889     else
       
   890         {
       
   891         data8.Copy( aData );        // Unicode aData to normal text
       
   892         }
       
   893 
       
   894     // NOTE: If need some special line break do it with logging phase
       
   895 
       
   896     // If html logging and line break is used add the line break.
       
   897     if ( ( iLoggerType == CStifLogger::EHtml ) && iWithLineBreak && aWithLineBreak )
       
   898         {
       
   899         data8.Append( _L( "<BR>" ) );
       
   900         data8.Append( _L( "\n" ) );  // To make html file more readable
       
   901                                     // with text editor
       
   902         }
       
   903 
       
   904     // Other cases line break is normal '\n' if logging is used
       
   905     else if( iWithLineBreak && aWithLineBreak )
       
   906         {
       
   907         data8.Append( 0x0D ); // 13 or '\' in Symbian OS
       
   908         data8.Append( 0x0A ); // 10 or 'n' in Symbian OS
       
   909         }
       
   910 
       
   911     // Write the data to file
       
   912     TInt tmp = 0;
       
   913     if( iFile.Seek( ESeekEnd, tmp ) == KErrNone )
       
   914         {
       
   915         RDEBUG_FILEWRITECRASH(_L("iFile.Write 3 in"));
       
   916         TPtrC8 dataToFile(0, 0);
       
   917         if(iUnicode)
       
   918             {
       
   919             data16.Copy(data8);
       
   920             dataToFile.Set((TUint8 *)(data16.Ptr()), data16.Length() * 2);
       
   921             }
       
   922         else
       
   923             {
       
   924             dataToFile.Set(data8);
       
   925             }
       
   926         if(iFile.Write(dataToFile) == KErrNone)
       
   927             iFile.Flush();
       
   928         RDEBUG_FILEWRITECRASH(_L("iFile.Write 3 out"));
       
   929         }
       
   930     if( iDataHBuf8 == NULL )
       
   931         {
       
   932         delete dataHBuf8;
       
   933         dataHBuf8 = 0;
       
   934         delete dataHBuf16;
       
   935         dataHBuf16 = 0;
       
   936         }
       
   937 
       
   938     return KErrNone;
       
   939 
       
   940     }
       
   941 
       
   942 /*
       
   943 -------------------------------------------------------------------------------
       
   944 
       
   945     Class: CFileOutput
       
   946 
       
   947     Method: EventRanking
       
   948 
       
   949     Description: For event ranking logging.
       
   950 
       
   951     Parameters: TPtr& aData: inout: Data with event ranking
       
   952 
       
   953     Return Values: None
       
   954 
       
   955     Errors/Exceptions: None
       
   956 
       
   957     Status: Approved
       
   958 
       
   959 -------------------------------------------------------------------------------
       
   960 */
       
   961 void CFileOutput::EventRanking( TPtr& aData )
       
   962     {
       
   963     // Returns the machine's current tick count.
       
   964     TUint tick = User::TickCount();
       
   965     tick &= 0xffff;
       
   966     aData.AppendNum( tick );
       
   967     aData.Append( _L( " " ) );
       
   968     }
       
   969 
       
   970 /*
       
   971 -------------------------------------------------------------------------------
       
   972 
       
   973     Class: CFileOutput
       
   974 
       
   975     Method: EventRanking
       
   976 
       
   977     Description: For event ranking logging.
       
   978 
       
   979     Parameters: TPtr8& aData: inout: Data with event ranking
       
   980 
       
   981     Return Values: None
       
   982 
       
   983     Errors/Exceptions: None
       
   984 
       
   985     Status: Approved
       
   986 
       
   987 -------------------------------------------------------------------------------
       
   988 */
       
   989 void CFileOutput::EventRanking( TPtr8& aData )
       
   990     {
       
   991     // Returns the machine's current tick count.
       
   992     TUint tick = User::TickCount();
       
   993     tick &= 0xffff;
       
   994     aData.AppendNum( tick );
       
   995     aData.Append( _L8( " " ) );
       
   996 
       
   997     }
       
   998 
       
   999 /*
       
  1000 -------------------------------------------------------------------------------
       
  1001 
       
  1002     Class: CFileOutput
       
  1003 
       
  1004     Method: AddTimeStampToData
       
  1005 
       
  1006     Description: For date and time logging.
       
  1007 
       
  1008     Parameters: TPtr& aData: inout: Data with time stamps
       
  1009 
       
  1010     Return Values: None
       
  1011 
       
  1012     Errors/Exceptions: None
       
  1013 
       
  1014     Status: Approved
       
  1015 
       
  1016 -------------------------------------------------------------------------------
       
  1017 */
       
  1018 void CFileOutput::AddTimeStampToData( TPtr& aData )
       
  1019     {
       
  1020     TStifLoggerTimeStamp timeStamp;
       
  1021     GetDateAndTime( timeStamp );
       
  1022 
       
  1023     TStifLoggerTimeStamp8 tStamp16;
       
  1024     tStamp16.Copy(timeStamp);
       
  1025 
       
  1026     aData.Append( tStamp16 );
       
  1027     }
       
  1028 
       
  1029 /*
       
  1030 -------------------------------------------------------------------------------
       
  1031 
       
  1032     Class: CFileOutput
       
  1033 
       
  1034     Method: AddTimeStampToData
       
  1035 
       
  1036     Description: For date and time logging.
       
  1037 
       
  1038     Parameters: TPtr8& aData: inout: Data with time stamps
       
  1039 
       
  1040     Return Values: None
       
  1041 
       
  1042     Errors/Exceptions: None
       
  1043 
       
  1044     Status: Approved
       
  1045 
       
  1046 -------------------------------------------------------------------------------
       
  1047 */
       
  1048 void CFileOutput::AddTimeStampToData( TPtr8& aData )
       
  1049     {
       
  1050     TStifLoggerTimeStamp timeStamp;
       
  1051     GetDateAndTime( timeStamp );
       
  1052     aData.Append( timeStamp );
       
  1053 
       
  1054     }
       
  1055 
       
  1056 /*
       
  1057 -------------------------------------------------------------------------------
       
  1058 
       
  1059     Class: CFileOutput
       
  1060 
       
  1061     Method: GetDateAndTime
       
  1062 
       
  1063     Description: For date and time logging.
       
  1064 
       
  1065     Parameters: TStifLoggerTimeStamp& aDataAndTime: inout: Generated date and time
       
  1066 
       
  1067     Return Values: None
       
  1068 
       
  1069     Errors/Exceptions: None
       
  1070 
       
  1071     Status: Approved
       
  1072 
       
  1073 -------------------------------------------------------------------------------
       
  1074 */
       
  1075 void CFileOutput::GetDateAndTime( TStifLoggerTimeStamp& aDataAndTime )
       
  1076     {
       
  1077     TInt num( 0 );
       
  1078     TInt microseconds( 0 );
       
  1079 
       
  1080     // Append date
       
  1081     TTime time;
       
  1082     time.HomeTime();
       
  1083     TDateTime dateTime( time.DateTime() );
       
  1084 
       
  1085     num = dateTime.Day() + 1;
       
  1086     if( num < 10 )
       
  1087         {
       
  1088         aDataAndTime.Append( '0' );
       
  1089         }
       
  1090     // Append month
       
  1091     aDataAndTime.AppendNum( num );
       
  1092     aDataAndTime.Append( '.' );
       
  1093     num = 0;
       
  1094     num = dateTime.Month();
       
  1095     switch( num )
       
  1096         {
       
  1097         case EJanuary:      // 1
       
  1098             {
       
  1099              aDataAndTime.Append( _L( "Jan" ) );
       
  1100              break;
       
  1101             }
       
  1102         case EFebruary:     // 2
       
  1103             {
       
  1104              aDataAndTime.Append( _L( "Feb" ) );
       
  1105              break;
       
  1106             }
       
  1107         case EMarch:        // 3
       
  1108             {
       
  1109              aDataAndTime.Append( _L( "Mar" ) );
       
  1110              break;
       
  1111             }
       
  1112         case EApril:        // 4
       
  1113             {
       
  1114              aDataAndTime.Append( _L( "Apr" ) );
       
  1115              break;
       
  1116             }
       
  1117         case EMay:          // 5
       
  1118             {
       
  1119              aDataAndTime.Append( _L( "May" ) );
       
  1120              break;
       
  1121             }
       
  1122         case EJune:         // 6
       
  1123             {
       
  1124              aDataAndTime.Append( _L( "Jun" ) );
       
  1125              break;
       
  1126             }
       
  1127         case EJuly:         // 7
       
  1128             {
       
  1129              aDataAndTime.Append( _L( "Jul" ) );
       
  1130              break;
       
  1131             }
       
  1132         case EAugust:       // 8
       
  1133             {
       
  1134              aDataAndTime.Append( _L( "Aug" ) );
       
  1135              break;
       
  1136             }
       
  1137         case ESeptember:    // 9
       
  1138             {
       
  1139              aDataAndTime.Append( _L( "Sep" ) );
       
  1140              break;
       
  1141             }
       
  1142         case EOctober:      // 10
       
  1143             {
       
  1144              aDataAndTime.Append( _L( "Oct" ) );
       
  1145              break;
       
  1146             }
       
  1147         case ENovember:     // 11
       
  1148             {
       
  1149              aDataAndTime.Append( _L( "Nov" ) );
       
  1150              break;
       
  1151             }
       
  1152         case EDecember:     // 12
       
  1153             {
       
  1154              aDataAndTime.Append( _L( "Dec" ) );
       
  1155              break;
       
  1156             }
       
  1157         default:
       
  1158             {
       
  1159              aDataAndTime.Append( '-' );
       
  1160              break;
       
  1161             }
       
  1162         }
       
  1163    // Append year
       
  1164     aDataAndTime.Append( '.' );
       
  1165     aDataAndTime.AppendNum( dateTime.Year() );
       
  1166 
       
  1167     // Append time
       
  1168     aDataAndTime.Append( ' ' );
       
  1169     num = dateTime.Hour();
       
  1170     if( num < 10 )
       
  1171         {
       
  1172         aDataAndTime.Append( '0' );
       
  1173         }
       
  1174     aDataAndTime.AppendNum( num );
       
  1175     aDataAndTime.Append( ':' );
       
  1176     num = dateTime.Minute();
       
  1177     if( num < 10 )
       
  1178         {
       
  1179         aDataAndTime.Append( '0' );
       
  1180         }
       
  1181     aDataAndTime.AppendNum( num );
       
  1182     aDataAndTime.Append( ':' );
       
  1183 
       
  1184     num = dateTime.Second();                // Seconds
       
  1185     microseconds = dateTime.MicroSecond();  // Microseconds
       
  1186 
       
  1187     // Seconds
       
  1188     if( num < 10 )
       
  1189         {
       
  1190         aDataAndTime.Append( '0' );
       
  1191         }
       
  1192     aDataAndTime.AppendNum( num );
       
  1193 
       
  1194     // Milliseconds
       
  1195     aDataAndTime.Append( '.' );
       
  1196     aDataAndTime.AppendNumFixedWidth( microseconds, EDecimal, 3 );
       
  1197 
       
  1198     // NOTE: If you add more spaces etc. remember increment KMaxTimeStamp size!
       
  1199 
       
  1200     if ( iLoggerType == CStifLogger::EHtml )
       
  1201         {
       
  1202         aDataAndTime.Append( _L("....") );
       
  1203         }
       
  1204     else
       
  1205         {
       
  1206         aDataAndTime.Append( _L("    ") );
       
  1207         }
       
  1208 
       
  1209     }
       
  1210 
       
  1211 // ================= OTHER EXPORTED FUNCTIONS =================================
       
  1212 // None
       
  1213 
       
  1214 // End of File