stif/Logger/src/RDebugOutput.cpp
changeset 36 813b186005b6
parent 30 86a2e675b80a
child 41 838cdffd57ce
equal deleted inserted replaced
30:86a2e675b80a 36:813b186005b6
     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 CRDebugOutput 
       
    15 * class member functions.
       
    16 *
       
    17 */
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include <e32std.h>
       
    21 #include "Output.h"
       
    22 #include "RDebugOutput.h"
       
    23 #include "LoggerOverFlow.h"
       
    24 
       
    25 // EXTERNAL DATA STRUCTURES
       
    26 // None
       
    27 
       
    28 // EXTERNAL FUNCTION PROTOTYPES  
       
    29 // None
       
    30 
       
    31 // CONSTANTS
       
    32 // None
       
    33 
       
    34 // MACROS
       
    35 // None
       
    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 
       
    53 // ================= MEMBER FUNCTIONS =========================================
       
    54 
       
    55 /*
       
    56 -------------------------------------------------------------------------------
       
    57 
       
    58     Class: CRDebugOutput
       
    59 
       
    60     Method: CRDebugOutput
       
    61 
       
    62     Description: Default constructor
       
    63 
       
    64     C++ default constructor can NOT contain any code, that
       
    65     might leave.
       
    66 
       
    67     Parameters: TLoggerType aLoggerType: in: File type
       
    68                 TBool aWithTimeStamp: in: For timestamp
       
    69                 TBool aWithLineBreak: in: For line break
       
    70                 TBool aWithEventRanking: in: For events ranking to file
       
    71 
       
    72     Return Values: None
       
    73 
       
    74     Errors/Exceptions: None
       
    75 
       
    76     Status: Approved
       
    77 
       
    78 -------------------------------------------------------------------------------
       
    79 */
       
    80 CRDebugOutput::CRDebugOutput( CStifLogger::TLoggerType aLoggerType,
       
    81                                 TBool aWithTimeStamp,
       
    82                                 TBool aWithLineBreak,
       
    83                                 TBool aWithEventRanking ) :
       
    84     COutput()
       
    85     {
       
    86     // Indicates file type
       
    87     iLoggerType = aLoggerType;
       
    88 
       
    89     // Time stamp indicator
       
    90     iWithTimeStamp = aWithTimeStamp;
       
    91 
       
    92     // Line break indicator
       
    93     iWithLineBreak = aWithLineBreak;
       
    94 
       
    95     // Log event ranking indicator
       
    96     iWithEventRanking = aWithEventRanking;
       
    97 
       
    98     // Data buffer
       
    99     iDataHBuf = NULL;
       
   100     iDataHBuf1 = NULL;
       
   101     iDataHBuf2 = NULL;
       
   102 
       
   103     }
       
   104 
       
   105 /*
       
   106 -------------------------------------------------------------------------------
       
   107 
       
   108     Class: CRDebugOutput
       
   109 
       
   110     Method: ConstructL
       
   111 
       
   112     Description: Symbian OS second phase constructor
       
   113 
       
   114     Symbian OS default constructor can leave.
       
   115 
       
   116     Parameters: None
       
   117 
       
   118     Return Values: None
       
   119 
       
   120     Errors/Exceptions: None
       
   121 
       
   122     Status: Approved
       
   123 
       
   124 -------------------------------------------------------------------------------
       
   125 */
       
   126 void CRDebugOutput::ConstructL( TInt aStaticBufferSize )
       
   127     {
       
   128     if( aStaticBufferSize != 0)
       
   129         {
       
   130         iDataHBuf1 = HBufC::NewL( aStaticBufferSize );      
       
   131         iDataHBuf2 = HBufC::NewL( aStaticBufferSize );      
       
   132         iStaticBufferSize = aStaticBufferSize;
       
   133         }
       
   134     }
       
   135 
       
   136 /*
       
   137 -------------------------------------------------------------------------------
       
   138 
       
   139     Class: CRDebugOutput
       
   140 
       
   141     Method: NewL
       
   142 
       
   143     Description: Two-phased constructor.
       
   144 
       
   145     Parameters: const TDesC& aTestPath: in: Log path
       
   146                 const TDesC& aTestFile: in: Log filename
       
   147                 TLoggerType aLoggerType: in: File type
       
   148                 TBool aOverWrite: in: For file overwrite
       
   149                 TBool aWithTimeStamp: in: For timestamp
       
   150                 TBool aWithLineBreak: in: For line break
       
   151                 TBool aWithEventRanking: in: For events ranking to file
       
   152                 TBool aThreadIdToLogFile: in: Indicator to thread id adding to
       
   153                                               end of the log file
       
   154                 TBool aCreateLogDir: in: Indicator to directory creation
       
   155 
       
   156     Return Values: CRDebugOutput*: pointer to CFileOutput object
       
   157 
       
   158     Errors/Exceptions: Leaves if ConstructL leaves
       
   159 
       
   160     Status: Proposal
       
   161 
       
   162 -------------------------------------------------------------------------------
       
   163 */
       
   164 CRDebugOutput* CRDebugOutput::NewL( const TDesC& /* aTestPath */,
       
   165                                     const TDesC& /* aTestFile */,
       
   166                                     CStifLogger::TLoggerType aLoggerType,
       
   167                                     TBool /* aOverWrite */,
       
   168                                     TBool aWithTimeStamp,
       
   169                                     TBool aWithLineBreak,
       
   170                                     TBool aWithEventRanking,
       
   171                                     TBool /* aThreadIdToLogFile */,
       
   172                                     TBool /* aCreateLogDir */,
       
   173                                     TInt aStaticBufferSize)
       
   174     {
       
   175     // Create CFileOutput object fileWriter
       
   176     CRDebugOutput* rdebugWriter = new (ELeave) CRDebugOutput( 
       
   177                                                         aLoggerType,
       
   178                                                         aWithTimeStamp,
       
   179                                                         aWithLineBreak,
       
   180                                                         aWithEventRanking );
       
   181 
       
   182     CleanupStack::PushL( rdebugWriter );
       
   183     rdebugWriter->ConstructL( aStaticBufferSize );
       
   184     CleanupStack::Pop( rdebugWriter );
       
   185 
       
   186     return rdebugWriter;
       
   187 
       
   188     }
       
   189 
       
   190 /*
       
   191 -------------------------------------------------------------------------------
       
   192 
       
   193     Class: CRDebugOutput
       
   194 
       
   195     Method: ~CRDebugOutput
       
   196 
       
   197     Description: Destructor
       
   198 
       
   199     Parameters: None
       
   200 
       
   201     Return Values: None
       
   202 
       
   203     Errors/Exceptions: None
       
   204 
       
   205     Status: Approved
       
   206 
       
   207 -------------------------------------------------------------------------------
       
   208 */
       
   209 CRDebugOutput::~CRDebugOutput()
       
   210     {
       
   211     delete iDataHBuf1;
       
   212     delete iDataHBuf2;
       
   213     }
       
   214 
       
   215 /*
       
   216 -------------------------------------------------------------------------------
       
   217 
       
   218     Class: CRDebugOutput
       
   219 
       
   220     Method: Write
       
   221 
       
   222     Description: Write log information or data to the file. 16 bit.
       
   223 
       
   224     Parameters: TBool aWithTimeStamp: in: Is time stamp flag used
       
   225                 TBool aWithLineBreak: in: Is line break flag used
       
   226                 TBool aWithEventRanking: in: Is event ranking flag used
       
   227                 const TDesC& aData: in: Logged or saved data
       
   228 
       
   229     Return Values: TInt: Symbian error code.
       
   230 
       
   231     Errors/Exceptions: None
       
   232 
       
   233     Status: Proposal
       
   234 
       
   235 -------------------------------------------------------------------------------
       
   236 */
       
   237 TInt CRDebugOutput::Write( TBool aWithTimeStamp,
       
   238                             TBool aWithLineBreak,
       
   239                             TBool aWithEventRanking,
       
   240                             const TDesC& aData )
       
   241     {
       
   242     TInt currentEndPos( 0 );        // Current position in aData parsing
       
   243                                     // to partitions
       
   244 
       
   245     // a logInfo size must be at least the minimumSpace size
       
   246     TInt minimumSpace = ( KMaxTimeStamp + KMaxHtmlLineBreak + KMaxLineBreak +
       
   247                             KMaxEventRanking + KMaxSpace );
       
   248         
       
   249     TPtr logInfo(0, 0);
       
   250     HBufC* dataHBuf = NULL;    
       
   251     
       
   252     if(iDataHBuf1 != NULL)                            
       
   253         {
       
   254         TInt messageLength = aData.Length() + minimumSpace;
       
   255         if( messageLength > iStaticBufferSize )
       
   256             {
       
   257              RDebug::Print(_L("Warning: buffer size too small, not able to log!"));
       
   258              return KErrOverflow;
       
   259             }
       
   260         // Using the HBufC created in ConstructL
       
   261         logInfo.Set( iDataHBuf1->Des() ); // Memory allocation for data
       
   262         
       
   263         }
       
   264     else
       
   265         {
       
   266         // Buffer size is minimum space plus aData(aData length may be 0 but
       
   267         // time stamp is used)
       
   268         if( ( aData.Length() + minimumSpace ) < ( KMaxLogData + minimumSpace ) )
       
   269             {
       
   270             dataHBuf = HBufC::New( aData.Length() + minimumSpace );
       
   271             }
       
   272         // Buffer size is over KMaxLogData
       
   273         else
       
   274             {
       
   275             dataHBuf = HBufC::New( aData.Length() );
       
   276             }
       
   277         if( dataHBuf == NULL )
       
   278             {
       
   279             return KErrNoMemory;
       
   280             }
       
   281         logInfo.Set( dataHBuf->Des() ); // Memory allocation for data
       
   282         }
       
   283 
       
   284     logInfo.Copy( aData );          // Copy data
       
   285     
       
   286     TPtr data( 0, 0 );
       
   287 
       
   288     // Add time stamp and/or event ranking if required
       
   289     EventAndTimeCombiner( logInfo, data, aWithTimeStamp,
       
   290                             aWithLineBreak, aWithEventRanking );
       
   291 
       
   292     while( data.Length() > currentEndPos )
       
   293         {
       
   294         // In this loop round data length is/under 254
       
   295         if( ( data.Length() - currentEndPos ) <= KMaxRDebug )
       
   296             {
       
   297             // Current positions to rest of data position
       
   298             logInfo = data.Mid( currentEndPos, ( data.Length() - currentEndPos ) );
       
   299             // Prevent rdebug from parsing text string as formating string
       
   300             RDebug::Print( _L( "%S" ), &logInfo );
       
   301             }
       
   302         // In this loop round data length is over 254
       
   303         else
       
   304             {
       
   305             // Current positions to KMaxRDebug that includes space for ' ->'
       
   306             logInfo = data.Mid( currentEndPos, KMaxRDebug );
       
   307             // Prevent rdebug from parsing text string as formating string
       
   308             RDebug::Print( _L( "%S ->" ), &logInfo );
       
   309             }
       
   310         currentEndPos = currentEndPos + KMaxRDebug;
       
   311         }
       
   312 
       
   313     delete dataHBuf;
       
   314 
       
   315     if(iDataHBuf2 == NULL)
       
   316         {
       
   317         delete iDataHBuf;
       
   318         iDataHBuf = NULL;
       
   319         }
       
   320 
       
   321     return KErrNone;
       
   322 
       
   323     }
       
   324 
       
   325 /*
       
   326 -------------------------------------------------------------------------------
       
   327 
       
   328     Class: CRDebugOutput
       
   329 
       
   330     Method: Write
       
   331 
       
   332     Description: Write log information or data to the file. 8 bit.
       
   333 
       
   334     Parameters: TBool aWithTimeStamp: in: Is time stamp flag used
       
   335                 TBool aWithLineBreak: in: Is line break flag used
       
   336                 TBool aWithEventRanking: in: Is event ranking flag used
       
   337                 const TDesC8& aData: in: Logged or saved data
       
   338 
       
   339     Return Values: TInt
       
   340 
       
   341     Errors/Exceptions: None
       
   342 
       
   343     Status: Proposal
       
   344 
       
   345 -------------------------------------------------------------------------------
       
   346 */
       
   347 TInt CRDebugOutput::Write( TBool aWithTimeStamp,
       
   348                             TBool aWithLineBreak,
       
   349                             TBool aWithEventRanking,
       
   350                             const TDesC8& aData )
       
   351     {
       
   352     TInt currentEndPos( 0 );        // Current position in aData parsing
       
   353                                     // to partitions
       
   354     TPtr logInfo(0, 0);
       
   355 
       
   356     // a logInfo size must be at least the minimumSpace size
       
   357     TInt minimumSpace = ( KMaxTimeStamp + KMaxHtmlLineBreak + KMaxLineBreak +
       
   358                             KMaxEventRanking + KMaxSpace );
       
   359     HBufC* dataHBuf = NULL;
       
   360     if(iDataHBuf1 != NULL)                            
       
   361         {
       
   362         if( ( aData.Length() + minimumSpace ) > iStaticBufferSize )
       
   363             {
       
   364              RDebug::Print(_L("Warning: buffer size too small, not able to log!"));
       
   365              return KErrOverflow;
       
   366             }       
       
   367         logInfo.Set( iDataHBuf1->Des() ); // Memory allocation for data
       
   368         }
       
   369     else
       
   370         {
       
   371         // 8 bit data to 16 bit because RDebug::Print don't support 8 bit printing
       
   372         
       
   373         // Buffer size is minimum space plus aData(aData length may be 0 but
       
   374         // time stamp is used)
       
   375         if( ( aData.Length() + minimumSpace ) < ( KMaxLogData + minimumSpace ) )
       
   376             {
       
   377             dataHBuf = HBufC::New( aData.Length() + minimumSpace );
       
   378             }
       
   379         // Buffer size is over KMaxLogData
       
   380         else
       
   381             {
       
   382             dataHBuf = HBufC::New( aData.Length() );
       
   383             }
       
   384         if( dataHBuf == NULL )
       
   385             {
       
   386             return KErrNoMemory;
       
   387             }
       
   388         logInfo.Set( dataHBuf->Des() ); // Memory allocation for data
       
   389         }
       
   390         
       
   391     logInfo.Copy( aData );          // Copy data
       
   392 
       
   393     TPtr data( 0, 0 );
       
   394 
       
   395     // Add time stamp and/or event ranking if required
       
   396     EventAndTimeCombiner( logInfo, data, aWithTimeStamp,
       
   397                             aWithLineBreak, aWithEventRanking );
       
   398     while( data.Length() > currentEndPos )
       
   399         {
       
   400         // In this loop round data length is/under 254
       
   401         if( ( data.Length() - currentEndPos ) <= KMaxRDebug )
       
   402             {
       
   403             // Current positions to rest of data position
       
   404             logInfo = data.Mid( currentEndPos, ( data.Length() - currentEndPos ) );
       
   405             // Prevent rdebug from parsing text string as formating string
       
   406             RDebug::Print( _L( "%S" ), &logInfo );
       
   407             }
       
   408         // In this loop round data length is over 254
       
   409         else
       
   410             {
       
   411             // Current positions to KMaxRDebug that includes space for ' ->'
       
   412             logInfo = data.Mid( currentEndPos, KMaxRDebug );
       
   413             // Prevent rdebug from parsing text string as formating string
       
   414             RDebug::Print( _L( "%S ->" ), &logInfo );
       
   415             }
       
   416         currentEndPos = currentEndPos + KMaxRDebug;
       
   417         }
       
   418 
       
   419     delete dataHBuf;
       
   420 
       
   421     if(iDataHBuf2 == NULL)
       
   422        {
       
   423        delete iDataHBuf;
       
   424        iDataHBuf = NULL;
       
   425        }
       
   426 
       
   427     return KErrNone;
       
   428 
       
   429     }
       
   430 
       
   431 /*
       
   432 -------------------------------------------------------------------------------
       
   433 
       
   434     Class: CRDebugOutput
       
   435 
       
   436     Method: EventAndTimeCombiner    
       
   437 
       
   438     Description: Event ranking and time stamp combimer.
       
   439 
       
   440     Parameters: TLogInfo aLogInfo: inout: Overflowed data
       
   441                 TPtr8& aData: inout: Combined data
       
   442                 TBool aWithTimeStamp: in: Is time stamp flag used
       
   443                 TBool aWithLineBreak: in: Is line break flag used
       
   444                 TBool aWithEventRanking: in: Is event ranking flag used
       
   445 
       
   446     Return Values: None
       
   447 
       
   448     Errors/Exceptions: None
       
   449 
       
   450     Status: Proposal
       
   451 
       
   452 -------------------------------------------------------------------------------
       
   453 */
       
   454 void CRDebugOutput::EventAndTimeCombiner( TPtr& aLogInfo,
       
   455                                             TPtr& aData,
       
   456                                             TBool aWithTimeStamp,
       
   457                                             TBool aWithLineBreak,
       
   458                                             TBool aWithEventRanking )
       
   459     {
       
   460     TInt extraLength( 0 );
       
   461 
       
   462     // Extra space calculation
       
   463     if( iWithEventRanking && aWithEventRanking )
       
   464         {
       
   465         extraLength = extraLength + KMaxEventRanking + KMaxSpace;
       
   466         }
       
   467     if( ( iLoggerType == CStifLogger::EHtml ) && iWithLineBreak && aWithLineBreak )
       
   468         {
       
   469         extraLength = extraLength + KMaxHtmlLineBreak;
       
   470         }
       
   471     if( iWithLineBreak && aWithLineBreak )
       
   472         {
       
   473         extraLength = extraLength + KMaxLineBreak;
       
   474         }
       
   475     if( aWithTimeStamp && iWithTimeStamp )
       
   476         {
       
   477         extraLength = extraLength + KMaxTimeStamp;
       
   478         }
       
   479 
       
   480     // Calculated space
       
   481     TInt space = aLogInfo.Length();
       
   482 
       
   483     if(iDataHBuf2 != NULL)                            
       
   484         {
       
   485         aData.Set( iDataHBuf2->Des() );  // Memory allocation for data
       
   486         aData.Copy( _L("") ); // Initialize aData buffer
       
   487         }
       
   488     else
       
   489     {        
       
   490         iDataHBuf = HBufC::New( space + extraLength );
       
   491         if( iDataHBuf == NULL )
       
   492             {
       
   493             return;
       
   494             }
       
   495         aData.Set( iDataHBuf->Des() );  // Memory allocation for data
       
   496     }
       
   497 
       
   498     // Event ranking
       
   499     if( iWithEventRanking && aWithEventRanking && !iWithTimeStamp )
       
   500         {
       
   501         EventRanking( aData );          // Event ranking to data
       
   502         aData.Append( aLogInfo );       // Unicode aData to normal text
       
   503         }
       
   504     // Time stamp
       
   505     else if( iWithTimeStamp && aWithTimeStamp )
       
   506         {
       
   507         // With event ranking
       
   508         if( iWithEventRanking && aWithEventRanking )
       
   509             {
       
   510             EventRanking( aData );      // Event ranking to data
       
   511             }
       
   512         AddTimeStampToData( aData );    // Add time stamp
       
   513         aData.Append( aLogInfo );       // Unicode aData to normal text
       
   514         }
       
   515     else
       
   516         {
       
   517         aData.Copy( aLogInfo );         // Unicode aData to normal text
       
   518         }
       
   519 
       
   520     // NOTE: If need some special line break do it with logging phase
       
   521 
       
   522     // If html logging and line break is used add the line break.
       
   523     if ( ( iLoggerType == CStifLogger::EHtml ) && iWithLineBreak && aWithLineBreak )
       
   524         {
       
   525         aData.Append( _L( "<BR>" ) );
       
   526         aData.Append( _L( "\n" ) );  // To make html file more readable
       
   527                                     // with text editor
       
   528         }
       
   529 
       
   530     // Other cases line break is normal '\n' if logging is used
       
   531     else if( iWithLineBreak && aWithLineBreak )
       
   532         {
       
   533         aData.Append( 0x0D ); // 13 or '\' in Symbian OS
       
   534         aData.Append( 0x0A ); // 10 or 'n' in Symbian OS
       
   535         }
       
   536 
       
   537     }
       
   538 
       
   539 /*
       
   540 -------------------------------------------------------------------------------
       
   541 
       
   542     Class: CFileOutput
       
   543 
       
   544     Method: EventRanking
       
   545 
       
   546     Description: For event ranking logging.
       
   547 
       
   548     Parameters: TPtr8& aData: inout: Data with event ranking
       
   549 
       
   550     Return Values: None
       
   551 
       
   552     Errors/Exceptions: None
       
   553 
       
   554     Status: Approved
       
   555 
       
   556 -------------------------------------------------------------------------------
       
   557 */
       
   558 void CRDebugOutput::EventRanking( TPtr& aData )
       
   559     {
       
   560     // Returns the machine's current tick count.
       
   561     TUint tick = User::TickCount();
       
   562     tick &= 0xffff;
       
   563     aData.AppendNum( tick );
       
   564     aData.Append( _L( " " ) );
       
   565 
       
   566     }
       
   567 
       
   568 /*
       
   569 -------------------------------------------------------------------------------
       
   570 
       
   571     Class: CFileOutput
       
   572 
       
   573     Method: DateAndTime
       
   574 
       
   575     Description: For date and time logging.
       
   576 
       
   577     Parameters: TPtr8& aData: inout: Data with time stamps
       
   578 
       
   579     Return Values: None
       
   580 
       
   581     Errors/Exceptions: None
       
   582 
       
   583     Status: Approved
       
   584 
       
   585 -------------------------------------------------------------------------------
       
   586 */
       
   587 void CRDebugOutput::AddTimeStampToData( TPtr& aData )
       
   588     {
       
   589     TStifLoggerTimeStamp8 timeStamp;
       
   590     GetDateAndTime( timeStamp );
       
   591     aData.Append( timeStamp );
       
   592 
       
   593     }
       
   594 
       
   595 /*
       
   596 -------------------------------------------------------------------------------
       
   597 
       
   598     Class: CFileOutput
       
   599 
       
   600     Method: GetDateAndTime
       
   601 
       
   602     Description: For date and time logging.
       
   603 
       
   604     Parameters: TStifLoggerTimeStamp& aDataAndTime: inout: Generated date and time
       
   605 
       
   606     Return Values: None
       
   607 
       
   608     Errors/Exceptions: None
       
   609 
       
   610     Status: Approved
       
   611 
       
   612 -------------------------------------------------------------------------------
       
   613 */
       
   614 void CRDebugOutput::GetDateAndTime( TStifLoggerTimeStamp8& aDataAndTime )
       
   615     {
       
   616     TInt num( 0 );
       
   617     TInt microseconds( 0 );
       
   618 
       
   619     // Append date
       
   620     TTime time;
       
   621     time.HomeTime();
       
   622     TDateTime dateTime( time.DateTime() );
       
   623 
       
   624     num = dateTime.Day() + 1;
       
   625     if( num < 10 )
       
   626         {
       
   627         aDataAndTime.Append( '0' );
       
   628         }
       
   629     // Append month
       
   630     aDataAndTime.AppendNum( num );  
       
   631     num = dateTime.Month() + 1;     // returns enum
       
   632     if( num < 10 )
       
   633         {
       
   634         aDataAndTime.Append( '0' );
       
   635         }
       
   636     aDataAndTime.AppendNum( num );
       
   637     aDataAndTime.AppendNum( dateTime.Year() );
       
   638 
       
   639     // Append time
       
   640     aDataAndTime.Append( ' ' );
       
   641     num = dateTime.Hour();
       
   642     if( num < 10 )
       
   643         {
       
   644         aDataAndTime.Append( '0' );
       
   645         }
       
   646     aDataAndTime.AppendNum( num );
       
   647     num = dateTime.Minute();
       
   648     if( num < 10 )
       
   649         {
       
   650         aDataAndTime.Append( '0' );
       
   651         }
       
   652     aDataAndTime.AppendNum( num );
       
   653 
       
   654     num = dateTime.Second();
       
   655     microseconds = dateTime.MicroSecond();  // Microseconds
       
   656 
       
   657     // Seconds
       
   658     if( num < 10 )
       
   659         {
       
   660         aDataAndTime.Append( '0' );
       
   661         }
       
   662     aDataAndTime.AppendNum( num );
       
   663 
       
   664    // Milliseconds
       
   665     aDataAndTime.Append( '.' );
       
   666     aDataAndTime.AppendNumFixedWidth( microseconds, EDecimal, 3 );
       
   667 
       
   668     // NOTE: If you add more spaces etc. remember increment KMaxTimeStamp size!
       
   669 
       
   670     if ( iLoggerType == CStifLogger::EHtml )
       
   671         {
       
   672         aDataAndTime.Append( _L("....") );
       
   673         }
       
   674     else
       
   675         {
       
   676         aDataAndTime.Append( _L("    ") );
       
   677         }
       
   678 
       
   679     }
       
   680 
       
   681 // ================= OTHER EXPORTED FUNCTIONS =================================
       
   682 // None
       
   683 
       
   684 // End of File