os/textandloc/charconvfw/charconvplugins/src/shared/SHIFTJIS_SHARED_2.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2000-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:       
    15 *
    16 */
    17 
    18 
    19 #include "PictographObserver.h"
    20 #include "featmgr/featmgr.h"  
    21 
    22 #include <e32std.h>
    23 #include <charconv.h>
    24 #include <convutils.h>
    25 #include "jisx0201.h"
    26 #include "jisx0208.h"
    27 #include "SHIFTJIS_2.H"
    28 #include <convdata.h>
    29 
    30 //const TUint KSingleByteRangeFirstBlockStart=0x00;
    31 const TUint KSingleByteRangeFirstBlockEnd=0x7f;
    32 const TUint KSingleByteRangeSecondBlockStart=0xa1;
    33 const TUint KSingleByteRangeSecondBlockEnd=0xdf;
    34 const TUint KFirstByteRangeFirstBlockStart=0x81;
    35 const TUint KFirstByteRangeFirstBlockEnd=0x9f;
    36 const TUint KFirstByteRangeFirstBlockLength=(KFirstByteRangeFirstBlockEnd+1)-KFirstByteRangeFirstBlockStart;
    37 const TUint KFirstByteRangeSecondBlockStart=0xe0;
    38 // Ken Lunde's book "CJKV Information Processing" (page 176) says this
    39 // constant should be 0xef, but no Shift-JIS characters in
    40 // \charconv\data\JISX0208.TXT have a first byte greater than 0xea, and
    41 // some extensions of Shift-JIS may use the 0xeb-0xef range for the first
    42 // byte of their characters (e.g. "MOPERA"), and in order for users of this
    43 // DLL to be able to implement these extensions using the
    44 // aArrayOfAdditionalXxxxx parameters, this constant therefore needs to
    45 // be set as low as possible, i.e. to 0xea
    46 const TUint KFirstByteRangeSecondBlockEnd=0xea;
    47 const TUint KFirstByteRangeOtherBlockEnd = 0xfc;
    48 
    49 const TUint KPictoFirstByteStart = 0xF0;
    50 const TUint KPictoFirstByteEnd = 0xF9;
    51 
    52 const TUint KSecondByteRangeFirstBlockStart=0x40;
    53 const TUint KSecondByteRangeFirstBlockEnd=0x7e;
    54 const TUint KSecondByteRangeFirstBlockLength=(KSecondByteRangeFirstBlockEnd+1)-KSecondByteRangeFirstBlockStart;
    55 const TUint KSecondByteRangeSecondBlockStart=0x80;
    56 const TUint KSecondByteRangeSecondBlockEnd=0xfc;
    57 
    58 // SecureID for Brower app
    59 const TUint32 KBrowserSecureId = 0x10008D39;
    60 // Define for converting from YenSign to BackSlash
    61 const TUint KCharacterCodeForYenSign = 0x00A5;
    62 const TUint KCharacterCodeForBackSlash = 0x005C;
    63 
    64 TInt BytesInOtherDoubleByteAreas(const TDesC8& aShiftJis);
    65 TInt OneIfNotValid(const TDesC8& aShiftJis);
    66 
    67 TBool IsJisX0208LeadByte(TUint a)
    68     {
    69     return (KFirstByteRangeFirstBlockStart <= a
    70         && a <= KFirstByteRangeFirstBlockEnd)
    71         || (KFirstByteRangeSecondBlockStart <= a
    72         && a <= KFirstByteRangeSecondBlockEnd);
    73     }
    74 
    75 TBool IsValidTrailByte(TUint a)
    76     {
    77     return KSecondByteRangeFirstBlockStart <= a
    78         && a <= KSecondByteRangeSecondBlockEnd
    79         && a != KSecondByteRangeFirstBlockEnd + 1;
    80     }
    81 
    82 TBool IsOtherLeadByte(TUint a)
    83     {
    84     if ( FeatureManager::FeatureSupported(KFeatureIdJapanesePicto) )
    85         {        
    86         return ((KFirstByteRangeSecondBlockEnd < a && a <= KFirstByteRangeOtherBlockEnd)
    87                 && (a < KPictoFirstByteStart || a > KPictoFirstByteEnd));
    88         }
    89     else
    90         {        
    91         return KFirstByteRangeSecondBlockEnd < a
    92                 && a <= KFirstByteRangeOtherBlockEnd;
    93         }
    94     }
    95 
    96 _LIT8(KLit8ShiftJisReplacementForUnconvertibleUnicodeCharacters, "\x81\x48"); // fullwidth question mark
    97 
    98 #if defined(_DEBUG)
    99 
   100 _LIT(KLitPanicText, "SHIFTJIS_SHARED");
   101 
   102 enum TPanic
   103     {
   104     EPanicIndexOverflow1=1,
   105     EPanicIndexOverflow2,
   106     EPanicNothingToConvert1,
   107     EPanicNothingToConvert2,
   108     EPanicOddNumberOfBytes1,
   109     EPanicOddNumberOfBytes2,
   110     EPanicBadPointers1,
   111     EPanicBadPointers2,
   112     EPanicBadPointers3,
   113     EPanicBadPointers4,
   114     EPanicBadPointers5,
   115     EPanicBadPointers6,
   116     EPanicBadPointers7,
   117     EPanicBadPointers8,
   118     EPanicBadPointers9
   119     };
   120 
   121 LOCAL_C void Panic(TPanic aPanic)
   122     {
   123     User::Panic(KLitPanicText, aPanic);
   124     }
   125 
   126 #endif
   127 
   128 // TCombinedArrayOfCharacterSets
   129 
   130 class TCombinedArrayOfCharacterSets
   131     {
   132 public:
   133     TCombinedArrayOfCharacterSets(const TArray<CnvUtilities::SCharacterSet>* aArrayOfAdditionalCharacterSets);
   134     ~TCombinedArrayOfCharacterSets();
   135     TArray<CnvUtilities::SCharacterSet> Array() const;
   136 private:
   137     static TInt CombinedCount(const CBase* aThis);
   138     static const TAny* CombinedAccessor(const CBase* aThis, TInt aIndex);
   139 private:
   140     RArray<CnvUtilities::SCharacterSet> iArrayOfCoreCharacterSets;
   141     const TArray<CnvUtilities::SCharacterSet>* iArrayOfAdditionalCharacterSets;
   142     };
   143 
   144 TCombinedArrayOfCharacterSets::TCombinedArrayOfCharacterSets(const TArray<CnvUtilities::SCharacterSet>* aArrayOfAdditionalCharacterSets)
   145     :iArrayOfAdditionalCharacterSets(aArrayOfAdditionalCharacterSets)
   146     {
   147     if ( FeatureManager::FeatureSupported(KFeatureIdJapanesePicto) )
   148         {      
   149         CnvUtilities::SCharacterSet characterSet;
   150         characterSet.iConversionData=&CnvJisX0201::ConversionData();
   151         characterSet.iConvertFromIntermediateBufferInPlace=CnvShiftJis::DummyConvertFromIntermediateBufferInPlace;
   152         characterSet.iEscapeSequence=&KNullDesC8;
   153         iArrayOfCoreCharacterSets.Append(characterSet);
   154         characterSet.iConversionData=&CnvJisX0208::ConversionData();
   155         characterSet.iConvertFromIntermediateBufferInPlace=CnvShiftJis::ConvertFromJisX0208ToShiftJisInPlace;
   156         characterSet.iEscapeSequence=&KNullDesC8;
   157         iArrayOfCoreCharacterSets.Append(characterSet);
   158 
   159         SetCharacterSetsForPictograph(iArrayOfCoreCharacterSets, ECharsetShiftJis);
   160         }
   161     else
   162         {            
   163         CnvUtilities::SCharacterSet characterSet;
   164         characterSet.iConversionData=&CnvJisX0201::ConversionData();
   165         characterSet.iConvertFromIntermediateBufferInPlace=CnvShiftJis::DummyConvertFromIntermediateBufferInPlace;
   166         characterSet.iEscapeSequence=&KNullDesC8;
   167         iArrayOfCoreCharacterSets.Append(characterSet);
   168         characterSet.iConversionData=&CnvJisX0208::ConversionData();
   169         characterSet.iConvertFromIntermediateBufferInPlace=CnvShiftJis::ConvertFromJisX0208ToShiftJisInPlace;
   170         characterSet.iEscapeSequence=&KNullDesC8;
   171         iArrayOfCoreCharacterSets.Append(characterSet);
   172         }
   173     }
   174 
   175 TCombinedArrayOfCharacterSets::~TCombinedArrayOfCharacterSets()
   176     {
   177     iArrayOfCoreCharacterSets.Close();
   178     }
   179 
   180 
   181 TArray<CnvUtilities::SCharacterSet> TCombinedArrayOfCharacterSets::Array() const
   182     {
   183     return TArray<CnvUtilities::SCharacterSet>(CombinedCount, CombinedAccessor, REINTERPRET_CAST(const CBase*, this));
   184     }
   185 
   186 TInt TCombinedArrayOfCharacterSets::CombinedCount(const CBase* aThis)
   187     {
   188     const TCombinedArrayOfCharacterSets& thisReference=*REINTERPRET_CAST(const TCombinedArrayOfCharacterSets*, aThis);
   189     const TInt numberOfCoreCharacterSets=thisReference.iArrayOfCoreCharacterSets.Count();
   190     if (thisReference.iArrayOfAdditionalCharacterSets!=NULL)
   191         {
   192         return numberOfCoreCharacterSets+thisReference.iArrayOfAdditionalCharacterSets->Count();
   193         }
   194     return numberOfCoreCharacterSets;
   195     }
   196 
   197 const TAny* TCombinedArrayOfCharacterSets::CombinedAccessor(const CBase* aThis, TInt aIndex)
   198     {
   199     const TCombinedArrayOfCharacterSets& thisReference=*REINTERPRET_CAST(const TCombinedArrayOfCharacterSets*, aThis);
   200     const TInt numberOfCoreCharacterSets=thisReference.iArrayOfCoreCharacterSets.Count();
   201     if (aIndex>=numberOfCoreCharacterSets)
   202         {
   203         __ASSERT_DEBUG(thisReference.iArrayOfAdditionalCharacterSets!=NULL, Panic(EPanicIndexOverflow1));
   204         return &(*thisReference.iArrayOfAdditionalCharacterSets)[aIndex-numberOfCoreCharacterSets];
   205         }
   206     return &thisReference.iArrayOfCoreCharacterSets[aIndex];
   207     }
   208 
   209 // TCombinedArrayOfMethods
   210 
   211 class TCombinedArrayOfMethods
   212     {
   213 public:
   214     TCombinedArrayOfMethods(const TArray<CnvUtilities::SMethod>* aArrayOfAdditionalMethods);
   215     ~TCombinedArrayOfMethods();
   216     TArray<CnvUtilities::SMethod> Array() const;
   217 private:
   218     static TInt CombinedCount(const CBase* aThis);
   219     static const TAny* CombinedAccessor(const CBase* aThis, TInt aIndex);
   220 private:
   221     RArray<CnvUtilities::SMethod> iArrayOfCoreMethods;
   222     const TArray<CnvUtilities::SMethod>* iArrayOfAdditionalMethods;
   223     };
   224 
   225 TCombinedArrayOfMethods::TCombinedArrayOfMethods(const TArray<CnvUtilities::SMethod>* aArrayOfAdditionalMethods)
   226     :iArrayOfAdditionalMethods(aArrayOfAdditionalMethods)
   227     {
   228     if ( FeatureManager::FeatureSupported(KFeatureIdJapanesePicto) )
   229         {      
   230         SetMethodsForPictograph(iArrayOfCoreMethods, ECharsetShiftJis);
   231         CnvUtilities::SMethod method;
   232         method.iNumberOfBytesAbleToConvert=CnvShiftJis::NumberOfBytesAbleToConvertToJisX0201;
   233         method.iConvertToIntermediateBufferInPlace=CnvShiftJis::DummyConvertToIntermediateBufferInPlace;
   234         method.iConversionData=&CnvJisX0201::ConversionData();
   235         method.iNumberOfBytesPerCharacter=1;
   236         method.iNumberOfCoreBytesPerCharacter=1;
   237         iArrayOfCoreMethods.Append(method);
   238         method.iNumberOfBytesAbleToConvert=CnvShiftJis::NumberOfBytesAbleToConvertToJisX0208;
   239         method.iConvertToIntermediateBufferInPlace=CnvShiftJis::ConvertToJisX0208FromShiftJisInPlace;
   240         method.iConversionData=&CnvJisX0208::ConversionData();
   241         method.iNumberOfBytesPerCharacter=2;
   242         method.iNumberOfCoreBytesPerCharacter=2;
   243         iArrayOfCoreMethods.Append(method);
   244         }
   245     else
   246         {        
   247         CnvUtilities::SMethod method;
   248         method.iNumberOfBytesAbleToConvert=CnvShiftJis::NumberOfBytesAbleToConvertToJisX0201;
   249         method.iConvertToIntermediateBufferInPlace=CnvShiftJis::DummyConvertToIntermediateBufferInPlace;
   250         method.iConversionData=&CnvJisX0201::ConversionData();
   251         method.iNumberOfBytesPerCharacter=1;
   252         method.iNumberOfCoreBytesPerCharacter=1;
   253         iArrayOfCoreMethods.Append(method);
   254         method.iNumberOfBytesAbleToConvert=CnvShiftJis::NumberOfBytesAbleToConvertToJisX0208;
   255         method.iConvertToIntermediateBufferInPlace=CnvShiftJis::ConvertToJisX0208FromShiftJisInPlace;
   256         method.iConversionData=&CnvJisX0208::ConversionData();
   257         method.iNumberOfBytesPerCharacter=2;
   258         method.iNumberOfCoreBytesPerCharacter=2;
   259         iArrayOfCoreMethods.Append(method);    
   260         }
   261     }
   262 
   263 TCombinedArrayOfMethods::~TCombinedArrayOfMethods()
   264     {
   265     iArrayOfCoreMethods.Close();
   266     }
   267 
   268 
   269 TArray<CnvUtilities::SMethod> TCombinedArrayOfMethods::Array() const
   270     {
   271     return TArray<CnvUtilities::SMethod>(CombinedCount, CombinedAccessor, REINTERPRET_CAST(const CBase*, this));
   272     }
   273 
   274 TInt TCombinedArrayOfMethods::CombinedCount(const CBase* aThis)
   275     {
   276     const TCombinedArrayOfMethods& thisReference=*REINTERPRET_CAST(const TCombinedArrayOfMethods*, aThis);
   277     const TInt numberOfCoreMethods=thisReference.iArrayOfCoreMethods.Count();
   278     if (thisReference.iArrayOfAdditionalMethods!=NULL)
   279         {
   280         return numberOfCoreMethods+thisReference.iArrayOfAdditionalMethods->Count();
   281         }
   282     return numberOfCoreMethods;
   283     }
   284 
   285 const TAny* TCombinedArrayOfMethods::CombinedAccessor(const CBase* aThis, TInt aIndex)
   286     {
   287     const TCombinedArrayOfMethods& thisReference=*REINTERPRET_CAST(const TCombinedArrayOfMethods*, aThis);
   288     const TInt numberOfCoreMethods=thisReference.iArrayOfCoreMethods.Count();
   289     if (aIndex>=numberOfCoreMethods)
   290         {
   291         __ASSERT_DEBUG(thisReference.iArrayOfAdditionalMethods!=NULL, Panic(EPanicIndexOverflow2));
   292         return &(*thisReference.iArrayOfAdditionalMethods)[aIndex-numberOfCoreMethods];
   293         }
   294     return &thisReference.iArrayOfCoreMethods[aIndex];
   295     }
   296 
   297 // CnvShiftJis
   298 
   299 EXPORT_C const TDesC8& CnvShiftJis::ReplacementForUnconvertibleUnicodeCharacters()
   300     {
   301     return KLit8ShiftJisReplacementForUnconvertibleUnicodeCharacters;
   302     }
   303 
   304 EXPORT_C TInt CnvShiftJis::ConvertFromUnicode(CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, const TDesC8& aReplacementForUnconvertibleUnicodeCharacters, TDes8& aForeign, const TDesC16& aUnicode, CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters)
   305     {
   306     return DoConvertFromUnicode(aDefaultEndiannessOfForeignCharacters, aReplacementForUnconvertibleUnicodeCharacters, aForeign, aUnicode, aIndicesOfUnconvertibleCharacters, NULL);
   307     }
   308 
   309 /**
   310  * Converts text from Unicode to Shift-JIS (aArrayOfAdditionalCharacterSets provides support
   311  * for Shift-JIS extensions)
   312  *
   313  * @since Internationalization_6.2
   314  */
   315 EXPORT_C TInt CnvShiftJis::ConvertFromUnicode(CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, const TDesC8& aReplacementForUnconvertibleUnicodeCharacters, TDes8& aForeign, const TDesC16& aUnicode, CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters, const TArray<CnvUtilities::SCharacterSet>& aArrayOfAdditionalCharacterSets)
   316     {
   317     return DoConvertFromUnicode(aDefaultEndiannessOfForeignCharacters, aReplacementForUnconvertibleUnicodeCharacters, aForeign, aUnicode, aIndicesOfUnconvertibleCharacters, &aArrayOfAdditionalCharacterSets);
   318     }
   319 
   320 EXPORT_C TInt CnvShiftJis::ConvertToUnicode(
   321     CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
   322     TDes16& aUnicode, const TDesC8& aForeign,
   323     TInt& aNumberOfUnconvertibleCharacters,
   324     TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter)
   325     {
   326     // DummyData converts any pair of bytes into FFFD
   327     static const SCnvConversionData::SVariableByteData::SRange
   328         DummyByteLengths = {0, 255, 1, 0};
   329     static const SCnvConversionData::SOneDirectionData::SRange DummyConv =
   330         { 0xFFFD, 0xFFFD,
   331         SCnvConversionData::SOneDirectionData::SRange::EDirect, 2, 0 };
   332     static const SCnvConversionData DummyData =
   333         {
   334         SCnvConversionData::EFixedBigEndian,
   335         {1, &DummyByteLengths},
   336         {1, &DummyConv},
   337         {1, &DummyConv}
   338         };
   339     TFixedArray<CnvUtilities::SMethod, 2> nullExtension;
   340     // First extension converts unrecognised double byte characters to FFFD
   341     nullExtension[0].iNumberOfBytesAbleToConvert
   342         = BytesInOtherDoubleByteAreas;
   343     nullExtension[0].iConvertToIntermediateBufferInPlace
   344         = CnvShiftJis::DummyConvertToIntermediateBufferInPlace;
   345     // This conversion data won't do anything for us: it will just get us
   346     // a load of FFFD, which is what we want.
   347     nullExtension[0].iConversionData = &DummyData;
   348     nullExtension[0].iNumberOfBytesPerCharacter = 2;
   349     nullExtension[0].iNumberOfCoreBytesPerCharacter = 2;
   350     // Second extension converts any other single byte to FFFD,
   351     // but only ever one!
   352     nullExtension[1].iNumberOfBytesAbleToConvert
   353         = OneIfNotValid;
   354     nullExtension[1].iConvertToIntermediateBufferInPlace
   355         = CnvShiftJis::DummyConvertToIntermediateBufferInPlace;
   356     // This conversion data won't do anything for us: it will just get us
   357     // a load of FFFD, which is what we want.
   358     nullExtension[1].iConversionData = &CnvJisX0201::ConversionData();
   359     nullExtension[1].iNumberOfBytesPerCharacter = 1;
   360     nullExtension[1].iNumberOfCoreBytesPerCharacter = 1;
   361     const TArray<CnvUtilities::SMethod> nullExtensionArray = nullExtension.Array();
   362     return DoConvertToUnicode(aDefaultEndiannessOfForeignCharacters,
   363         aUnicode, aForeign, aNumberOfUnconvertibleCharacters,
   364         aIndexOfFirstByteOfFirstUnconvertibleCharacter,
   365         &nullExtensionArray);
   366     }
   367 
   368 /**
   369  * Converts text from Shift-JIS to Unicode (aArrayOfAdditionalMethods provides support
   370  * for Shift-JIS extensions)
   371  *
   372  * @since Internationalization_6.2
   373  */
   374 EXPORT_C TInt CnvShiftJis::ConvertToUnicode(CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, TDes16& aUnicode, const TDesC8& aForeign, TInt& aNumberOfUnconvertibleCharacters, TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter, const TArray<CnvUtilities::SMethod>& aArrayOfAdditionalMethods)
   375     {
   376     return DoConvertToUnicode(aDefaultEndiannessOfForeignCharacters, aUnicode, aForeign, aNumberOfUnconvertibleCharacters, aIndexOfFirstByteOfFirstUnconvertibleCharacter, &aArrayOfAdditionalMethods);
   377     }
   378 
   379 TInt CnvShiftJis::DoConvertFromUnicode(
   380     CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
   381     const TDesC8& aReplacementForUnconvertibleUnicodeCharacters,
   382     TDes8& aForeign, const TDesC16& aUnicode,
   383     CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters,
   384     const TArray<CnvUtilities::SCharacterSet>* aArrayOfAdditionalCharacterSets)
   385     {
   386     TCombinedArrayOfCharacterSets combinedArrayOfCharacterSets(aArrayOfAdditionalCharacterSets);
   387     return CnvUtilities::ConvertFromUnicode(aDefaultEndiannessOfForeignCharacters, aReplacementForUnconvertibleUnicodeCharacters, aForeign, aUnicode, aIndicesOfUnconvertibleCharacters, combinedArrayOfCharacterSets.Array());
   388     }
   389 
   390 TInt CnvShiftJis::DoConvertToUnicode(
   391     CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
   392     TDes16& aUnicode, const TDesC8& aForeign,
   393     TInt& aNumberOfUnconvertibleCharacters,
   394     TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter,
   395     const TArray<CnvUtilities::SMethod>* aArrayOfAdditionalMethods)
   396     {
   397     TCombinedArrayOfMethods combinedArrayOfMethods(aArrayOfAdditionalMethods);
   398     TInt unconvert = CnvUtilities::ConvertToUnicodeFromHeterogeneousForeign(
   399         aDefaultEndiannessOfForeignCharacters, aUnicode, aForeign,
   400         aNumberOfUnconvertibleCharacters,
   401         aIndexOfFirstByteOfFirstUnconvertibleCharacter,
   402         combinedArrayOfMethods.Array());
   403 
   404     // The following is specific impelementation for brower.
   405     // If brower app calls this API, the yen sign code(0xA5)
   406     // must be converted to backslash code(0x5C).
   407     // Becasue Javascript supports backslash code ony.
   408     TBool browserProcess = (RProcess().SecureId().iId == KBrowserSecureId);
   409     if (browserProcess && aUnicode.Length() > 0)
   410         {
   411         const TUint16* pB = aUnicode.Ptr();
   412         const TUint16* pbase = pB;
   413         const TUint16* pE = pB + aUnicode.Length() -1;
   414         while (pE>=pbase)
   415             {
   416             if (*pbase == KCharacterCodeForYenSign)
   417                 {
   418                 aUnicode[pbase - pB] = KCharacterCodeForBackSlash;
   419                 }
   420             pbase++;
   421             }
   422         }
   423 
   424     return unconvert;
   425     }
   426 
   427 void CnvShiftJis::DummyConvertFromIntermediateBufferInPlace(TInt, TDes8&, TInt& aNumberOfCharactersThatDroppedOut)
   428     {
   429     aNumberOfCharactersThatDroppedOut=0;
   430     }
   431 
   432 void CnvShiftJis::ConvertFromJisX0208ToShiftJisInPlace(TInt aStartPositionInDescriptor, TDes8& aDescriptor, TInt& aNumberOfCharactersThatDroppedOut)
   433     {
   434     aNumberOfCharactersThatDroppedOut=0;
   435     const TInt descriptorLength=aDescriptor.Length();
   436     __ASSERT_DEBUG(descriptorLength>aStartPositionInDescriptor, Panic(EPanicNothingToConvert1));
   437     __ASSERT_DEBUG((descriptorLength-aStartPositionInDescriptor)%2==0, Panic(EPanicOddNumberOfBytes1));
   438     TUint8* pointerToCurrentByte=CONST_CAST(TUint8*, aDescriptor.Ptr());
   439     const TUint8* const pointerToLastByte=pointerToCurrentByte+(descriptorLength-1);
   440     pointerToCurrentByte+=aStartPositionInDescriptor;
   441     FOREVER
   442         {
   443         TUint firstByte=*pointerToCurrentByte-0x21;
   444         TUint secondByte=*(pointerToCurrentByte+1)-0x21;
   445         if (firstByte%2!=0)
   446             {
   447             secondByte+=94;
   448             }
   449         firstByte/=2;
   450         if (firstByte<KFirstByteRangeFirstBlockLength)
   451             {
   452             firstByte+=KFirstByteRangeFirstBlockStart;
   453             }
   454         else
   455             {
   456             firstByte+=KFirstByteRangeSecondBlockStart-KFirstByteRangeFirstBlockLength;
   457             }
   458         if (secondByte<KSecondByteRangeFirstBlockLength)
   459             {
   460             secondByte+=KSecondByteRangeFirstBlockStart;
   461             }
   462         else
   463             {
   464             secondByte+=KSecondByteRangeSecondBlockStart-KSecondByteRangeFirstBlockLength;
   465             }
   466         *pointerToCurrentByte=STATIC_CAST(TUint8, firstByte);
   467         ++pointerToCurrentByte;
   468         *pointerToCurrentByte=STATIC_CAST(TUint8, secondByte);
   469         __ASSERT_DEBUG(pointerToCurrentByte<=pointerToLastByte, Panic(EPanicBadPointers1));
   470         if (pointerToCurrentByte>=pointerToLastByte)
   471             {
   472             break;
   473             }
   474         ++pointerToCurrentByte;
   475         }
   476     }
   477 
   478 TInt CnvShiftJis::NumberOfBytesAbleToConvertToJisX0201(const TDesC8& aDescriptor)
   479     {
   480     const TUint8* pointerToPreviousByte=aDescriptor.Ptr()-1;
   481     const TUint8* const pointerToLastByte=pointerToPreviousByte+aDescriptor.Length();
   482     if (pointerToPreviousByte==pointerToLastByte)
   483         {
   484         return 0;
   485         }
   486     FOREVER
   487         {
   488         __ASSERT_DEBUG(pointerToPreviousByte<pointerToLastByte, Panic(EPanicBadPointers2));
   489         const TUint currentByte=*(pointerToPreviousByte+1);
   490         if (((currentByte>KSingleByteRangeFirstBlockEnd) && (currentByte<KSingleByteRangeSecondBlockStart)) ||
   491             (currentByte>KSingleByteRangeSecondBlockEnd))
   492             {
   493             break;
   494             }
   495         __ASSERT_DEBUG(pointerToPreviousByte<pointerToLastByte, Panic(EPanicBadPointers3));
   496         ++pointerToPreviousByte;
   497         __ASSERT_DEBUG(pointerToPreviousByte<=pointerToLastByte, Panic(EPanicBadPointers4));
   498         if (pointerToPreviousByte>=pointerToLastByte)
   499             {
   500             break;
   501             }
   502         }
   503     return (pointerToPreviousByte+1)-aDescriptor.Ptr();
   504     }
   505 
   506 TInt CnvShiftJis::NumberOfBytesAbleToConvertToJisX0208(const TDesC8& aDescriptor)
   507     {
   508     const TUint8* pointerToPreviousByte=aDescriptor.Ptr()-1;
   509     const TUint8* const pointerToLastByte=pointerToPreviousByte+aDescriptor.Length();
   510     if (pointerToPreviousByte==pointerToLastByte)
   511         {
   512         return 0;
   513         }
   514     FOREVER
   515         {
   516         __ASSERT_DEBUG(pointerToPreviousByte<pointerToLastByte, Panic(EPanicBadPointers5));
   517         TUint currentByte=*(pointerToPreviousByte+1);
   518         if (!IsJisX0208LeadByte(currentByte))
   519             {
   520             if (!IsOtherLeadByte(currentByte))
   521                 {
   522                 break;
   523                 }
   524             }
   525         __ASSERT_DEBUG(pointerToPreviousByte<pointerToLastByte, Panic(EPanicBadPointers6));
   526         if (pointerToPreviousByte+1>=pointerToLastByte)
   527             {
   528             break;
   529             }
   530         __ASSERT_DEBUG(pointerToPreviousByte+2<=pointerToLastByte, Panic(EPanicBadPointers7));
   531         currentByte=*(pointerToPreviousByte+2);
   532         if (!IsValidTrailByte(currentByte))
   533             {
   534             break;
   535             }
   536         pointerToPreviousByte+=2;
   537         __ASSERT_DEBUG(pointerToPreviousByte<=pointerToLastByte, Panic(EPanicBadPointers8));
   538         if (pointerToPreviousByte>=pointerToLastByte)
   539             {
   540             break;
   541             }
   542         }
   543     return (pointerToPreviousByte+1)-aDescriptor.Ptr();
   544     }
   545 
   546 void CnvShiftJis::DummyConvertToIntermediateBufferInPlace(TDes8&)
   547     {
   548     }
   549 
   550 void CnvShiftJis::ConvertToJisX0208FromShiftJisInPlace(TDes8& aDescriptor)
   551     {
   552     const TInt descriptorLength=aDescriptor.Length();
   553     __ASSERT_DEBUG(descriptorLength>0, Panic(EPanicNothingToConvert2));
   554     __ASSERT_DEBUG(descriptorLength%2==0, Panic(EPanicOddNumberOfBytes2));
   555     TUint8* pointerToCurrentByte=CONST_CAST(TUint8*, aDescriptor.Ptr());
   556     const TUint8* const pointerToLastByte=pointerToCurrentByte+(descriptorLength-1);
   557     FOREVER
   558         {
   559         TUint firstByte=*pointerToCurrentByte;
   560         TUint secondByte=*(pointerToCurrentByte+1);
   561         if (firstByte<KFirstByteRangeSecondBlockStart)
   562             {
   563             firstByte-=KFirstByteRangeFirstBlockStart;
   564             }
   565         else
   566             {
   567             firstByte-=KFirstByteRangeSecondBlockStart-KFirstByteRangeFirstBlockLength;
   568             }
   569         if (secondByte<KSecondByteRangeSecondBlockStart)
   570             {
   571             secondByte-=KSecondByteRangeFirstBlockStart;
   572             }
   573         else
   574             {
   575             secondByte-=KSecondByteRangeSecondBlockStart-KSecondByteRangeFirstBlockLength;
   576             }
   577         firstByte*=2;
   578         if (secondByte>=94)
   579             {
   580             ++firstByte;
   581             secondByte-=94;
   582             }
   583         firstByte+=0x21;
   584         secondByte+=0x21;
   585         *pointerToCurrentByte=STATIC_CAST(TUint8, firstByte);
   586         ++pointerToCurrentByte;
   587         *pointerToCurrentByte=STATIC_CAST(TUint8, secondByte);
   588         __ASSERT_DEBUG(pointerToCurrentByte<=pointerToLastByte, Panic(EPanicBadPointers9));
   589         if (pointerToCurrentByte>=pointerToLastByte)
   590             {
   591             break;
   592             }
   593         ++pointerToCurrentByte;
   594         }
   595     }
   596 
   597 TInt BytesInOtherDoubleByteAreas(const TDesC8& aShiftJis)
   598     {
   599     const TText8* start = aShiftJis.Ptr();
   600     const TText8* end = start + aShiftJis.Length() - 1;
   601     const TText8* p = start;
   602     while (p < end && IsOtherLeadByte(p[0]) && IsValidTrailByte(p[1]))
   603         p += 2;
   604     return p - start;
   605     }
   606 
   607 TInt OneIfNotValid(const TDesC8& aShiftJis)
   608     {
   609     TInt length = aShiftJis.Length();
   610     if (length == 0)
   611         return 0;
   612     TInt c = aShiftJis[0];
   613     // If the next byte is not a lead byte, we can swallow it. The
   614     // double-byte methods obviously can't be waiting for more
   615     // information.
   616     if (!IsOtherLeadByte(c) && !IsJisX0208LeadByte(c))
   617         return 1;
   618     // Otherwise we have a lead byte. If it is on its own we cannot
   619     // swallow it as the double-byte converters will be waiting for
   620     // more information. If they have the information (i.e. if length > 1)
   621     // then they have passed on it and we can swallow it.
   622     return length == 1? 0 : 1;
   623     }