ipsservices/ipssosplugin/src/ipsplgtextsearcher.cpp
changeset 0 8466d47a6819
equal deleted inserted replaced
-1:000000000000 0:8466d47a6819
       
     1 /*
       
     2 * Copyright (c) 2005-2008 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 file implements class CIpsPlgTextSearcher.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 
       
    21 #include "emailtrace.h"
       
    22 #include "ipsplgheaders.h"
       
    23 
       
    24 const TUint KKeywordsArrayGranularity = 8;
       
    25 const TInt KUnicodeConversionBufferSize = 100;
       
    26 
       
    27 // ================= MEMBER FUNCTIONS ====================
       
    28 
       
    29 // ----------------------------------------------------------------------------
       
    30 // CIpsPlgTextSearcher::NewL()
       
    31 // Symbian OS 2 phased constructor.
       
    32 // ----------------------------------------------------------------------------
       
    33 //
       
    34 CIpsPlgTextSearcher* CIpsPlgTextSearcher::NewL( 
       
    35     MIpsPlgTextSearcherObserver& aObserver )
       
    36     {
       
    37     FUNC_LOG;
       
    38     CIpsPlgTextSearcher* self = CIpsPlgTextSearcher::NewLC( aObserver );
       
    39     CleanupStack::Pop( self );
       
    40     return self;
       
    41     }
       
    42 
       
    43 // ----------------------------------------------------------------------------
       
    44 // CIpsPlgTextSearcher::NewLC()
       
    45 // Symbian OS 2 phased constructor.
       
    46 // ----------------------------------------------------------------------------
       
    47 //
       
    48 CIpsPlgTextSearcher* CIpsPlgTextSearcher::NewLC( 
       
    49     MIpsPlgTextSearcherObserver& aObserver )
       
    50     {
       
    51     FUNC_LOG;
       
    52     CIpsPlgTextSearcher* self = 
       
    53         new ( ELeave ) CIpsPlgTextSearcher( aObserver );
       
    54     CleanupStack::PushL( self );
       
    55     self->ConstructL();
       
    56     return self;
       
    57     }
       
    58 
       
    59 // ----------------------------------------------------------------------------
       
    60 // CIpsPlgTextSearcher::CIpsPlgTextSearcher()
       
    61 // Performs the first phase of two phase construction.
       
    62 // ----------------------------------------------------------------------------
       
    63 //
       
    64 CIpsPlgTextSearcher::CIpsPlgTextSearcher( 
       
    65     MIpsPlgTextSearcherObserver& aObserver )
       
    66     : iObserver( aObserver )
       
    67     {
       
    68     FUNC_LOG;
       
    69     }
       
    70 
       
    71 // ----------------------------------------------------------------------------
       
    72 // CIpsPlgTextSearcher::ConstructL()
       
    73 // Performs the second phase construction.
       
    74 // ----------------------------------------------------------------------------
       
    75 //
       
    76 void CIpsPlgTextSearcher::ConstructL()
       
    77     {
       
    78     FUNC_LOG;
       
    79     iSearchKeywords8 = 
       
    80         new ( ELeave ) CDesC8ArrayFlat( KKeywordsArrayGranularity );
       
    81     User::LeaveIfError ( iRFs.Connect() );
       
    82     }
       
    83 
       
    84 // ----------------------------------------------------------------------------
       
    85 // CIpsPlgTextSearcher::~CIpsPlgTextSearcher()
       
    86 // Destructor
       
    87 // ----------------------------------------------------------------------------
       
    88 //
       
    89 CIpsPlgTextSearcher::~CIpsPlgTextSearcher()
       
    90     {
       
    91     FUNC_LOG;
       
    92     iKeywordSearchStatusArray.Close();
       
    93     
       
    94     if( iSearchKeywords8 )
       
    95         {
       
    96         iSearchKeywords8->Reset();
       
    97         delete iSearchKeywords8;
       
    98         }
       
    99     
       
   100     iRFs.Close();
       
   101     }
       
   102 
       
   103 // ----------------------------------------------------------------------------
       
   104 // CIpsPlgTextSearcher::SetParametersL()
       
   105 // Sets the search parameters for the search.
       
   106 // ----------------------------------------------------------------------------
       
   107 //
       
   108 void CIpsPlgTextSearcher::SetParametersL(  
       
   109     const CDesCArray& aKeywords, 
       
   110     TIpsPlgCriteriaOperation aOperator, 
       
   111     TBool aCaseSensitive, 
       
   112     TInt aSearchResultRecommendedSnippetLength )
       
   113     {
       
   114     FUNC_LOG;
       
   115     iHaveParameters = ETrue;
       
   116     
       
   117     iSearchKeywords = &aKeywords;
       
   118     
       
   119     iOperator = aOperator;
       
   120     iCaseSensitive = aCaseSensitive;
       
   121     iSearchResultRecommendedSnippetLength = 
       
   122         aSearchResultRecommendedSnippetLength;
       
   123 
       
   124     iKeywordSearchStatusArray.Reset();
       
   125     TInt count( aKeywords.Count() );
       
   126     for ( TInt i(0); i < count; i++ )
       
   127         {
       
   128         TIpsPlgKeywordSearchStatus status;
       
   129         status.iFound = EFalse;
       
   130         status.iFoundAsNthWord = KErrNotFound;
       
   131         
       
   132         iKeywordSearchStatusArray.AppendL( status );
       
   133         }
       
   134     }
       
   135 
       
   136 // ----------------------------------------------------------------------------
       
   137 // CIpsPlgTextSearcher::Cleanup()
       
   138 // Cleans up internal data.  Must be called before each new search is started.
       
   139 //  Does not clean up the parameters set via SetParametersL.
       
   140 // ----------------------------------------------------------------------------
       
   141 //
       
   142 void CIpsPlgTextSearcher::Cleanup()
       
   143     {
       
   144     FUNC_LOG;
       
   145     TInt count( iKeywordSearchStatusArray.Count() );
       
   146     for ( TInt i(0); i < count; i++ )
       
   147         {    
       
   148         iKeywordSearchStatusArray[i].iFound = EFalse;
       
   149         iKeywordSearchStatusArray[i].iFoundAsNthWord = KErrNotFound;
       
   150         }
       
   151     }
       
   152 
       
   153 // ----------------------------------------------------------------------------
       
   154 // CIpsPlgTextSearcher::SearchL()
       
   155 // ----------------------------------------------------------------------------
       
   156 //
       
   157 TBool CIpsPlgTextSearcher::SearchL( const TDesC& aToBeSearchedDes )
       
   158     {
       
   159     FUNC_LOG;
       
   160     __ASSERT_DEBUG( iHaveParameters, 
       
   161         User::Panic( KIpsPlgPanicCategory, EIpsPlgNoParameters ) );
       
   162     
       
   163     // when aToBeSearchedDes has no data, it can match *
       
   164     if( !aToBeSearchedDes.Length() )
       
   165         {
       
   166         return EFalse;
       
   167         }
       
   168 
       
   169     iFirstMatchKeywordCharPos = KErrNotFound;
       
   170     
       
   171     TBool found( DoStringCompareWithKeywordsL( aToBeSearchedDes, *iSearchKeywords,
       
   172         iKeywordSearchStatusArray, iOperator, iCaseSensitive ) );
       
   173         
       
   174     if ( found )
       
   175         {
       
   176         // Parameters are not used in function
       
   177         iObserver.HitL( KNullDesC, KErrNone, EFalse, EFalse );
       
   178         }
       
   179     return found;
       
   180     }
       
   181     
       
   182 // ----------------------------------------------------------------------------
       
   183 // CIpsPlgTextSearcher::SearchL()
       
   184 // ----------------------------------------------------------------------------
       
   185 //
       
   186 TBool CIpsPlgTextSearcher::SearchL( const TDesC8& aToBeSearchedDes )
       
   187     {
       
   188     FUNC_LOG;
       
   189     __ASSERT_DEBUG( iHaveParameters, 
       
   190         User::Panic( KIpsPlgPanicCategory, EIpsPlgNoParameters ) );
       
   191     
       
   192     // when aToBeSearchedDes has no data, it can match *
       
   193     if( !aToBeSearchedDes.Length() )
       
   194         {
       
   195         return EFalse;
       
   196         }
       
   197         
       
   198     // Create 8 bit versions from the keywords for better efficiency
       
   199     iSearchKeywords8->Reset();    
       
   200     TInt count( iSearchKeywords->Count() );
       
   201     for ( TInt i(0); i < count; i++ )
       
   202         {
       
   203         HBufC8* keyword8Bit = ConvertFromUnicodeL( iRFs,
       
   204                      iSearchKeywords->MdcaPoint( i ), 
       
   205                      KCharacterSetIdentifierUtf8 );
       
   206         CleanupStack::PushL( keyword8Bit );
       
   207         iSearchKeywords8->AppendL( *keyword8Bit );
       
   208         CleanupStack::PopAndDestroy( keyword8Bit );
       
   209         }
       
   210 
       
   211     iFirstMatchKeywordCharPos = KErrNotFound;
       
   212     
       
   213     TBool found( DoStringCompareWithKeywordsL( aToBeSearchedDes, *iSearchKeywords8,
       
   214         iKeywordSearchStatusArray, iOperator, iCaseSensitive ) );
       
   215 
       
   216     if ( found ) 
       
   217         {
       
   218         // Parameters are not used in function
       
   219         iObserver.HitL( KNullDesC, KErrNone, EFalse, EFalse );
       
   220         }
       
   221     return found;
       
   222     }
       
   223     
       
   224 // ----------------------------------------------------------------------------
       
   225 // CIpsPlgTextSearcher::DoStringCompareWithKeywords()
       
   226 // ----------------------------------------------------------------------------
       
   227 //
       
   228 TBool CIpsPlgTextSearcher::DoStringCompareWithKeywordsL( 
       
   229     const TDesC& aToBeSearchedDes,
       
   230     const CDesCArray& aKeywords, 
       
   231     RArray<TIpsPlgKeywordSearchStatus>& aKeywordSearchStatusArray,
       
   232     TIpsPlgCriteriaOperation aOperator, 
       
   233     TBool aCaseSensitive )
       
   234     {
       
   235     FUNC_LOG;
       
   236     // Compare the string will all the keywords
       
   237     TInt count( aKeywords.Count() );
       
   238     if ( count != aKeywordSearchStatusArray.Count() )
       
   239         {
       
   240         User::Leave( KErrArgument );
       
   241         }
       
   242     for ( TInt i(0); i < count; i++ )
       
   243         {
       
   244         if ( !aKeywordSearchStatusArray[i].iFound )    // keyword not yet found
       
   245             {
       
   246             TInt match;
       
   247             if ( aCaseSensitive )
       
   248                 {                
       
   249                 match = aToBeSearchedDes.Match( aKeywords[i] );
       
   250                 }
       
   251             else
       
   252                 {
       
   253                 match = aToBeSearchedDes.MatchC( aKeywords[i] );
       
   254                 }
       
   255 
       
   256             // KErrNotFound indicates that no match was found
       
   257             if ( match != KErrNotFound ) 
       
   258                 {
       
   259                 aKeywordSearchStatusArray[i].iFound = ETrue;
       
   260                 // The 1st found keyword will be also the snippet
       
   261                 if ( iFirstMatchKeywordCharPos == KErrNotFound  )
       
   262                     {
       
   263   
       
   264                     if ( match == aToBeSearchedDes.Length() ) 
       
   265                         {
       
   266                         iFirstMatchKeywordCharPos = 0;
       
   267                         }
       
   268                     else
       
   269                         {                        
       
   270                         iFirstMatchKeywordCharPos = match;
       
   271                         }
       
   272                      
       
   273                     }
       
   274 
       
   275                 if ( aOperator == EIpsPlgCriteriaOperationOR )
       
   276                     {
       
   277                     // As soon as one keyword is found, the OR search can stop
       
   278                     return ETrue; 
       
   279                     }
       
   280                 }
       
   281             }
       
   282         }
       
   283 
       
   284     // Check if there is still need to continue searching.
       
   285     TBool keywordsFound;
       
   286     switch ( aOperator )
       
   287         {
       
   288         case EIpsPlgCriteriaOperationAND:
       
   289             keywordsFound = ETrue;
       
   290             break;
       
   291 
       
   292         case EIpsPlgCriteriaOperationOR:
       
   293             keywordsFound = EFalse;
       
   294             break;
       
   295 
       
   296         default:
       
   297             keywordsFound = ETrue;    // to avoid warning
       
   298             break;
       
   299         }
       
   300 
       
   301     // For AND search, all keywords must be found, thus if 1 is not found -> 
       
   302     // No hit
       
   303     if( aOperator == EIpsPlgCriteriaOperationAND )
       
   304         {
       
   305         for ( TInt j(0); j < count; j++ )
       
   306             {
       
   307             if ( !aKeywordSearchStatusArray[j].iFound )
       
   308                 {
       
   309                 return EFalse;
       
   310                 }
       
   311             }
       
   312         }
       
   313     return keywordsFound;
       
   314     }
       
   315 
       
   316 // ----------------------------------------------------------------------------
       
   317 // CIpsPlgTextSearcher::DoStringCompareWithKeywordsL()
       
   318 // ----------------------------------------------------------------------------
       
   319 //
       
   320 TBool CIpsPlgTextSearcher::DoStringCompareWithKeywordsL( 
       
   321     const TDesC8& aToBeSearchedDes,
       
   322     const CDesC8Array& aKeywords, 
       
   323     RArray<TIpsPlgKeywordSearchStatus>& aKeywordSearchStatusArray,
       
   324     TIpsPlgCriteriaOperation aOperator, 
       
   325     TBool aCaseSensitive )
       
   326     {
       
   327     FUNC_LOG;
       
   328     TInt count( aKeywords.Count() );
       
   329     if ( count != aKeywordSearchStatusArray.Count() )
       
   330         {
       
   331         User::Leave( KErrArgument );
       
   332         }
       
   333     // Compare the string will all the keywords
       
   334     for ( TInt i=0; i<aKeywords.Count(); i++ )
       
   335         {
       
   336         if ( !aKeywordSearchStatusArray[i].iFound ) // keyword not yet found
       
   337             {
       
   338             TInt match;
       
   339             if ( aCaseSensitive )
       
   340                 {                
       
   341                 match = aToBeSearchedDes.Match( aKeywords[i] );
       
   342                 }
       
   343             else
       
   344                 {
       
   345                 match = aToBeSearchedDes.MatchC( aKeywords[i] );
       
   346                 }
       
   347 
       
   348             // KErrNotFound indicates that no match was found
       
   349             if ( match != KErrNotFound )    
       
   350                 {
       
   351                 aKeywordSearchStatusArray[i].iFound = ETrue;
       
   352                 // The 1st found keyword will be also the snippet
       
   353                 if ( iFirstMatchKeywordCharPos == KErrNotFound  )
       
   354                     {
       
   355                     iFirstMatchKeywordCharPos = match;
       
   356                     }
       
   357 
       
   358                 if ( aOperator == EIpsPlgCriteriaOperationOR )
       
   359                     {
       
   360                     // As soon as one keyword is found, the OR search can stop
       
   361                     return ETrue;  
       
   362                     }
       
   363                 }
       
   364             }
       
   365         }
       
   366 
       
   367     // Check if there is still need to continue searching.
       
   368     TBool keywordsFound;
       
   369     switch ( aOperator )
       
   370         {
       
   371         case EIpsPlgCriteriaOperationAND:
       
   372             keywordsFound = ETrue;
       
   373             break;
       
   374 
       
   375         case EIpsPlgCriteriaOperationOR:
       
   376             keywordsFound = EFalse;
       
   377             break;
       
   378 
       
   379         default:
       
   380             keywordsFound = ETrue;    // to avoid warning
       
   381             break;
       
   382         }
       
   383 
       
   384     // For AND search, all keywords must be found, thus if 1 is not found -> 
       
   385     // No hit
       
   386     if( aOperator == EIpsPlgCriteriaOperationAND )
       
   387         {
       
   388         for ( TInt j(0); j < count; j++ )
       
   389             {
       
   390             if ( !aKeywordSearchStatusArray[j].iFound )
       
   391                 {
       
   392                 return EFalse;
       
   393                 }
       
   394             }
       
   395         }
       
   396     return keywordsFound;
       
   397     }
       
   398     
       
   399 // ----------------------------------------------------------------------------
       
   400 // CIpsPlgTextSearcher::CreateSnippetLC()
       
   401 // Creates the snippet from the 1st found keyword hit.  16 bit version.
       
   402 // ----------------------------------------------------------------------------
       
   403 //
       
   404 HBufC* CIpsPlgTextSearcher::CreateSnippetLC( 
       
   405     const TDesC& aToBeSearchedDes, 
       
   406     TInt& aSnippetCharPos,
       
   407     TBool& aStartIncomplete, 
       
   408     TBool& aEndIncomplete ) const
       
   409     {
       
   410     FUNC_LOG;
       
   411     TInt halfSnippetLen ( iSearchResultRecommendedSnippetLength / 2 );
       
   412     
       
   413     TInt firstChar ( iFirstMatchKeywordCharPos - halfSnippetLen );
       
   414     // if firstChar is negative, then we can give more space to lastChar
       
   415     TInt lastChar ( 
       
   416         iFirstMatchKeywordCharPos + halfSnippetLen - Min( firstChar, 0) );
       
   417     
       
   418     TInt searchDesLastChar ( aToBeSearchedDes.Length() );
       
   419     
       
   420     // if lastChar is go out of the total length, put the firstChar head toward
       
   421     firstChar = 
       
   422         Max( 0, firstChar - Max( 0, ( lastChar - searchDesLastChar ) ) ) ;    
       
   423     
       
   424     aSnippetCharPos = halfSnippetLen + ( lastChar - searchDesLastChar );
       
   425     
       
   426     aStartIncomplete = ETrue;
       
   427     if ( firstChar <= 0 )
       
   428         {
       
   429         firstChar = 0;
       
   430         aStartIncomplete = EFalse;
       
   431         aSnippetCharPos = iFirstMatchKeywordCharPos;
       
   432         }
       
   433 
       
   434     aEndIncomplete = ETrue;
       
   435     if ( lastChar >= searchDesLastChar )
       
   436         {        
       
   437         lastChar = searchDesLastChar;                    
       
   438         aEndIncomplete = EFalse;
       
   439         }            
       
   440     
       
   441     return aToBeSearchedDes.Mid( 
       
   442         firstChar, 
       
   443         Min( lastChar - firstChar, searchDesLastChar - firstChar ) ).AllocLC();
       
   444     }
       
   445     
       
   446 // ----------------------------------------------------------------------------
       
   447 // CIpsPlgTextSearcher::CreateSnippetLC()
       
   448 // Creates the snippet from the 1st found keyword hit.  8 bit version.
       
   449 // ----------------------------------------------------------------------------
       
   450 //
       
   451 HBufC* CIpsPlgTextSearcher::CreateSnippetLC( 
       
   452     const TDesC8& aToBeSearchedDes, 
       
   453     TInt& aSnippetCharPos,
       
   454     TBool& aStartIncomplete, 
       
   455     TBool& aEndIncomplete )
       
   456     {
       
   457     FUNC_LOG;
       
   458     TInt halfSnippetLen ( iSearchResultRecommendedSnippetLength / 2 );
       
   459     
       
   460     TInt firstChar ( iFirstMatchKeywordCharPos - halfSnippetLen );
       
   461     TInt lastChar ( 
       
   462         iFirstMatchKeywordCharPos + halfSnippetLen - Min( firstChar, 0) );
       
   463     
       
   464     TInt searchDesLastChar ( aToBeSearchedDes.Length() );
       
   465 
       
   466     firstChar = 
       
   467         Max( 0, firstChar - Max( 0, ( lastChar - searchDesLastChar ) ) ) ;    
       
   468     
       
   469     aSnippetCharPos = halfSnippetLen + ( lastChar - searchDesLastChar );
       
   470 
       
   471     aStartIncomplete = ETrue;
       
   472     if ( firstChar <= 0 )
       
   473         {
       
   474         firstChar = 0;
       
   475         aStartIncomplete = EFalse;
       
   476         aSnippetCharPos = iFirstMatchKeywordCharPos;
       
   477         }
       
   478 
       
   479     aEndIncomplete = ETrue;
       
   480     if ( lastChar >= searchDesLastChar )
       
   481         {        
       
   482         lastChar = searchDesLastChar;                    
       
   483         aEndIncomplete = EFalse;
       
   484         }    
       
   485         
       
   486     HBufC8* snippet8 = aToBeSearchedDes.Mid( firstChar, 
       
   487         Min( lastChar - firstChar, searchDesLastChar - firstChar ) ).AllocLC();
       
   488     HBufC* snippet= ConvertToUnicodeL( iRFs, *snippet8, 
       
   489         KCharacterSetIdentifierUtf8 );
       
   490     CleanupStack::PopAndDestroy( snippet8 );
       
   491     CleanupStack::PushL( snippet );
       
   492     return snippet;
       
   493     }
       
   494 
       
   495 // ----------------------------------------------------------------------------
       
   496 // CIpsPlgTextSearcher::ConvertFromUnicodeL()
       
   497 // Makes a conversion from unicode
       
   498 // ----------------------------------------------------------------------------
       
   499 HBufC8* CIpsPlgTextSearcher::ConvertFromUnicodeL(
       
   500     RFs& aFs, 
       
   501     const TDesC16& aUnicodeSource,
       
   502     TUint aTargetEncoding )
       
   503     {
       
   504     FUNC_LOG;
       
   505     CCnvCharacterSetConverter* converter = CCnvCharacterSetConverter::NewLC();
       
   506     if ( converter->PrepareToConvertToOrFromL(aTargetEncoding, aFs) 
       
   507          != CCnvCharacterSetConverter::EAvailable )
       
   508         {
       
   509         User::Leave( KErrNotSupported );
       
   510         }
       
   511 
       
   512     TBuf8<KUnicodeConversionBufferSize> temp8Buffer;
       
   513     HBufC8*     target = NULL;
       
   514     TPtrC       source16Ptr( aUnicodeSource );
       
   515 
       
   516     for( ;; ) // conversion loop
       
   517         {
       
   518         TInt state = CCnvCharacterSetConverter::KStateDefault;
       
   519         TInt returnValue = 
       
   520             converter->ConvertFromUnicode( temp8Buffer, source16Ptr, state );
       
   521         if ( returnValue == CCnvCharacterSetConverter::EErrorIllFormedInput )
       
   522             {
       
   523             User::Leave( KErrCorrupt );
       
   524             }
       
   525         else
       
   526             {
       
   527             if ( returnValue < 0 ) // future-proof against "TError" expanding
       
   528                 {
       
   529                 User::Leave( KErrGeneral );
       
   530                 }
       
   531             }
       
   532 
       
   533         if ( !target )
       
   534             {
       
   535             target = temp8Buffer.AllocLC();
       
   536             }
       
   537         else
       
   538             {
       
   539             HBufC8* tmp = 
       
   540                 target->ReAllocL( target->Length() + temp8Buffer.Length() );
       
   541             CleanupStack::Pop( target );
       
   542             target = tmp;
       
   543             CleanupStack::PushL( target );
       
   544             target->Des().Append( temp8Buffer );
       
   545             }
       
   546 
       
   547         if ( returnValue == 0 ) // All is converted without Errors
       
   548             {
       
   549             break;
       
   550             }
       
   551 
       
   552         // There is "returnValue" bytes not converted yet
       
   553         source16Ptr.Set( source16Ptr.Right( returnValue ) );
       
   554         }
       
   555     CleanupStack::Pop( target );  // Ownership is transferred
       
   556     CleanupStack::PopAndDestroy( converter );
       
   557     return target;
       
   558     }
       
   559 
       
   560 // ----------------------------------------------------------------------------
       
   561 // CIpsPlgTextSearcher::ConvertToUnicodeL()
       
   562 // Makes a conversion into unicode
       
   563 // ----------------------------------------------------------------------------
       
   564 HBufC16* CIpsPlgTextSearcher::ConvertToUnicodeL( 
       
   565     RFs& aFs, 
       
   566     const TDesC8& aSource,
       
   567     TUint aSourceEncoding )
       
   568     {
       
   569     FUNC_LOG;
       
   570     CCnvCharacterSetConverter* converter = CCnvCharacterSetConverter::NewLC();
       
   571     if ( converter->PrepareToConvertToOrFromL( aSourceEncoding, aFs ) 
       
   572          != CCnvCharacterSetConverter::EAvailable )
       
   573         {
       
   574         User::Leave( KErrNotSupported );
       
   575         }
       
   576 
       
   577     TBuf<KUnicodeConversionBufferSize> temp16Buffer;
       
   578     HBufC*  unicode = NULL;
       
   579     TPtrC8  source8Ptr( aSource );
       
   580 
       
   581     for( ;; ) // conversion loop
       
   582         {
       
   583         TInt state = CCnvCharacterSetConverter::KStateDefault;
       
   584 
       
   585         TInt returnValue = 
       
   586             converter->ConvertToUnicode( temp16Buffer, source8Ptr, state );
       
   587         if ( returnValue == CCnvCharacterSetConverter::EErrorIllFormedInput )
       
   588             {
       
   589             User::Leave( KErrCorrupt );
       
   590             }
       
   591         else
       
   592             {
       
   593             if ( returnValue < 0 ) // future-proof against "TError" expanding
       
   594                 {
       
   595                 User::Leave( KErrGeneral );
       
   596                 }
       
   597             }
       
   598 
       
   599         if ( !unicode )
       
   600             {
       
   601             unicode = temp16Buffer.AllocLC();
       
   602             }
       
   603         else
       
   604             {
       
   605             HBufC* tmp = 
       
   606                 unicode->ReAllocL( unicode->Length() + temp16Buffer.Length() );
       
   607             CleanupStack::Pop( unicode );
       
   608             unicode = tmp;
       
   609             CleanupStack::PushL( unicode );
       
   610             unicode->Des().Append( temp16Buffer );
       
   611             }
       
   612 
       
   613         if ( returnValue == 0 ) // All is converted without Errors
       
   614             {
       
   615             break;
       
   616             }
       
   617 
       
   618         // There is "returnValue" bytes not converted yet
       
   619         source8Ptr.Set( source8Ptr.Right( returnValue ) );
       
   620         }
       
   621 
       
   622     CleanupStack::Pop( unicode ); // Ownership is transferred
       
   623     CleanupStack::PopAndDestroy( converter );
       
   624     return unicode;
       
   625     }
       
   626     
       
   627 
       
   628 
       
   629 
       
   630 
       
   631